import type { ToolHandler, ToolResult } from "./types";

interface SearxResult {
  title?: string;
  url?: string;
  content?: string;
}

interface SearxResponse {
  results?: SearxResult[];
}

export const searchWeb: ToolHandler = async (args, ctx): Promise<ToolResult> => {
  const query = typeof args.requete === "string" ? args.requete.trim() : "";
  const requested = Number(args.nb_resultats);
  const n = Math.min(10, Math.max(1, Number.isFinite(requested) ? requested : 5));

  if (!query) return { content: "Requête vide.", error: "empty_query" };

  const base = (ctx.searxngUrl || "http://localhost:8888").replace(/\/+$/, "");
  const url = `${base}/search?q=${encodeURIComponent(query)}&format=json`;

  try {
    const res = await fetch(url, {
      headers: { Accept: "application/json" },
      signal: AbortSignal.timeout(15_000),
    });
    if (!res.ok) {
      return {
        content: `SearXNG a renvoyé une erreur ${res.status}. Vérifie que l'instance tourne et que le format JSON est activé dans settings.yml.`,
        error: `http_${res.status}`,
      };
    }
    const data = (await res.json()) as SearxResponse;
    const results = (data.results ?? []).slice(0, n);
    if (results.length === 0) return { content: `Aucun résultat pour "${query}".` };

    const text = results
      .map((r, i) => {
        const title = (r.title ?? "Sans titre").trim();
        const ur = (r.url ?? "").trim();
        const snippet = (r.content ?? "").replace(/\s+/g, " ").trim().slice(0, 300);
        return `[${i + 1}] ${title}\nURL: ${ur}\nSnippet : ${snippet}`;
      })
      .join("\n\n");
    return {
      content: text,
      meta: { query, count: results.length, urls: results.map((r) => r.url).filter(Boolean) },
    };
  } catch (e) {
    return {
      content: `Erreur lors de la requête à SearXNG : ${e instanceof Error ? e.message : "inconnue"}`,
      error: "fetch_error",
    };
  }
};
