'use client';

import { useState, useMemo } from 'react';
import { X, CheckCircle2, AlertTriangle, HelpCircle, ListChecks } from 'lucide-react';
import type { VersionPlan } from '@/lib/version-plan';
import type { VersionWithContext } from '@/lib/derive';
import { useDevTaskStore } from '@/stores/useDevTaskStore';
import { useTestCaseStore } from '@/stores/useTestCaseStore';
import { useTaskCategoryStore } from '@/stores/useTaskCategoryStore';
import { useAuthStore } from '@/stores/useAuthStore';
import { findCategoryByCode, resolveAiTaskCategoryByName, type CategoryGroup } from '@/lib/task-category';
import { clampDevAiEstimateHours, clampTestCaseAiEstimateHours } from '@/lib/ai-estimation-policy';
import { resolveDecomposeDraftRequirementFields } from '@/lib/ai-decompose-adoption';
import { formatReportRequirementLabel } from '@/lib/ai-decompose-report';
import { resolveRecommendedAssignee } from '@/lib/ai-assignee-recommendation';
import type {
  AgentDecomposeTarget,
  AgentDecomposeResponse,
  AgentDevTaskDraft,
  AgentTestCaseDraft,
} from '@ftb/shared';

interface Props {
  result: AgentDecomposeResponse;
  version: VersionWithContext;
  plan: VersionPlan;
  requirements: Array<{ id: string; code: string; title: string; description?: string }>;
  target: AgentDecomposeTarget;
  dedupeSummary?: { removedDevTaskCount: number; removedTestCaseCount: number };
  onClose: () => void;
  onAdopted?: () => void;
  onRejected?: () => void;
}

export function DecomposeReportModal({
  result,
  version,
  plan,
  requirements,
  target,
  dedupeSummary,
  onClose,
  onAdopted,
  onRejected,
}: Props) {
  const { createTask } = useDevTaskStore();
  const { createTestCase } = useTestCaseStore();
  const { categories, ensureCategory } = useTaskCategoryStore();
  const user = useAuthStore((s) => s.user);

  const { result: data, meta } = result;
  const showDevDrafts = target !== 'test_cases';
  const showTestDrafts = target !== 'dev_tasks';
  const filteredDuplicateCount =
    (dedupeSummary?.removedDevTaskCount ?? 0) + (dedupeSummary?.removedTestCaseCount ?? 0);
  const prototypeOnlyGroups = data.report.prototypeOnly ?? [];

  const [selectedDevIdx, setSelectedDevIdx] = useState<Set<number>>(
    new Set(showDevDrafts ? data.devTaskDrafts.map((_, i) => i) : []),
  );
  const [selectedTcIdx, setSelectedTcIdx] = useState<Set<number>>(
    new Set(showTestDrafts ? data.testCaseDrafts.map((_, i) => i) : []),
  );
  const [useRecommendedAssignees, setUseRecommendedAssignees] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [submitted, setSubmitted] = useState(false);

  const reqByCode = useMemo(() => {
    const m = new Map<string, { id: string; code: string; title: string }>();
    for (const r of requirements) m.set(r.code, r);
    return m;
  }, [requirements]);

  const reqByInternalId = useMemo(() => {
    const m = new Map<string, { id: string; code: string; title: string }>();
    for (const r of requirements) m.set(r.id, r);
    return m;
  }, [requirements]);

  const toggleDev = (i: number) => {
    const n = new Set(selectedDevIdx);
    if (n.has(i)) n.delete(i);
    else n.add(i);
    setSelectedDevIdx(n);
  };
  const toggleTc = (i: number) => {
    const n = new Set(selectedTcIdx);
    if (n.has(i)) n.delete(i);
    else n.add(i);
    setSelectedTcIdx(n);
  };

  const resolveDraftTaskTypeName = (
    draft: AgentDevTaskDraft | AgentTestCaseDraft,
    fallbackGroup: Extract<CategoryGroup, 'development' | 'testing'>,
  ) => {
    const explicitName = draft.taskTypeName?.trim();
    if (explicitName) return explicitName;
    const mappedName = findCategoryByCode(categories, draft.categoryCode)?.name;
    if (mappedName) return mappedName;
    if (draft.categoryCode) return draft.categoryCode;
    return fallbackGroup === 'testing' ? '功能测试' : '开发任务';
  };

  const resolveDraftCategoryName = (
    draft: AgentDevTaskDraft | AgentTestCaseDraft,
    fallbackGroup: Extract<CategoryGroup, 'development' | 'testing'>,
  ) =>
    resolveAiTaskCategoryByName(categories, resolveDraftTaskTypeName(draft, fallbackGroup), fallbackGroup, {
      allowCreate: fallbackGroup !== 'testing',
      fallbackCode: draft.categoryCode,
    }).category.name;

  const handleAdopt = () => {
    if (submitting) return;
    setSubmitting(true);
    const now = new Date().toISOString();

    // 把每个 reference 的 requirement 类型 id（AI 给的是 code）映射回内部 id
    const normalizeRefs = (refs: AgentDevTaskDraft['references'] | AgentTestCaseDraft['references']) =>
      refs.map((ref) => {
        if (ref.type === 'requirement') {
          const r = reqByCode.get(ref.id) ?? reqByInternalId.get(ref.id);
          if (r) return { ...ref, id: r.id, label: ref.label || `${r.code} ${r.title}` };
        }
        return ref;
      });

    if (showDevDrafts) {
      for (let i = 0; i < data.devTaskDrafts.length; i++) {
        if (!selectedDevIdx.has(i)) continue;
        const draft = data.devTaskDrafts[i];
        const refs = normalizeRefs(draft.references);
        const requirementFields = resolveDecomposeDraftRequirementFields({ ...draft, references: refs }, requirements);
        const taskTypeName = resolveDraftTaskTypeName(draft, 'development');
        const categoryId = ensureCategory(taskTypeName, 'development', { fallbackCode: draft.categoryCode }).id;
        const aiEstimateHours = clampDevAiEstimateHours(draft.categoryCode, draft.aiEstimateHours);
        const recommendedAssignee = resolveRecommendedAssignee(draft, version.members ?? []);

        createTask({
          versionId: version.id,
          requirementId: requirementFields.requirementId,
          requirementName: requirementFields.requirementName,
          title: draft.title,
          description: draft.description,
          categoryId,
          assigneeId: useRecommendedAssignees ? recommendedAssignee?.name ?? '' : '',
          reviewerId: undefined,
          priority: draft.priority,
          expectedStartAt: '',
          expectedEndAt: '',
          estimateHours: undefined,
          aiEstimateHours,
          actualStartAt: undefined,
          actualEndAt: undefined,
          status: 'todo',
          blockReason: undefined,
          blockedById: undefined,
          predecessorIds: undefined,
          riskLevel: undefined,
          delayReason: undefined,
          overdueVersionReason: undefined,
          references: refs,
          aiDraft: true,
          aiDraftAt: now,
          createdBy: user?.name || 'AI',
        } as any);
      }
    }

    if (showTestDrafts) {
      for (let i = 0; i < data.testCaseDrafts.length; i++) {
        if (!selectedTcIdx.has(i)) continue;
        const draft = data.testCaseDrafts[i];
        const refs = normalizeRefs(draft.references);
        const requirementFields = resolveDecomposeDraftRequirementFields({ ...draft, references: refs }, requirements);
        const taskTypeName = resolveDraftTaskTypeName(draft, 'testing');
        const categoryId = ensureCategory(taskTypeName, 'testing', {
          allowCreate: false,
          fallbackCode: draft.categoryCode,
        }).id;
        const aiEstimateHours = clampTestCaseAiEstimateHours(draft.categoryCode, draft.aiEstimateHours);
        const recommendedAssignee = resolveRecommendedAssignee(draft, version.members ?? []);

        createTestCase({
          versionId: version.id,
          requirementId: requirementFields.requirementId || undefined,
          requirementName: requirementFields.requirementName,
          title: draft.title,
          description: draft.description,
          categoryId,
          priority: draft.priority,
          estimateHours: undefined,
          aiEstimateHours,
          assigneeId: useRecommendedAssignees ? recommendedAssignee?.name : undefined,
          references: refs,
          aiDraft: true,
          aiDraftAt: now,
          createdBy: user?.name || 'AI',
        } as any);
      }
    }

    setSubmitted(true);
    setSubmitting(false);

    // 1.5 秒后自动关闭
    setTimeout(() => {
      onAdopted?.();
      onClose();
    }, 1500);
  };

  const visibleRecommendationCount = useMemo(() => {
    const members = version.members ?? [];
    const devCount = showDevDrafts
      ? data.devTaskDrafts.filter((draft) => resolveRecommendedAssignee(draft, members)).length
      : 0;
    const testCount = showTestDrafts
      ? data.testCaseDrafts.filter((draft) => resolveRecommendedAssignee(draft, members)).length
      : 0;
    return devCount + testCount;
  }, [data.devTaskDrafts, data.testCaseDrafts, showDevDrafts, showTestDrafts, version.members]);

  const selectedVisibleCount = (showDevDrafts ? selectedDevIdx.size : 0) + (showTestDrafts ? selectedTcIdx.size : 0);

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40" onClick={onClose}>
      <div
        className="w-full max-w-3xl max-h-[85vh] flex flex-col rounded-2xl bg-[var(--bg-card)] border border-[var(--line)] shadow-2xl"
        onClick={(e) => e.stopPropagation()}
      >
        {/* Header */}
        <div className="flex items-center justify-between px-5 py-4 border-b border-[var(--line)]">
          <div className="flex items-center gap-2">
            <ListChecks className="h-4 w-4 text-purple-600" />
            <h3 className="text-[14px] font-semibold text-[var(--ink)]">AI 拆解结果</h3>
            <span className="text-[11px] text-[var(--ink-muted)]">
              {meta.model} · 输入 {meta.inputTokens} tok · 输出 {meta.outputTokens} tok ·{' '}
              {(meta.durationMs / 1000).toFixed(1)}s
            </span>
          </div>
          <button onClick={onClose} className="p-1 rounded hover:bg-[var(--bg-subtle)]">
            <X className="h-4 w-4 text-[var(--ink-muted)]" />
          </button>
        </div>

        {/* Body */}
        <div className="flex-1 overflow-y-auto px-5 py-4 space-y-4">
          {filteredDuplicateCount > 0 && (
            <div className="rounded-lg border border-purple-200 bg-purple-50 px-3 py-2 text-[12px] text-purple-700">
              已自动过滤 {dedupeSummary?.removedDevTaskCount ?? 0} 个重复开发任务、{dedupeSummary?.removedTestCaseCount ?? 0} 个重复测试用例。
            </div>
          )}

          {/* 对账报告 */}
          <section>
            <h4 className="text-[12px] font-semibold text-[var(--ink-soft)] mb-2">对账报告</h4>

            {data.report.matched.length > 0 && (
              <div className="rounded-lg border border-emerald-200 bg-emerald-50 p-3 mb-2">
                <div className="flex items-center gap-1.5 mb-1.5">
                  <CheckCircle2 className="h-3.5 w-3.5 text-emerald-600" />
                  <span className="text-[12px] font-medium text-emerald-700">
                    完美对应（{data.report.matched.length}）
                  </span>
                </div>
                <ul className="text-[12px] text-emerald-800 space-y-1 ml-5">
                  {data.report.matched.map((m, i) => (
                    <li key={i} className="flex flex-wrap items-center gap-1">
                      <span
                        className="max-w-[280px] truncate font-medium"
                        title={formatReportRequirementLabel(m.reqId, requirements)}
                      >
                        {formatReportRequirementLabel(m.reqId, requirements)}
                      </span>
                      <span>↔ {m.noteIds.join(', ') || '(仅需求驱动)'} → 拆出 {m.taskCount} 个任务</span>
                    </li>
                  ))}
                </ul>
              </div>
            )}

            {data.report.reqOnly.length > 0 && (
              <div className="rounded-lg border border-amber-200 bg-amber-50 p-3 mb-2">
                <div className="flex items-center gap-1.5 mb-1.5">
                  <AlertTriangle className="h-3.5 w-3.5 text-amber-600" />
                  <span className="text-[12px] font-medium text-amber-700">仅需求未见原型</span>
                </div>
                <p className="text-[11px] text-amber-700 mb-1">
                  以下需求在原型上未找到对应批注，已按需求文字拆解，请人工核对：
                </p>
                <ul className="text-[12px] text-amber-800 ml-5 list-disc">
                  {data.report.reqOnly.map((id, i) => {
                    const label = formatReportRequirementLabel(id, requirements);
                    return <li key={i} className="max-w-[360px] truncate" title={label}>{label}</li>;
                  })}
                </ul>
              </div>
            )}

            {prototypeOnlyGroups.length > 0 && (
              <div className="rounded-lg border border-blue-200 bg-blue-50 p-3 mb-2">
                <div className="flex items-center gap-1.5 mb-1.5">
                  <AlertTriangle className="h-3.5 w-3.5 text-blue-600" />
                  <span className="text-[12px] font-medium text-blue-700">无需求ID分组</span>
                </div>
                <p className="text-[11px] text-blue-700 mb-1">
                  以下原型批注明确可拆，但未匹配到关联需求；采纳后只进入任务/用例，不进入需求池或关联需求列表：
                </p>
                <ul className="text-[12px] text-blue-800 ml-5 list-disc space-y-0.5">
                  {prototypeOnlyGroups.map((item, i) => (
                    <li key={i}>
                      <span className="font-medium">无需求ID · {item.requirementName}</span>
                      <span>（{item.noteIds.join(', ') || '无批注编号'} → 拆出 {item.taskCount} 个任务）</span>
                    </li>
                  ))}
                </ul>
              </div>
            )}

            {data.report.ambiguous.length > 0 && (
              <div className="rounded-lg border border-rose-200 bg-rose-50 p-3 mb-2">
                <div className="flex items-center gap-1.5 mb-1.5">
                  <HelpCircle className="h-3.5 w-3.5 text-rose-600" />
                  <span className="text-[12px] font-medium text-rose-700">含糊批注</span>
                </div>
                <ul className="text-[12px] text-rose-800 ml-5 space-y-0.5">
                  {data.report.ambiguous.map((a, i) => (
                    <li key={i}>
                      <span className="font-medium">{a.noteId}</span>：{a.reason}
                    </li>
                  ))}
                </ul>
              </div>
            )}
          </section>

          {/* DevTask 草案 */}
          {showDevDrafts && (
          <section>
            <h4 className="text-[12px] font-semibold text-[var(--ink-soft)] mb-2">
              开发任务草案（{data.devTaskDrafts.length}）
            </h4>
            {data.devTaskDrafts.length === 0 ? (
              <p className="text-[12px] text-[var(--ink-muted)]">无可生成的任务</p>
            ) : (
              <div className="space-y-2">
                {data.devTaskDrafts.map((d, i) => {
                  const recommendation = resolveRecommendedAssignee(d, version.members ?? []);
                  return (
                  <label
                    key={i}
                    className="flex gap-2 p-3 rounded-lg border border-[var(--line)] hover:bg-[var(--bg-subtle)] cursor-pointer"
                  >
                    <input
                      type="checkbox"
                      checked={selectedDevIdx.has(i)}
                      onChange={() => toggleDev(i)}
                      className="mt-0.5"
                    />
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-2 flex-wrap">
                        <span className="text-[13px] font-medium text-[var(--ink)]">{d.title}</span>
                        <span className="text-[10px] px-1.5 py-0.5 rounded bg-[var(--bg-subtle)] text-[var(--ink-soft)]">
                          {resolveDraftCategoryName(d, 'development')}
                        </span>
                        <span className="text-[10px] px-1.5 py-0.5 rounded bg-zinc-100 text-zinc-600">
                          {d.priority}
                        </span>
                        <span className="text-[10px] text-[var(--ink-muted)]">
                          AI预估 {clampDevAiEstimateHours(d.categoryCode, d.aiEstimateHours)}h
                        </span>
                        {d.requirementName && (
                          <span className="text-[10px] px-1.5 py-0.5 rounded bg-blue-50 text-blue-700 border border-blue-200">
                            无需求ID · {d.requirementName}
                          </span>
                        )}
                        {recommendation && (
                          <span
                            className="text-[10px] px-1.5 py-0.5 rounded bg-emerald-50 text-emerald-700 border border-emerald-200"
                            title={recommendation.reason ?? ''}
                          >
                            推荐 {recommendation.name}
                          </span>
                        )}
                      </div>
                      {d.description && (
                        <p className="mt-1 text-[12px] text-[var(--ink-soft)] line-clamp-2">{d.description}</p>
                      )}
                      <div className="mt-1.5 flex flex-wrap gap-1">
                        {d.references.map((r, j) => (
                          <span
                            key={j}
                            className="text-[10px] px-1.5 py-0.5 rounded bg-purple-50 text-purple-700 border border-purple-200"
                          >
                            {r.label}
                          </span>
                        ))}
                      </div>
                    </div>
                  </label>
                  );
                })}
              </div>
            )}
          </section>
          )}

          {/* TestCase 草案 */}
          {showTestDrafts && (
          <section>
            <h4 className="text-[12px] font-semibold text-[var(--ink-soft)] mb-2">
              测试用例草案（{data.testCaseDrafts.length}）
            </h4>
            {data.testCaseDrafts.length === 0 ? (
              <p className="text-[12px] text-[var(--ink-muted)]">无可生成的用例</p>
            ) : (
              <div className="space-y-2">
                {data.testCaseDrafts.map((d, i) => {
                  const recommendation = resolveRecommendedAssignee(d, version.members ?? []);
                  return (
                  <label
                    key={i}
                    className="flex gap-2 p-3 rounded-lg border border-[var(--line)] hover:bg-[var(--bg-subtle)] cursor-pointer"
                  >
                    <input
                      type="checkbox"
                      checked={selectedTcIdx.has(i)}
                      onChange={() => toggleTc(i)}
                      className="mt-0.5"
                    />
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-2 flex-wrap">
                        <span className="text-[13px] font-medium text-[var(--ink)]">{d.title}</span>
                        <span className="text-[10px] px-1.5 py-0.5 rounded bg-[var(--bg-subtle)] text-[var(--ink-soft)]">
                          {resolveDraftCategoryName(d, 'testing')}
                        </span>
                        <span className="text-[10px] px-1.5 py-0.5 rounded bg-zinc-100 text-zinc-600">
                          {d.priority}
                        </span>
                        <span className="text-[10px] text-[var(--ink-muted)]">
                          AI预估 {clampTestCaseAiEstimateHours(d.categoryCode, d.aiEstimateHours)}h
                        </span>
                        {d.requirementName && (
                          <span className="text-[10px] px-1.5 py-0.5 rounded bg-blue-50 text-blue-700 border border-blue-200">
                            无需求ID · {d.requirementName}
                          </span>
                        )}
                        {recommendation && (
                          <span
                            className="text-[10px] px-1.5 py-0.5 rounded bg-emerald-50 text-emerald-700 border border-emerald-200"
                            title={recommendation.reason ?? ''}
                          >
                            推荐 {recommendation.name}
                          </span>
                        )}
                      </div>
                      <pre className="mt-1 text-[11px] text-[var(--ink-soft)] whitespace-pre-wrap font-sans line-clamp-3">
                        {d.description}
                      </pre>
                      <div className="mt-1.5 flex flex-wrap gap-1">
                        {d.references.map((r, j) => (
                          <span
                            key={j}
                            className="text-[10px] px-1.5 py-0.5 rounded bg-purple-50 text-purple-700 border border-purple-200"
                          >
                            {r.label}
                          </span>
                        ))}
                      </div>
                    </div>
                  </label>
                  );
                })}
              </div>
            )}
          </section>
          )}
        </div>

        {/* Footer */}
        <div className="flex items-center justify-between gap-3 px-5 py-3 border-t border-[var(--line)]">
          <div className="flex flex-col gap-1">
            <div className="text-[12px] text-[var(--ink-muted)]">
              已选 {showDevDrafts ? selectedDevIdx.size : 0} 个任务 + {showTestDrafts ? selectedTcIdx.size : 0} 个用例
            </div>
            {visibleRecommendationCount > 0 && (
              <label className="flex items-center gap-2 text-[12px] text-[var(--ink-soft)]">
                <input
                  type="checkbox"
                  checked={useRecommendedAssignees}
                  onChange={(event) => setUseRecommendedAssignees(event.target.checked)}
                />
                <span>采纳推荐负责人（{visibleRecommendationCount}）</span>
              </label>
            )}
          </div>
          <div className="flex gap-2">
            <button
              onClick={() => {
                onRejected?.();
                onClose();
              }}
              disabled={submitting || submitted}
              className="h-8 px-3 rounded-lg text-[12px] font-medium border border-[var(--line)] text-[var(--ink-soft)] hover:bg-[var(--bg-subtle)]"
            >
              不采纳
            </button>
            <button
              onClick={onClose}
              disabled={submitting || submitted}
              className="h-8 px-3 rounded-lg text-[12px] font-medium border border-[var(--line)] text-[var(--ink-soft)] hover:bg-[var(--bg-subtle)]"
            >
              稍后处理
            </button>
            <button
              onClick={handleAdopt}
              disabled={submitting || submitted || selectedVisibleCount === 0}
              className="h-8 px-4 rounded-lg text-[12px] font-medium bg-purple-600 text-white hover:bg-purple-700 disabled:opacity-50"
            >
              {submitted ? '✓ 已采纳' : submitting ? '采纳中...' : '采纳选中'}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
