"use client";

import { CheckCircle2, CircleDashed, Flag, Plus } from "lucide-react";
import { useEffect, useState } from "react";

import { api } from "@/lib/api/client";
import { Badge } from "@/components/ui/Badge";
import { Button } from "@/components/ui/Button";
import { Field } from "@/components/ui/Field";
import { TextArea } from "@/components/ui/TextArea";
import { TextInput } from "@/components/ui/TextInput";
import {
  nextFreeForeshadowCode,
  suggestForeshadowCode,
} from "@/lib/foreshadow/board";
import { useForeshadow } from "@/lib/foreshadow/useForeshadow";
import type { ForeshadowSuggestion } from "@/lib/review/sse";

interface ForeshadowSuggestionsProps {
  suggestions: ForeshadowSuggestion[];
  // 审项是否未完成（incomplete）。
  incomplete: boolean;
  projectId: string;
  chapterNo: number;
  // 把「仍待处理（未登记/未回收）」的建议数上抛给报告页：
  // 喂 AcceptPanel 的验收预览与伏笔分区徽标，随登记/回收操作实时递减。
  onRemainingChange?: (count: number) => void;
}

interface RegisterFormState {
  code: string;
  title: string;
  plantedAt: number;
  content: string;
}

// 伏笔建议区（UX §6.4 ②）：planted「新埋待确认」/ resolved「疑似回收」。
// 四审只读（不变量#3），但作者可在此**显式确认**：新埋→登记（POST），疑似回收→标记回收（PATCH→CLOSED）。
// 这是作者确认动作，非 AI 静默写库；复用伏笔看板端点（lib/foreshadow）。
export function ForeshadowSuggestions({
  suggestions,
  incomplete,
  projectId,
  chapterNo,
  onRemainingChange,
}: ForeshadowSuggestionsProps) {
  const fs = useForeshadow([]);
  const [openIdx, setOpenIdx] = useState<number | null>(null);
  const [form, setForm] = useState<RegisterFormState | null>(null);
  const [registered, setRegistered] = useState<Set<number>>(new Set());
  const [resolved, setResolved] = useState<Set<number>>(new Set());
  const [pending, setPending] = useState<Set<number>>(new Set());
  // 项目已存在的伏笔（用于隐藏「之前会话就已保存过」的建议）：
  // savedTitles = 已登记伏笔的标题；savedClosedCodes = 已 CLOSED（已回收）的 code。
  const [savedTitles, setSavedTitles] = useState<Set<string>>(new Set());
  const [savedClosedCodes, setSavedClosedCodes] = useState<Set<string>>(
    new Set(),
  );
  // 看板已占用的全部代号——预填登记代号时跳过它们，避免撞码 422。
  const [savedCodes, setSavedCodes] = useState<Set<string>>(new Set());

  useEffect(() => {
    let active = true;
    void (async () => {
      const { data } = await api.GET("/projects/{project_id}/foreshadow", {
        params: { path: { project_id: projectId } },
      });
      if (!active || !data?.foreshadow) return;
      setSavedTitles(new Set(data.foreshadow.map((f) => f.title.trim())));
      setSavedClosedCodes(
        new Set(
          data.foreshadow
            .filter((f) => f.status === "CLOSED")
            .map((f) => f.code),
        ),
      );
      setSavedCodes(
        new Set(data.foreshadow.map((f) => f.code).filter((c) => c)),
      );
    })();
    return () => {
      active = false;
    };
  }, [projectId]);

  // 该建议是否「已保存过」→ 从列表隐藏：
  // - 本次会话已登记/回收（registered/resolved）
  // - 新埋建议：标题已存在于看板（之前已登记）
  // - 疑似回收建议：对应 code 已 CLOSED（之前已回收）
  const isAlreadySaved = (s: ForeshadowSuggestion, i: number): boolean => {
    if (s.kind === "resolved") {
      return resolved.has(i) || (s.code ? savedClosedCodes.has(s.code) : false);
    }
    return registered.has(i) || savedTitles.has(s.title.trim());
  };

  const openRegister = (i: number, s: ForeshadowSuggestion): void => {
    setOpenIdx(i);
    setForm({
      code: nextFreeForeshadowCode(suggestForeshadowCode(s.code, i), savedCodes),
      title: s.title,
      plantedAt: chapterNo,
      content: s.note ?? s.where ?? "",
    });
  };

  const closeForm = (): void => {
    setOpenIdx(null);
    setForm(null);
  };

  const markPending = (i: number, on: boolean): void =>
    setPending((prev) => {
      const next = new Set(prev);
      if (on) next.add(i);
      else next.delete(i);
      return next;
    });

  const submitRegister = async (i: number): Promise<void> => {
    if (!form || !form.code.trim() || !form.title.trim()) return;
    markPending(i, true);
    const ok = await fs.register({
      projectId,
      code: form.code,
      title: form.title,
      plantedAt: form.plantedAt,
      content: form.content,
    });
    markPending(i, false);
    if (ok) {
      setRegistered((prev) => new Set(prev).add(i));
      // 并入已存集合：连续登记时下一条不再取到同一空闲码，且该标题立即隐藏。
      setSavedCodes((prev) => new Set(prev).add(form.code));
      setSavedTitles((prev) => new Set(prev).add(form.title.trim()));
      closeForm();
    }
  };

  const markResolved = async (i: number, code: string): Promise<void> => {
    markPending(i, true);
    const ok = await fs.transition(code, { projectId, toStatus: "CLOSED" });
    markPending(i, false);
    if (ok) setResolved((prev) => new Set(prev).add(i));
  };

  // 保留原始下标 i（registered/resolved/pending/openIdx 均按 i 索引），仅过滤已保存项。
  const visible = suggestions
    .map((s, i) => ({ s, i }))
    .filter(({ s, i }) => !isAlreadySaved(s, i));

  // 上抛「仍待处理」建议数（已登记/已回收/历史已存的都已从 visible 过滤），
  // 让报告页的验收预览与伏笔徽标随作者操作递减（父传入稳定 setter）。
  const remaining = visible.length;
  useEffect(() => {
    onRemainingChange?.(remaining);
  }, [remaining, onRemainingChange]);

  return (
    <section>
      {incomplete ? (
        <Badge variant="warning">
          <CircleDashed className="h-3 w-3" aria-hidden="true" />
          未完成
        </Badge>
      ) : visible.length === 0 ? (
        <p className="text-xs text-ink-soft">无伏笔建议。</p>
      ) : (
        <ul className="space-y-2">
          {visible.map(({ s, i }) => {
            const code = s.code;
            const isResolved = s.kind === "resolved";
            const busy = pending.has(i);
            return (
              <li
                key={i}
                className="rounded border border-line bg-panel p-2 text-xs"
              >
                <Badge variant={isResolved ? "success" : "accent"}>
                  {isResolved ? (
                    <Flag className="h-3 w-3" aria-hidden="true" />
                  ) : (
                    <Plus className="h-3 w-3" aria-hidden="true" />
                  )}
                  {isResolved ? "疑似回收" : "新埋待确认"}
                </Badge>
                {code ? (
                  <span className="font-mono text-ink-soft"> {code}</span>
                ) : null}
                <p className="mt-1 text-ink">{s.title}</p>
                {s.where ? (
                  <span className="text-ink-soft">{s.where}</span>
                ) : null}
                {s.note ? <p className="mt-0.5 text-ink-soft">{s.note}</p> : null}

                {/* 作者确认动作区（已保存的建议已从列表过滤，故无需「已登记」态） */}
                {isResolved ? (
                  code ? (
                    <Button
                      disabled={busy}
                      onClick={() => void markResolved(i, code)}
                      className="mt-1.5"
                      variant="secondary"
                      size="sm"
                    >
                      <CheckCircle2 className="h-4 w-4" aria-hidden="true" />
                      {busy ? "处理中…" : "标记回收"}
                    </Button>
                  ) : (
                    <p className="mt-1.5 text-ink-soft">
                      未关联编码，去伏笔看板处理。
                    </p>
                  )
                ) : openIdx === i && form ? (
                  <RegisterFormInline
                    form={form}
                    busy={busy}
                    onChange={setForm}
                    onSubmit={() => void submitRegister(i)}
                    onCancel={closeForm}
                  />
                ) : (
                  <Button
                    onClick={() => openRegister(i, s)}
                    className="mt-1.5"
                    variant="outline"
                    size="sm"
                  >
                    <Plus className="h-4 w-4" aria-hidden="true" />
                    登记此伏笔
                  </Button>
                )}
              </li>
            );
          })}
        </ul>
      )}
    </section>
  );
}

interface RegisterFormInlineProps {
  form: RegisterFormState;
  busy: boolean;
  onChange: (form: RegisterFormState) => void;
  onSubmit: () => void;
  onCancel: () => void;
}

// 新埋伏笔登记表单：预填标题/埋设章/线索，code 给建议值可改（code/title 必填）。
function RegisterFormInline({
  form,
  busy,
  onChange,
  onSubmit,
  onCancel,
}: RegisterFormInlineProps) {
  const canSubmit =
    !busy && form.code.trim().length > 0 && form.title.trim().length > 0;
  return (
    <div className="mt-2 space-y-1.5 border-t border-line pt-2">
      <Field label="编码" htmlFor="fs-reg-code">
        <TextInput
          id="fs-reg-code"
          type="text"
          value={form.code}
          onChange={(e) => onChange({ ...form, code: e.target.value })}
          controlSize="sm"
        />
      </Field>
      <Field label="标题" htmlFor="fs-reg-title">
        <TextInput
          id="fs-reg-title"
          type="text"
          value={form.title}
          onChange={(e) => onChange({ ...form, title: e.target.value })}
          controlSize="sm"
        />
      </Field>
      <Field label="埋设章号" htmlFor="fs-reg-planted">
        <TextInput
          id="fs-reg-planted"
          type="number"
          min={1}
          value={form.plantedAt}
          onChange={(e) =>
            onChange({ ...form, plantedAt: Number(e.target.value) || 1 })
          }
          controlSize="sm"
        />
      </Field>
      <Field label="线索/正文（可选）" htmlFor="fs-reg-content">
        <TextArea
          id="fs-reg-content"
          value={form.content}
          onChange={(e) => onChange({ ...form, content: e.target.value })}
          rows={2}
          controlSize="sm"
        />
      </Field>
      <div className="flex gap-2 pt-0.5">
        <Button
          disabled={!canSubmit}
          onClick={onSubmit}
          variant="primary"
          size="sm"
        >
          <CheckCircle2 className="h-4 w-4" aria-hidden="true" />
          {busy ? "登记中…" : "确认登记"}
        </Button>
        <Button
          disabled={busy}
          onClick={onCancel}
          variant="secondary"
          size="sm"
        >
          取消
        </Button>
      </div>
    </div>
  );
}
