export type RagToolContext = {
  userId: string;
};

type RagFetchResult =
  | { ok: true; status: number; data: unknown }
  | { ok: false; status: number; error: string; data?: unknown };

const readEnv = (key: string) => {
  try {
    const v = process.env[key];
    return typeof v === "string" ? v.trim() : "";
  } catch {
    return "";
  }
};

const safeJoinUrl = (base: string, path: string) => {
  const b = String(base || "").trim().replace(/\/+$/, "");
  const p = String(path || "").trim().replace(/^\/+/, "");
  if (!b) return `/${p}`;
  return `${b}/${p}`;
};

const fetchJson = async (url: string, init: RequestInit, timeoutMs: number): Promise<RagFetchResult> => {
  const ms = Math.max(500, Math.min(60_000, Math.floor(timeoutMs || 0) || 20_000));
  const controller = new AbortController();
  const t = setTimeout(() => controller.abort(), ms);
  try {
    const res = await fetch(url, { ...init, signal: controller.signal });
    const data = (await res.json().catch(() => null)) as unknown;
    if (!res.ok) {
      const detail =
        typeof data === "object" && data && "detail" in (data as any) ? String((data as any).detail ?? "") : "";
      const msg = detail || `HTTP ${res.status}`;
      return { ok: false, status: res.status, error: msg, data };
    }
    return { ok: true, status: res.status, data };
  } catch (e) {
    const msg = e instanceof Error ? e.message : String(e);
    return { ok: false, status: 0, error: msg };
  } finally {
    clearTimeout(t);
  }
};

export const createRagServerTools = (args: {
  ctx: RagToolContext;
  allowedToolIds: Set<string>;
}) => {
  const run = async (toolId: string, toolArgs: Record<string, unknown>) => {
    if (!args.allowedToolIds.has(toolId)) {
      throw new Error(`工具未被允许：${toolId}`);
    }

    if (toolId === "rag_lightrag_query") {
      const query = String(toolArgs.query ?? "").trim();
      if (!query) throw new Error("缺少 query");
      if (query.length < 2) throw new Error("query 太短（至少 2 个字符）");

      const modeRaw = String(toolArgs.mode ?? "mix").trim();
      const mode =
        modeRaw === "local" ||
        modeRaw === "global" ||
        modeRaw === "hybrid" ||
        modeRaw === "naive" ||
        modeRaw === "mix" ||
        modeRaw === "bypass"
          ? modeRaw
          : "mix";

      const topKRaw = Number(toolArgs.topK ?? toolArgs.top_k ?? 12);
      const topK = Math.max(1, Math.min(60, Number.isFinite(topKRaw) ? Math.floor(topKRaw) : 12));

      const chunkTopKRaw = Number(toolArgs.chunkTopK ?? toolArgs.chunk_top_k ?? topK);
      const chunkTopK = Math.max(1, Math.min(120, Number.isFinite(chunkTopKRaw) ? Math.floor(chunkTopKRaw) : topK));

      const includeReferences = toolArgs.includeReferences !== false;
      const includeChunkContent = Boolean(toolArgs.includeChunkContent ?? true);
      const onlyNeedContext = Boolean(toolArgs.onlyNeedContext ?? false);
      const responseType = String(toolArgs.responseType ?? "").trim() || undefined;

      const baseUrl = readEnv("LIGHTRAG_URL");
      if (!baseUrl) throw new Error("缺少环境变量：LIGHTRAG_URL");
      const apiKey = readEnv("LIGHTRAG_API_KEY");

      const url = safeJoinUrl(baseUrl, "/query");
      const payload = {
        query,
        mode,
        top_k: topK,
        chunk_top_k: chunkTopK,
        include_references: includeReferences,
        include_chunk_content: includeChunkContent,
        only_need_context: onlyNeedContext,
        ...(responseType ? { response_type: responseType } : {}),
      };

      const r = await fetchJson(
        url,
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json; charset=utf-8",
            ...(apiKey ? { "X-API-Key": apiKey } : {}),
          },
          body: JSON.stringify(payload),
        },
        35_000,
      );

      if (!r.ok) {
        throw new Error(`LightRAG 查询失败：${r.error}`);
      }
      return { ok: true, provider: "lightrag", query, mode, result: r.data };
    }

    throw new Error(`未知工具：${toolId}`);
  };

  return { run };
};

