"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Database,
  Download,
  FileText,
  Loader2,
  Play,
  RefreshCw,
  Search,
  Trash2,
} from "lucide-react";
import DashboardLayout from "@/components/layout/dashboard-layout";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Progress } from "@/components/ui/progress";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { useToast } from "@/components/ui/use-toast";
import {
  CodeKnowledgeBase,
  AutoConsistencyJobStatus,
  ConsistencyJob,
  ConsistencyResult,
  createCodeKnowledgeBase,
  createAutoConsistencyJob,
  createConsistencyJob,
  deleteCodeKnowledgeBase,
  downloadConsistencyExport,
  getAutoConsistencyJob,
  getConsistencyJob,
  getConsistencyResults,
  listCodeKnowledgeBases,
  listConsistencyJobs,
} from "@/lib/consistency-api";
import {
  getSrsJobResult,
  getSrsJobStatus,
  listSrsHistory,
  SrsHistoryItem,
} from "@/lib/srs-tools-api";

type VerdictFilter =
  | "all"
  | "implemented"
  | "partial"
  | "missing"
  | "conflict"
  | "uncertain";

type RequirementOption = {
  id: string;
  title?: string;
  description: string;
};

const verdictLabel: Record<VerdictFilter, string> = {
  all: "全部",
  implemented: "已实现",
  partial: "部分覆盖",
  missing: "缺失",
  conflict: "冲突",
  uncertain: "不确定",
};

const verdictVariant: Record<
  Exclude<VerdictFilter, "all">,
  "default" | "secondary" | "destructive" | "outline"
> = {
  implemented: "default",
  partial: "secondary",
  missing: "destructive",
  conflict: "destructive",
  uncertain: "outline",
};

const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

const formatDateTime = (value?: string | null) => {
  if (!value) {
    return "-";
  }
  return new Date(value).toLocaleString("zh-CN");
};

export default function ConsistencyAnalysisPage() {
  const [srsHistory, setSrsHistory] = useState<SrsHistoryItem[]>([]);
  const [codeKbs, setCodeKbs] = useState<CodeKnowledgeBase[]>([]);
  const [jobs, setJobs] = useState<ConsistencyJob[]>([]);
  const [selectedSrsJobId, setSelectedSrsJobId] = useState<number | "">("");
  const [selectedExtractionId, setSelectedExtractionId] = useState<number | null>(null);
  const [requirements, setRequirements] = useState<RequirementOption[]>([]);
  const [selectedRequirementUids, setSelectedRequirementUids] = useState<string[]>([]);
  const [selectedCodeKbId, setSelectedCodeKbId] = useState<number | "">("");
  const [activeJob, setActiveJob] = useState<ConsistencyJob | null>(null);
  const [results, setResults] = useState<ConsistencyResult[]>([]);
  const [selectedResultId, setSelectedResultId] = useState<number | null>(null);
  const [filter, setFilter] = useState<VerdictFilter>("all");
  const [isLoading, setIsLoading] = useState(false);
  const [isRunning, setIsRunning] = useState(false);
  const [topK, setTopK] = useState(8);
  const [maxCallHops, setMaxCallHops] = useState(2);
  const [minSimilarity, setMinSimilarity] = useState(0.55);
  const [useLlm, setUseLlm] = useState(true);
  const [autoRequirementFile, setAutoRequirementFile] = useState<File | null>(null);
  const [autoCodeFiles, setAutoCodeFiles] = useState<File[]>([]);
  const [autoCodeKbName, setAutoCodeKbName] = useState("自动构建代码知识库");
  const [autoJob, setAutoJob] = useState<AutoConsistencyJobStatus | null>(null);
  const [isAutoRunning, setIsAutoRunning] = useState(false);
  const [kbForm, setKbForm] = useState({
    name: "",
    project_path: "",
    vector_path: "C:/VS_program/zjl/RAG-TEST-TOOLS/satellite_rag.faiss",
    metadata_path: "C:/VS_program/zjl/RAG-TEST-TOOLS/satellite_rag_metadata.json",
    graph_path: "C:/VS_program/zjl/RAG-TEST-TOOLS/project_code_knowledge_graph.json",
  });
  const { toast } = useToast();

  const loadInitialData = useCallback(async () => {
    setIsLoading(true);
    try {
      const [srsItems, kbItems, jobItems] = await Promise.all([
        listSrsHistory(),
        listCodeKnowledgeBases(),
        listConsistencyJobs(),
      ]);
      setSrsHistory(srsItems);
      setCodeKbs(kbItems);
      setJobs(jobItems);
      const lastJob = jobItems[0];
      if (lastJob) {
        setActiveJob(lastJob);
        const rows = await getConsistencyResults(lastJob.id);
        setResults(rows);
        setSelectedResultId(rows[0]?.id ?? null);
      }
    } catch (error) {
      const message = error instanceof Error ? error.message : "加载失败";
      toast({ title: "加载失败", description: message, variant: "destructive" });
    } finally {
      setIsLoading(false);
    }
  }, [toast]);

  useEffect(() => {
    void loadInitialData();
  }, [loadInitialData]);

  const filteredResults = useMemo(() => {
    if (filter === "all") {
      return results;
    }
    return results.filter((item) => item.verdict === filter);
  }, [filter, results]);

  const selectedResult = useMemo(() => {
    return results.find((item) => item.id === selectedResultId) ?? filteredResults[0] ?? null;
  }, [filteredResults, results, selectedResultId]);

  const progressValue = activeJob?.total_requirements
    ? Math.round((activeJob.completed_requirements / activeJob.total_requirements) * 100)
    : 0;
  const selectedRequirementSnapshot = (selectedResult?.raw_judgment?.requirement_snapshot ??
    {}) as {
    title?: string;
    description?: string;
    acceptance_criteria?: string[];
  };
  const selectedReasoning =
    typeof selectedResult?.raw_judgment?.reasoning === "string"
      ? selectedResult.raw_judgment.reasoning
      : "";

  const handleSelectSrsJob = async (value: string) => {
    const jobId = Number(value);
    setSelectedSrsJobId(Number.isNaN(jobId) ? "" : jobId);
    setSelectedExtractionId(null);
    setRequirements([]);
    setSelectedRequirementUids([]);
    if (!jobId) {
      return;
    }
    try {
      const status = await getSrsJobStatus(jobId);
      if (!status.extraction_id) {
        throw new Error("该需求抽取任务尚未产生 extraction_id");
      }
      const result = await getSrsJobResult(jobId);
      const nextRequirements = result.requirements.map((item) => ({
        id: item.id,
        title: item.title,
        description: item.description,
      }));
      setSelectedExtractionId(status.extraction_id);
      setRequirements(nextRequirements);
      setSelectedRequirementUids(nextRequirements.map((item) => item.id));
    } catch (error) {
      const message = error instanceof Error ? error.message : "读取需求抽取结果失败";
      toast({ title: "选择失败", description: message, variant: "destructive" });
    }
  };

  const toggleRequirement = (requirementUid: string) => {
    setSelectedRequirementUids((prev) =>
      prev.includes(requirementUid)
        ? prev.filter((item) => item !== requirementUid)
        : [...prev, requirementUid]
    );
  };

  const handleRegisterKb = async () => {
    if (!kbForm.name.trim()) {
      toast({ title: "缺少名称", description: "请填写代码知识库名称。", variant: "destructive" });
      return;
    }
    try {
      const created = await createCodeKnowledgeBase(kbForm);
      setCodeKbs((prev) => [created, ...prev]);
      setSelectedCodeKbId(created.id);
      toast({ title: "注册成功", description: `已注册代码知识库 ${created.name}` });
    } catch (error) {
      const message = error instanceof Error ? error.message : "注册失败";
      toast({ title: "注册失败", description: message, variant: "destructive" });
    }
  };

  const handleDeleteKb = async (id: number) => {
    try {
      await deleteCodeKnowledgeBase(id);
      setCodeKbs((prev) => prev.filter((item) => item.id !== id));
      if (selectedCodeKbId === id) {
        setSelectedCodeKbId("");
      }
      toast({ title: "删除成功", description: "代码知识库记录已删除。" });
    } catch (error) {
      const message = error instanceof Error ? error.message : "删除失败";
      toast({ title: "删除失败", description: message, variant: "destructive" });
    }
  };

  const pollJob = async (jobId: number) => {
    for (let index = 0; index < 300; index += 1) {
      const job = await getConsistencyJob(jobId);
      setActiveJob(job);
      if (job.status === "completed") {
        const rows = await getConsistencyResults(jobId);
        setResults(rows);
        setSelectedResultId(rows[0]?.id ?? null);
        return;
      }
      if (job.status === "failed") {
        throw new Error(job.error_message || "比对任务失败");
      }
      await wait(2000);
    }
    throw new Error("比对任务超时，请稍后在历史任务中查看。");
  };

  const pollAutoJob = async (jobId: number) => {
    for (let index = 0; index < 300; index += 1) {
      const job = await getAutoConsistencyJob(jobId);
      setAutoJob(job);
      if (job.status === "completed") {
        if (!job.consistency_job_id) {
          throw new Error("自动任务完成但未返回一致性任务 ID");
        }
        const consistencyJob = await getConsistencyJob(job.consistency_job_id);
        const rows = await getConsistencyResults(job.consistency_job_id);
        setActiveJob(consistencyJob);
        setResults(rows);
        setSelectedResultId(rows[0]?.id ?? null);
        const [kbItems, jobItems] = await Promise.all([
          listCodeKnowledgeBases(),
          listConsistencyJobs(),
        ]);
        setCodeKbs(kbItems);
        setJobs(jobItems);
        return;
      }
      if (job.status === "failed") {
        throw new Error(job.error_message || "自动比对任务失败");
      }
      await wait(2000);
    }
    throw new Error("自动比对任务超时，请稍后刷新历史任务查看。");
  };

  const handleStartJob = async () => {
    if (!selectedExtractionId || !selectedCodeKbId) {
      toast({
        title: "缺少输入",
        description: "请先选择 SRS 抽取结果和代码知识库。",
        variant: "destructive",
      });
      return;
    }
    if (requirements.length > 0 && selectedRequirementUids.length === 0) {
      toast({
        title: "未选择需求",
        description: "请至少选择一条需求参与比对。",
        variant: "destructive",
      });
      return;
    }
    setIsRunning(true);
    setResults([]);
    setSelectedResultId(null);
    try {
      const created = await createConsistencyJob({
        srs_extraction_id: selectedExtractionId,
        code_kb_id: Number(selectedCodeKbId),
        top_k: topK,
        max_call_hops: maxCallHops,
        min_similarity: minSimilarity,
        use_llm: useLlm,
        requirement_uids:
          selectedRequirementUids.length > 0 && selectedRequirementUids.length < requirements.length
            ? selectedRequirementUids
            : undefined,
      });
      const pending = await getConsistencyJob(created.job_id);
      setActiveJob(pending);
      await pollJob(created.job_id);
      const jobItems = await listConsistencyJobs();
      setJobs(jobItems);
      toast({ title: "比对完成", description: "需求代码追踪矩阵已生成。" });
    } catch (error) {
      const message = error instanceof Error ? error.message : "任务启动失败";
      toast({ title: "比对失败", description: message, variant: "destructive" });
    } finally {
      setIsRunning(false);
    }
  };

  const handleStartAutoJob = async () => {
    if (!autoRequirementFile || autoCodeFiles.length === 0) {
      toast({
        title: "缺少上传文件",
        description: "请同时选择需求文件和代码文件或 zip 工程包。",
        variant: "destructive",
      });
      return;
    }
    setIsAutoRunning(true);
    setAutoJob(null);
    setResults([]);
    setSelectedResultId(null);
    try {
      const created = await createAutoConsistencyJob(autoRequirementFile, autoCodeFiles, {
        codeKbName: autoCodeKbName || "自动构建代码知识库",
        topK,
        maxCallHops,
        minSimilarity,
        useLlm,
        useSemantic: true,
      });
      const first = await getAutoConsistencyJob(created.job_id);
      setAutoJob(first);
      await pollAutoJob(created.job_id);
      toast({ title: "自动比对完成", description: "需求抽取、代码构建和一致性比对已完成。" });
    } catch (error) {
      const message = error instanceof Error ? error.message : "自动比对失败";
      toast({ title: "自动比对失败", description: message, variant: "destructive" });
    } finally {
      setIsAutoRunning(false);
    }
  };

  const handleLoadJob = async (jobId: number) => {
    try {
      const job = await getConsistencyJob(jobId);
      const rows = await getConsistencyResults(jobId);
      setActiveJob(job);
      setResults(rows);
      setSelectedResultId(rows[0]?.id ?? null);
    } catch (error) {
      const message = error instanceof Error ? error.message : "加载任务失败";
      toast({ title: "加载失败", description: message, variant: "destructive" });
    }
  };

  const handleExport = async (format: "json" | "markdown" | "xlsx") => {
    if (!activeJob) {
      return;
    }
    try {
      await downloadConsistencyExport(activeJob.id, format);
    } catch (error) {
      const message = error instanceof Error ? error.message : "导出失败";
      toast({ title: "导出失败", description: message, variant: "destructive" });
    }
  };

  return (
    <DashboardLayout>
      <div className="space-y-6">
        <Card>
          <CardHeader>
            <CardTitle className="text-2xl">需求代码一致性比对</CardTitle>
            <CardDescription>
              选择 SRS 抽取结果和代码知识库，生成需求到函数级代码证据的追踪矩阵。
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="grid gap-4 lg:grid-cols-2">
              <div className="space-y-2">
                <Label>需求抽取结果</Label>
                <select
                  className="h-10 w-full rounded-md border border-input bg-background px-3 text-sm"
                  value={selectedSrsJobId}
                  onChange={(event) => void handleSelectSrsJob(event.target.value)}
                >
                  <option value="">选择 SRS 历史任务</option>
                  {srsHistory.map((item) => (
                    <option key={item.jobId} value={item.jobId}>
                      {item.documentName} · {item.totalRequirements} 条 · {formatDateTime(item.generatedAt)}
                    </option>
                  ))}
                </select>
                <p className="text-xs text-muted-foreground">
                  当前 extraction_id: {selectedExtractionId ?? "-"}
                </p>
              </div>

              <div className="space-y-2">
                <Label>代码知识库</Label>
                <select
                  className="h-10 w-full rounded-md border border-input bg-background px-3 text-sm"
                  value={selectedCodeKbId}
                  onChange={(event) => setSelectedCodeKbId(Number(event.target.value) || "")}
                >
                  <option value="">选择代码知识库</option>
                  {codeKbs.filter((item) => item.status === "active").map((item) => (
                    <option key={item.id} value={item.id}>
                      {item.name} · {String(item.metadata_summary?.function_count ?? 0)} 函数
                    </option>
                  ))}
                </select>
              </div>
            </div>

            {requirements.length > 0 && (
              <div className="space-y-3 rounded-md border p-3">
                <div className="flex flex-wrap items-center justify-between gap-2">
                  <div>
                    <p className="text-sm font-medium">需求范围</p>
                    <p className="text-xs text-muted-foreground">
                      已选择 {selectedRequirementUids.length}/{requirements.length} 条需求参与比对
                    </p>
                  </div>
                  <div className="flex gap-2">
                    <Button
                      size="sm"
                      variant="outline"
                      onClick={() => setSelectedRequirementUids(requirements.map((item) => item.id))}
                    >
                      全选
                    </Button>
                    <Button size="sm" variant="outline" onClick={() => setSelectedRequirementUids([])}>
                      清空
                    </Button>
                  </div>
                </div>
                <div className="grid max-h-52 gap-2 overflow-y-auto pr-1 md:grid-cols-2">
                  {requirements.map((item) => {
                    const checked = selectedRequirementUids.includes(item.id);
                    return (
                      <label
                        key={item.id}
                        className="flex cursor-pointer gap-2 rounded-md border p-2 text-sm hover:border-primary/40"
                      >
                        <input
                          type="checkbox"
                          className="mt-1"
                          checked={checked}
                          onChange={() => toggleRequirement(item.id)}
                        />
                        <span>
                          <span className="block font-medium">{item.id}</span>
                          <span className="line-clamp-2 text-xs text-muted-foreground">
                            {item.title || item.description || "-"}
                          </span>
                        </span>
                      </label>
                    );
                  })}
                </div>
              </div>
            )}

            <div className="grid gap-4 md:grid-cols-4">
              <div className="space-y-2">
                <Label>Top K</Label>
                <Input
                  type="number"
                  min={1}
                  max={30}
                  value={topK}
                  onChange={(event) => setTopK(Number(event.target.value) || 8)}
                />
              </div>
              <div className="space-y-2">
                <Label>调用图跳数</Label>
                <Input
                  type="number"
                  min={0}
                  max={4}
                  value={maxCallHops}
                  onChange={(event) => setMaxCallHops(Number(event.target.value) || 0)}
                />
              </div>
              <div className="space-y-2">
                <Label>最小相似度</Label>
                <Input
                  type="number"
                  min={0}
                  max={1}
                  step={0.01}
                  value={minSimilarity}
                  onChange={(event) => setMinSimilarity(Number(event.target.value) || 0)}
                />
              </div>
              <div className="space-y-2">
                <Label>判定模式</Label>
                <select
                  className="h-10 w-full rounded-md border border-input bg-background px-3 text-sm"
                  value={useLlm ? "llm" : "heuristic"}
                  onChange={(event) => setUseLlm(event.target.value === "llm")}
                >
                  <option value="llm">LLM 结构化判定</option>
                  <option value="heuristic">保守启发式</option>
                </select>
              </div>
            </div>

            <div className="flex flex-wrap gap-3">
              <Button onClick={handleStartJob} disabled={isRunning}>
                {isRunning ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <Play className="mr-2 h-4 w-4" />
                )}
                启动比对
              </Button>
              <Button variant="outline" onClick={() => void loadInitialData()} disabled={isLoading}>
                <RefreshCw className="mr-2 h-4 w-4" />
                刷新
              </Button>
              <Button variant="outline" onClick={() => void handleExport("json")} disabled={!activeJob}>
                <Download className="mr-2 h-4 w-4" />
                JSON
              </Button>
              <Button variant="outline" onClick={() => void handleExport("markdown")} disabled={!activeJob}>
                <Download className="mr-2 h-4 w-4" />
                Markdown
              </Button>
              <Button variant="outline" onClick={() => void handleExport("xlsx")} disabled={!activeJob}>
                <Download className="mr-2 h-4 w-4" />
                Excel
              </Button>
            </div>

            {activeJob && (
              <div className="space-y-2 rounded-md border p-3 text-sm">
                <div className="flex flex-wrap items-center justify-between gap-2">
                  <span>
                    任务 #{activeJob.id} · {activeJob.status} · {activeJob.completed_requirements}/
                    {activeJob.total_requirements}
                  </span>
                  {activeJob.error_message && (
                    <span className="text-destructive">{activeJob.error_message}</span>
                  )}
                </div>
                <Progress value={progressValue} />
              </div>
            )}
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle className="text-lg">代码知识库注册</CardTitle>
            <CardDescription>
              先注册由 RAG-TEST-TOOLS 生成的 FAISS、metadata 和 graph JSON 文件。
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="grid gap-4 md:grid-cols-2">
              <div className="space-y-2">
                <Label>名称</Label>
                <Input
                  value={kbForm.name}
                  onChange={(event) => setKbForm((prev) => ({ ...prev, name: event.target.value }))}
                  placeholder="姿控代码知识库"
                />
              </div>
              <div className="space-y-2">
                <Label>项目路径</Label>
                <Input
                  value={kbForm.project_path}
                  onChange={(event) =>
                    setKbForm((prev) => ({ ...prev, project_path: event.target.value }))
                  }
                  placeholder="C:/path/project"
                />
              </div>
              <div className="space-y-2 md:col-span-2">
                <Label>FAISS 路径</Label>
                <Input
                  value={kbForm.vector_path}
                  onChange={(event) =>
                    setKbForm((prev) => ({ ...prev, vector_path: event.target.value }))
                  }
                />
              </div>
              <div className="space-y-2 md:col-span-2">
                <Label>Metadata 路径</Label>
                <Input
                  value={kbForm.metadata_path}
                  onChange={(event) =>
                    setKbForm((prev) => ({ ...prev, metadata_path: event.target.value }))
                  }
                />
              </div>
              <div className="space-y-2 md:col-span-2">
                <Label>Graph JSON 路径</Label>
                <Input
                  value={kbForm.graph_path}
                  onChange={(event) =>
                    setKbForm((prev) => ({ ...prev, graph_path: event.target.value }))
                  }
                />
              </div>
            </div>
            <div className="flex flex-wrap gap-3">
              <Button variant="secondary" onClick={() => void handleRegisterKb()}>
                <Database className="mr-2 h-4 w-4" />
                注册代码知识库
              </Button>
            </div>

            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>名称</TableHead>
                  <TableHead>函数数</TableHead>
                  <TableHead>状态</TableHead>
                  <TableHead>创建时间</TableHead>
                  <TableHead className="text-right">操作</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {codeKbs.length === 0 && (
                  <TableRow>
                    <TableCell colSpan={5} className="text-center text-muted-foreground">
                      暂无代码知识库
                    </TableCell>
                  </TableRow>
                )}
                {codeKbs.map((item) => (
                  <TableRow key={item.id}>
                    <TableCell>{item.name}</TableCell>
                    <TableCell>{String(item.metadata_summary?.function_count ?? "-")}</TableCell>
                    <TableCell>{item.status}</TableCell>
                    <TableCell>{formatDateTime(item.created_at)}</TableCell>
                    <TableCell className="text-right">
                      <Button
                        size="sm"
                        variant="destructive"
                        onClick={() => void handleDeleteKb(item.id)}
                      >
                        <Trash2 className="mr-1 h-3.5 w-3.5" />
                        删除
                      </Button>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </CardContent>
        </Card>

        <div className="grid gap-6 lg:grid-cols-[1fr_420px]">
          <Card>
            <CardHeader>
              <CardTitle className="text-lg">追踪矩阵</CardTitle>
              <CardDescription>按判定结果筛选缺失、部分覆盖、冲突和不确定项。</CardDescription>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="flex flex-wrap gap-2">
                {(["all", "implemented", "partial", "missing", "conflict", "uncertain"] as VerdictFilter[]).map(
                  (item) => (
                    <Button
                      key={item}
                      size="sm"
                      variant={filter === item ? "secondary" : "outline"}
                      onClick={() => setFilter(item)}
                    >
                      {verdictLabel[item]}
                    </Button>
                  )
                )}
              </div>
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>需求 ID</TableHead>
                    <TableHead>判定</TableHead>
                    <TableHead>覆盖分</TableHead>
                    <TableHead>置信度</TableHead>
                    <TableHead>函数</TableHead>
                    <TableHead>缺失点</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {filteredResults.length === 0 && (
                    <TableRow>
                      <TableCell colSpan={6} className="text-center text-muted-foreground">
                        暂无比对结果
                      </TableCell>
                    </TableRow>
                  )}
                  {filteredResults.map((item) => (
                    <TableRow
                      key={item.id}
                      className="cursor-pointer"
                      onClick={() => setSelectedResultId(item.id)}
                    >
                      <TableCell className="font-medium">{item.requirement_uid}</TableCell>
                      <TableCell>
                        <Badge variant={verdictVariant[item.verdict]}>
                          {verdictLabel[item.verdict]}
                        </Badge>
                      </TableCell>
                      <TableCell>{Math.round(item.coverage_score * 100)}%</TableCell>
                      <TableCell>{Math.round(item.confidence * 100)}%</TableCell>
                      <TableCell>{item.matched_functions.length}</TableCell>
                      <TableCell>{item.missing_points.length}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle className="text-lg">证据详情</CardTitle>
              <CardDescription>查看单条需求对应的函数、调用链和缺失点。</CardDescription>
            </CardHeader>
            <CardContent>
              {!selectedResult && (
                <div className="rounded-md border border-dashed p-6 text-center text-sm text-muted-foreground">
                  请选择矩阵中的一条结果。
                </div>
              )}
              {selectedResult && (
                <div className="space-y-4">
                  <div>
                    <div className="flex items-center gap-2">
                      <FileText className="h-4 w-4 text-muted-foreground" />
                      <h3 className="font-semibold">{selectedResult.requirement_uid}</h3>
                      <Badge variant={verdictVariant[selectedResult.verdict]}>
                        {verdictLabel[selectedResult.verdict]}
                      </Badge>
                    </div>
                    <p className="mt-2 text-sm text-muted-foreground">
                      建议: {selectedResult.suggestion || "-"}
                    </p>
                  </div>

                  <div>
                    <h4 className="mb-2 text-sm font-medium">需求原文</h4>
                    <p className="rounded-md border p-3 text-sm text-muted-foreground whitespace-pre-wrap">
                      {selectedRequirementSnapshot.description || "-"}
                    </p>
                  </div>

                  <div>
                    <h4 className="mb-2 text-sm font-medium">验收准则</h4>
                    <ul className="space-y-1 text-sm text-muted-foreground">
                      {(selectedRequirementSnapshot.acceptance_criteria?.length
                        ? selectedRequirementSnapshot.acceptance_criteria
                        : ["-"]
                      ).map((point, index) => (
                        <li key={`acceptance-${index}`}>• {point}</li>
                      ))}
                    </ul>
                  </div>

                  <div>
                    <h4 className="mb-2 text-sm font-medium">匹配函数</h4>
                    <div className="space-y-2">
                      {selectedResult.matched_functions.map((item, index) => (
                        <div key={`${item.node_id}-${index}`} className="rounded-md border p-3 text-sm">
                          <p className="font-medium">
                            {item.name} · similarity {Number(item.similarity || 0).toFixed(2)}
                          </p>
                          <p className="text-xs text-muted-foreground">
                            {item.file}:{item.start_line}-{item.end_line}
                          </p>
                          <p className="mt-2 text-xs text-muted-foreground line-clamp-3">
                            {item.evidence_summary || "-"}
                          </p>
                          {typeof item.logic_flow === "string" && item.logic_flow && (
                            <div className="mt-3 rounded-md bg-muted p-2">
                              <p className="mb-1 text-xs font-medium">逻辑流</p>
                              <p className="whitespace-pre-wrap text-xs text-muted-foreground">
                                {item.logic_flow}
                              </p>
                            </div>
                          )}
                          {typeof item.code_snippet === "string" && item.code_snippet && (
                            <pre className="mt-3 max-h-48 overflow-auto rounded-md bg-muted p-2 text-xs">
                              <code>{item.code_snippet}</code>
                            </pre>
                          )}
                        </div>
                      ))}
                      {selectedResult.matched_functions.length === 0 && (
                        <div className="rounded-md border border-dashed p-3 text-sm text-muted-foreground">
                          未召回函数证据
                        </div>
                      )}
                    </div>
                  </div>

                  <div>
                    <h4 className="mb-2 text-sm font-medium">覆盖点</h4>
                    <ul className="space-y-1 text-sm text-muted-foreground">
                      {(selectedResult.covered_points.length ? selectedResult.covered_points : ["-"]).map(
                        (point, index) => (
                          <li key={`covered-${index}`}>• {point}</li>
                        )
                      )}
                    </ul>
                  </div>

                  <div>
                    <h4 className="mb-2 text-sm font-medium">缺失点</h4>
                    <ul className="space-y-1 text-sm text-muted-foreground">
                      {(selectedResult.missing_points.length ? selectedResult.missing_points : ["-"]).map(
                        (point, index) => (
                          <li key={`missing-${index}`}>• {point}</li>
                        )
                      )}
                    </ul>
                  </div>

                  {selectedResult.conflict_points.length > 0 && (
                    <div>
                      <h4 className="mb-2 text-sm font-medium">冲突点</h4>
                      <ul className="space-y-1 text-sm text-muted-foreground">
                        {selectedResult.conflict_points.map((point, index) => (
                          <li key={`conflict-${index}`}>• {point}</li>
                        ))}
                      </ul>
                    </div>
                  )}

                  <div>
                    <h4 className="mb-2 text-sm font-medium">调用链</h4>
                    <ul className="space-y-1 text-sm text-muted-foreground">
                      {(selectedResult.call_chain_evidence.length
                        ? selectedResult.call_chain_evidence
                        : ["-"]
                      ).map((line, index) => (
                        <li key={`chain-${index}`}>• {line}</li>
                      ))}
                    </ul>
                  </div>

                  <div>
                    <h4 className="mb-2 text-sm font-medium">模型判定理由</h4>
                    <p className="rounded-md border p-3 text-sm text-muted-foreground whitespace-pre-wrap">
                      {selectedReasoning || "-"}
                    </p>
                  </div>
                </div>
              )}
            </CardContent>
          </Card>
        </div>

        <Card>
          <CardHeader>
            <CardTitle className="text-lg">历史任务</CardTitle>
            <CardDescription>加载历史比对任务及结果。</CardDescription>
          </CardHeader>
          <CardContent>
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>任务</TableHead>
                  <TableHead>状态</TableHead>
                  <TableHead>进度</TableHead>
                  <TableHead>创建时间</TableHead>
                  <TableHead className="text-right">操作</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {jobs.length === 0 && (
                  <TableRow>
                    <TableCell colSpan={5} className="text-center text-muted-foreground">
                      暂无历史任务
                    </TableCell>
                  </TableRow>
                )}
                {jobs.map((item) => (
                  <TableRow key={item.id}>
                    <TableCell>#{item.id}</TableCell>
                    <TableCell>{item.status}</TableCell>
                    <TableCell>
                      {item.completed_requirements}/{item.total_requirements}
                    </TableCell>
                    <TableCell>{formatDateTime(item.created_at)}</TableCell>
                    <TableCell className="text-right">
                      <Button size="sm" variant="outline" onClick={() => void handleLoadJob(item.id)}>
                        <Search className="mr-1 h-3.5 w-3.5" />
                        查看
                      </Button>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </CardContent>
        </Card>
      </div>
    </DashboardLayout>
  );
}
