"use client";

import { useCallback, useState } from "react";

import { api } from "@/lib/api/client";
import { useToast } from "@/components/Toast";
import {
  extractIngestConflicts,
  generationErrorMessage,
  type IngestConflicts,
} from "@/lib/generation/cards";
import { mapPreview, type PreviewModel } from "./toolbox";
import { buildIngestRequest, type IngestBuildInput } from "./ingest";
import type { ToolGenerateRequest } from "@/lib/api/types";

export type GenStatus = "idle" | "generating" | "preview" | "error";
export type IngestStatus = "idle" | "ingesting" | "conflict" | "done" | "error";

export interface UseGenerator {
  genStatus: GenStatus;
  preview: PreviewModel | null;
  // 原始结构化产物（供入库按选中下标形变；与 preview.items 同源对齐）。
  rawPreview: Record<string, unknown> | undefined;
  outputKind: string | null;
  ingestStatus: IngestStatus;
  // 409 冲突详情（待作者裁决）；裁决后带 acknowledge 重发。
  conflicts: IngestConflicts | null;
  created: string[];
  generate: (
    projectId: string,
    toolKey: string,
    body: ToolGenerateRequest,
  ) => Promise<void>;
  // 入库选中行；acknowledge 用于过 409（已查看冲突后重发）。
  ingest: (
    projectId: string,
    toolKey: string,
    input: IngestBuildInput,
  ) => Promise<boolean>;
  reset: () => void;
}

// 通用生成器状态机（idle→generating→preview）+ 入库 409 裁决流，仿 useCharacterGen。
// 声明驱动：generate/ingest 不感知具体工具，按 tool_key + descriptor 形变后调通用端点。
export function useGenerator(): UseGenerator {
  const [genStatus, setGenStatus] = useState<GenStatus>("idle");
  const [preview, setPreview] = useState<PreviewModel | null>(null);
  const [rawPreview, setRawPreview] = useState<
    Record<string, unknown> | undefined
  >(undefined);
  const [outputKind, setOutputKind] = useState<string | null>(null);
  const [ingestStatus, setIngestStatus] = useState<IngestStatus>("idle");
  const [conflicts, setConflicts] = useState<IngestConflicts | null>(null);
  const [created, setCreated] = useState<string[]>([]);
  const toast = useToast();

  const generate = useCallback<UseGenerator["generate"]>(
    async (projectId, toolKey, body) => {
      setGenStatus("generating");
      setPreview(null);
      setRawPreview(undefined);
      setOutputKind(null);
      setConflicts(null);
      setIngestStatus("idle");
      setCreated([]);
      try {
        const { data, error } = await api.POST(
          "/projects/{project_id}/skills/{tool_key}/generate",
          {
            params: { path: { project_id: projectId, tool_key: toolKey } },
            body,
          },
        );
        if (error || !data) {
          setGenStatus("error");
          toast(generationErrorMessage(error), "error");
          return;
        }
        setPreview(mapPreview(data.output_kind, data.preview));
        setRawPreview(data.preview);
        setOutputKind(data.output_kind);
        setGenStatus("preview");
      } catch {
        setGenStatus("error");
        toast("生成请求异常，请检查网络。", "error");
      }
    },
    [toast],
  );

  const ingest = useCallback<UseGenerator["ingest"]>(
    async (projectId, toolKey, input) => {
      const body = buildIngestRequest(input);
      if (!body) {
        toast("该生成器不支持入库。", "error");
        return false;
      }
      if (input.rows.length === 0) {
        toast("请至少选择一项入库。", "error");
        return false;
      }
      setIngestStatus("ingesting");
      try {
        const { data, error } = await api.POST(
          "/projects/{project_id}/skills/{tool_key}/ingest",
          {
            params: { path: { project_id: projectId, tool_key: toolKey } },
            body,
          },
        );
        if (error || !data) {
          const conflict = extractIngestConflicts(error);
          if (conflict) {
            // 409 CONFLICT_UNRESOLVED：展示冲突让作者裁决，再带 acknowledge 重发。
            setConflicts(conflict);
            setIngestStatus("conflict");
            return false;
          }
          setIngestStatus("error");
          toast(generationErrorMessage(error), "error");
          return false;
        }
        setCreated(data.created ?? []);
        setConflicts(null);
        setIngestStatus("done");
        toast(`已入库 ${data.created?.length ?? 0} 项至 ${data.table}`, "success");
        if (data.rejected_tables && data.rejected_tables.length > 0) {
          toast(`越权写表被丢弃：${data.rejected_tables.join("、")}`, "info");
        }
        return true;
      } catch {
        setIngestStatus("error");
        toast("入库请求异常，请检查网络。", "error");
        return false;
      }
    },
    [toast],
  );

  const reset = useCallback((): void => {
    setGenStatus("idle");
    setPreview(null);
    setRawPreview(undefined);
    setOutputKind(null);
    setIngestStatus("idle");
    setConflicts(null);
    setCreated([]);
  }, []);

  return {
    genStatus,
    preview,
    rawPreview,
    outputKind,
    ingestStatus,
    conflicts,
    created,
    generate,
    ingest,
    reset,
  };
}
