type SupabaseRouteClient = {
  from: (table: string) => any;
};

export type SlashSupabaseClient = SupabaseRouteClient;

export type SlashToolContext = {
  userId: string;
  // 可选：在 document scope 下提供，便于默认继承 workspace_id / parent_id
  currentDocumentId?: string;
};

const isRecord = (v: unknown): v is Record<string, unknown> =>
  typeof v === "object" && v !== null && !Array.isArray(v);

const pick = (obj: unknown, key: string) => (isRecord(obj) ? obj[key] : undefined);

const loadWorkspaceIds = async (supabase: SlashSupabaseClient, userId: string) => {
  const { data, error } = await supabase
    .from("workspace_members")
    .select("workspace_id")
    .eq("user_id", userId);
  if (error) {
    throw new Error(isRecord(error) && typeof error.message === "string" ? error.message : "读取工作区失败");
  }
  const rows = Array.isArray(data) ? data : [];
  return rows.map((r) => String((r as any)?.workspace_id ?? "")).filter(Boolean);
};

const inferWorkspaceIdFromDoc = async (supabase: SlashSupabaseClient, documentId: string) => {
  const { data, error } = await supabase.from("documents").select("workspace_id").eq("id", documentId).single();
  if (error) return null;
  const wid = String(pick(data, "workspace_id") ?? "").trim();
  return wid || null;
};

type ParsedSlash =
  | { ok: true; command: "new_doc"; params: { title: string; parentId?: string | null; workspaceId?: string | null } }
  | { ok: true; command: "rename_doc"; params: { documentId: string; title: string } }
  | { ok: false; error: string };

const parseSlash = (text: string): ParsedSlash => {
  const raw = String(text || "").trim();
  if (!raw.startsWith("/")) return { ok: false, error: "不是斜杠命令（必须以 / 开头）" };
  const parts = raw.split(/\s+/).filter(Boolean);
  const cmd = parts[0] ?? "";
  const rest = raw.slice(cmd.length).trim();

  if (cmd === "/new" || cmd === "/new-doc" || cmd === "/newdoc") {
    const title = rest.trim();
    if (!title) return { ok: false, error: "用法：/new <标题>" };
    return { ok: true, command: "new_doc", params: { title } };
  }

  if (cmd === "/rename" || cmd === "/rename-doc" || cmd === "/renamedoc") {
    const documentId = String(parts[1] ?? "").trim();
    const title = raw.split(/\s+/).slice(2).join(" ").trim();
    if (!documentId || !title) return { ok: false, error: "用法：/rename <documentId> <新标题>" };
    return { ok: true, command: "rename_doc", params: { documentId, title } };
  }

  return { ok: false, error: `未知命令：${cmd}` };
};

export const createSlashServerTools = (args: {
  supabase?: SlashSupabaseClient;
  ctx: SlashToolContext;
  allowedToolIds: Set<string>;
  // 说明：Convex 迁移阶段用于“去 Supabase 化”。如果提供该能力，则完全不依赖 Supabase。
  loadWorkspaceIds?: (userId: string) => Promise<string[]>;
  inferWorkspaceIdFromDoc?: (documentId: string) => Promise<string | null>;
  createDoc?: (args: { userId: string; workspaceId: string; parentId: string | null; title: string }) => Promise<{
    id: string;
    title: string;
    workspaceId: string;
    parentId: string | null;
    createdAt: unknown;
    updatedAt: unknown;
  }>;
  renameDoc?: (args: { userId: string; documentId: string; title: string }) => Promise<{
    id: string;
    title: string;
    workspaceId: string;
    parentId: string | null;
    updatedAt: unknown;
  }>;
}) => {
  const executeSlashTransport = async (parsed: ParsedSlash) => {
    if (!args.allowedToolIds.has("slash_run")) throw new Error("工具未被允许：slash_run");
    if (!parsed.ok) {
      throw new Error("error" in parsed ? parsed.error : "缺少 text（以 / 开头）或 command");
    }

    if (parsed.command === "new_doc") {
      const title = String(parsed.params.title ?? "").trim();
      if (!title) throw new Error("缺少标题");
      const parentId = parsed.params.parentId ? String(parsed.params.parentId) : null;
      const workspaceIdFromParams = parsed.params.workspaceId ? String(parsed.params.workspaceId) : null;
      const workspaceId =
        workspaceIdFromParams ||
        (args.ctx.currentDocumentId
          ? args.inferWorkspaceIdFromDoc
            ? await args.inferWorkspaceIdFromDoc(args.ctx.currentDocumentId)
            : args.supabase
              ? await inferWorkspaceIdFromDoc(args.supabase, args.ctx.currentDocumentId)
              : null
          : null) ||
        ((args.loadWorkspaceIds
          ? (await args.loadWorkspaceIds(args.ctx.userId))[0]
          : args.supabase
            ? (await loadWorkspaceIds(args.supabase, args.ctx.userId))[0]
            : null) ?? null) ||
        null;
      if (!workspaceId) throw new Error("无法推断 workspaceId（请在 params.workspaceId 指定）");

      if (args.createDoc) {
        const doc = await args.createDoc({
          userId: args.ctx.userId,
          workspaceId,
          parentId,
          title,
        });
        return { ok: true, command: "new_doc", document: doc };
      }

      if (!args.supabase) {
        throw new Error("缺少 Supabase 数据源（请在 Convex 模式下传入 createDoc/renameDoc）");
      }

      const payload = {
        workspace_id: workspaceId,
        user_id: args.ctx.userId,
        parent_id: parentId,
        title,
        content: [] as unknown[],
        raw_text: "",
      };
      const { data, error } = await args.supabase.from("documents").insert(payload).select("id,workspace_id,parent_id,title,created_at,updated_at").single();
      if (error) {
        throw new Error(isRecord(error) && typeof error.message === "string" ? error.message : "创建文档失败");
      }
      return {
        ok: true,
        command: "new_doc",
        document: {
          id: String(pick(data, "id") ?? ""),
          title: String(pick(data, "title") ?? ""),
          workspaceId: String(pick(data, "workspace_id") ?? ""),
          parentId: pick(data, "parent_id") ? String(pick(data, "parent_id")) : null,
          createdAt: pick(data, "created_at") ?? null,
          updatedAt: pick(data, "updated_at") ?? null,
        },
      };
    }

    if (parsed.command === "rename_doc") {
      const documentId = String(parsed.params.documentId ?? "").trim();
      const title = String(parsed.params.title ?? "").trim();
      if (!documentId || !title) throw new Error("缺少 documentId 或 title");

      if (args.renameDoc) {
        const doc = await args.renameDoc({ userId: args.ctx.userId, documentId, title });
        return { ok: true, command: "rename_doc", document: doc };
      }

      if (!args.supabase) {
        throw new Error("缺少 Supabase 数据源（请在 Convex 模式下传入 createDoc/renameDoc）");
      }

      const { data, error } = await args.supabase
        .from("documents")
        .update({ title })
        .eq("id", documentId)
        .select("id,workspace_id,parent_id,title,updated_at")
        .single();
      if (error) {
        throw new Error(isRecord(error) && typeof error.message === "string" ? error.message : "重命名失败");
      }
      return {
        ok: true,
        command: "rename_doc",
        document: {
          id: String(pick(data, "id") ?? ""),
          title: String(pick(data, "title") ?? ""),
          workspaceId: String(pick(data, "workspace_id") ?? ""),
          parentId: pick(data, "parent_id") ? String(pick(data, "parent_id")) : null,
          updatedAt: pick(data, "updated_at") ?? null,
        },
      };
    }

    throw new Error(`未实现命令：${(parsed as any).command}`);
  };

  return { parseSlash, executeSlashTransport };
};
