"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Database, Sparkles } from "lucide-react";

import { ThinkingIndicator } from "@/components/ThinkingIndicator";
import { Button } from "@/components/ui/Button";
import { Field } from "@/components/ui/Field";
import { SectionHeader } from "@/components/ui/SectionHeader";
import { SegmentedControl } from "@/components/ui/SegmentedControl";
import { StatusNote } from "@/components/ui/StatusNote";
import { TextInput } from "@/components/ui/TextInput";
import type { CharacterCardView } from "@/lib/api/types";
import {
  clampCharacterCount,
  MAX_CHARACTER_COUNT,
  MIN_CHARACTER_COUNT,
  roleMixTotal,
  sanitizeRoleMix,
  updateCard,
} from "@/lib/generation/cards";
import { useCharacterGen } from "@/lib/generation/useCharacterGen";
import { CharacterCardItem } from "./CharacterCardItem";
import { ConflictAdjudication } from "./ConflictAdjudication";
import { RoleMixEditor, type RoleMixRow } from "./RoleMixEditor";

type GenMode = "single" | "mix";

const MODE_OPTIONS: Array<{ value: GenMode; label: string }> = [
  { value: "single", label: "单一定位" },
  { value: "mix", label: "按定位配比" },
];

const DEFAULT_MIX_ROWS: RoleMixRow[] = [
  { role: "主角", count: 1 },
  { role: "对手", count: 1 },
];

interface CharacterGeneratorProps {
  projectId: string;
  // 入库成功后回调（如刷新 Codex 本地列表）。
  onIngested?: (created: string[], cards: CharacterCardView[]) => void;
}

// 角色生成器（UX §6.6）：一句话需求 + 数量 + 定位 → 预览卡 → 选/改 → 入库（处理 409 裁决）。
export function CharacterGenerator({
  projectId,
  onIngested,
}: CharacterGeneratorProps) {
  const gen = useCharacterGen();
  const [brief, setBrief] = useState("");
  const [count, setCount] = useState(MIN_CHARACTER_COUNT);
  const [role, setRole] = useState("");
  const [mode, setMode] = useState<GenMode>("single");
  const [mixRows, setMixRows] = useState<RoleMixRow[]>(DEFAULT_MIX_ROWS);
  // 配比模式下的有效合计（sanitize 后，已按 MAX 截断）——门控生成按钮。
  const mixTotal = roleMixTotal(sanitizeRoleMix(mixRows));
  // 编辑态卡片（预览返回后拷贝进本地，允许就地改）。
  const [drafts, setDrafts] = useState<CharacterCardView[]>([]);
  const [selected, setSelected] = useState<Set<number>>(new Set());

  // 预览返回 → 同步进本地编辑态 + 默认全选。
  const syncDrafts = useCallback((cards: CharacterCardView[]) => {
    setDrafts(cards);
    setSelected(new Set(cards.map((_, i) => i)));
  }, []);

  const onGenerate = useCallback(async () => {
    if (mode === "mix") {
      await gen.generate({
        projectId,
        brief,
        count,
        roleMix: sanitizeRoleMix(mixRows),
      });
      return;
    }
    await gen.generate({ projectId, brief, count, role });
  }, [gen, projectId, brief, count, role, mode, mixRows]);

  // gen.cards 变化（新预览）→ 重新同步本地草稿。
  const previewKey = gen.cards.map((c) => c.name).join("|");
  useEffect(() => {
    if (gen.genStatus === "preview") syncDrafts(gen.cards);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [previewKey, gen.genStatus]);

  const toggle = (i: number): void => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(i)) next.delete(i);
      else next.add(i);
      return next;
    });
  };

  const selectedCards = useMemo(
    () => drafts.filter((_, i) => selected.has(i)),
    [drafts, selected],
  );

  const doIngest = useCallback(
    async (acknowledge: boolean) => {
      const ok = await gen.ingest(projectId, selectedCards, acknowledge);
      if (ok) {
        onIngested?.(gen.created, selectedCards);
        setDrafts([]);
        setSelected(new Set());
      }
    },
    [gen, projectId, selectedCards, onIngested],
  );

  const generating = gen.genStatus === "generating";
  const ingesting = gen.ingestStatus === "ingesting";

  return (
    <section className="flex flex-col gap-4" aria-label="角色生成器">
      <div className="rounded border border-line bg-panel p-4">
        <SectionHeader title="角色生成器" className="mb-3" />
        <Field label="一句话需求" className="mb-3">
          <TextInput
            value={brief}
            onChange={(e) => setBrief(e.target.value)}
            placeholder="如：一个亦正亦邪的剑修，背负灭门血仇"
          />
        </Field>
        <div className="mb-3">
          <SegmentedControl
            options={MODE_OPTIONS}
            value={mode}
            onChange={setMode}
            ariaLabel="生成模式"
          />
        </div>

        {mode === "mix" ? (
          <Field
            label="角色定位配比"
            className="mb-3"
            help="每个定位产出对应数量，合计即总张数"
          >
            <RoleMixEditor rows={mixRows} onChange={setMixRows} />
          </Field>
        ) : (
          <div className="mb-3 flex flex-wrap items-end gap-3">
            <Field
              label="数量"
              className="w-28"
              help={`${MIN_CHARACTER_COUNT}–${MAX_CHARACTER_COUNT} 张`}
            >
              <TextInput
                type="number"
                min={MIN_CHARACTER_COUNT}
                max={MAX_CHARACTER_COUNT}
                value={count}
                onChange={(e) =>
                  setCount(clampCharacterCount(Number(e.target.value)))
                }
              />
            </Field>
            <Field label="定位（可选）" className="min-w-[12rem] flex-1">
              <TextInput
                value={role}
                onChange={(e) => setRole(e.target.value)}
                placeholder="主角 / CP / 对手 / 导师 / 工具人"
              />
            </Field>
          </div>
        )}

        <Button
          onClick={() => void onGenerate()}
          loading={generating}
          disabled={
            brief.trim().length === 0 ||
            (mode === "mix"
              ? mixTotal < MIN_CHARACTER_COUNT
              : count < MIN_CHARACTER_COUNT || count > MAX_CHARACTER_COUNT)
          }
          variant="primary"
        >
          <Sparkles className="h-4 w-4" aria-hidden="true" />
          生成
        </Button>
      </div>

      {generating ? (
        <div className="rounded border border-line bg-panel/50 p-4 text-cinnabar">
          <ThinkingIndicator label="生成中" />
        </div>
      ) : null}

      {gen.genStatus === "preview" && drafts.length > 0 ? (
        <div className="flex flex-col gap-3">
          <p className="text-xs text-ink-soft">
            已生成 {drafts.length} 张，选 {selectedCards.length} 张入库（可就地编辑名/弧光）。
          </p>
          <div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
            {drafts.map((card, i) => (
              <CharacterCardItem
                key={i}
                card={card}
                selected={selected.has(i)}
                onToggle={() => toggle(i)}
                onEdit={(patch) =>
                  setDrafts((prev) =>
                    prev.map((c, j) => (j === i ? updateCard(c, patch) : c)),
                  )
                }
              />
            ))}
          </div>

          {gen.ingestStatus === "conflict" && gen.conflicts ? (
            <ConflictAdjudication
              conflicts={gen.conflicts}
              busy={ingesting}
              onAcknowledge={() => void doIngest(true)}
              onCancel={() => gen.reset()}
            />
          ) : (
            <Button
              onClick={() => void doIngest(false)}
              disabled={ingesting || selectedCards.length === 0}
              variant="primary"
            >
              <Database className="h-4 w-4" aria-hidden="true" />
              {ingesting ? "入库中…" : `入库选中 ${selectedCards.length} 张`}
            </Button>
          )}
        </div>
      ) : null}

      {gen.ingestStatus === "done" && gen.created.length > 0 ? (
        <StatusNote variant="success">已入库：{gen.created.join("、")}</StatusNote>
      ) : null}
    </section>
  );
}
