"use client";

import { ChangeEvent, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useDropzone } from "react-dropzone";
import {
  Database,
  Download,
  FileJson,
  History,
  Loader2,
  Sparkles,
  Trash2,
  Upload,
} 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 {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { useToast } from "@/components/ui/use-toast";
import {
  downloadJson,
  parseRequirementJson,
  PriorityLevel,
  RequirementExtractionResult,
  RequirementItem,
} from "@/lib/document-mock";
import {
  createTestingGenerationJob,
  deleteTestingGeneration,
  generateTestingContent,
  getTestingGenerationJobStatus,
  getSrsJobResult,
  getTestingGenerationResult,
  KnowledgeBaseSummary,
  listKnowledgeBases,
  listSrsHistory,
  listTestingHistory,
  saveTestingGeneration,
  SrsHistoryItem,
  TestingGenerationHistoryItem,
  TestingGenerationSaveRequest,
  toExtractionResult,
} from "@/lib/srs-tools-api";
import { cn } from "@/lib/utils";

interface GeneratedTestItem {
  id: string;
  content: string;
}

interface GeneratedTestCase {
  id: string;
  itemId: string;
  testContent: string;
  operationSteps: string[];
  expectedResultPlaceholder: string;
}

interface GeneratedExpectedResult {
  id: string;
  caseId: string;
  result: string;
}

interface GeneratedRequirement extends RequirementItem {
  "测试项": GeneratedTestItem[];
  "测试用例": GeneratedTestCase[];
  "预期结果": GeneratedExpectedResult[];
}

interface TestingGenerationFile {
  sourceDocument: string;
  sourceJobId?: number | null;
  generatedAt: string;
  totalRequirements: number;
  knowledgeBaseId?: number | null;
  knowledgeBaseName?: string | null;
  requirements: GeneratedRequirement[];
}

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

const asRecord = (value: unknown): Record<string, unknown> | null => {
  if (!value || typeof value !== "object" || Array.isArray(value)) {
    return null;
  }
  return value as Record<string, unknown>;
};

const asString = (value: unknown, fallback = ""): string => {
  if (typeof value === "string") {
    return value;
  }
  return fallback;
};

const asPriority = (value: unknown): PriorityLevel => {
  if (value === "高" || value === "中" || value === "低") {
    return value;
  }
  return "中";
};

const normalizeRequirementType = (value: unknown): RequirementItem["requirementType"] => {
  if (
    value === "functional" ||
    value === "interface" ||
    value === "performance" ||
    value === "security" ||
    value === "reliability" ||
    value === "other"
  ) {
    return value;
  }
  return "functional";
};

const asStringArray = (value: unknown): string[] => {
  if (!Array.isArray(value)) {
    return [];
  }
  return value.map((item) => String(item));
};

const asGeneratedTestItems = (value: unknown): GeneratedTestItem[] => {
  if (!Array.isArray(value)) {
    return [];
  }
  return value
    .map((entry, index) => {
      const record = asRecord(entry);
      if (!record) {
        return null;
      }
      return {
        id: asString(record.id, `item-${index + 1}`),
        content: asString(record.content),
      };
    })
    .filter((entry): entry is GeneratedTestItem => entry !== null);
};

const asGeneratedTestCases = (value: unknown): GeneratedTestCase[] => {
  if (!Array.isArray(value)) {
    return [];
  }
  return value
    .map((entry, index) => {
      const record = asRecord(entry);
      if (!record) {
        return null;
      }
      return {
        id: asString(record.id, `case-${index + 1}`),
        itemId: asString(record.itemId),
        testContent: asString(record.testContent),
        operationSteps: asStringArray(record.operationSteps),
        expectedResultPlaceholder: asString(record.expectedResultPlaceholder),
      };
    })
    .filter((entry): entry is GeneratedTestCase => entry !== null);
};

const asExpectedResults = (value: unknown): GeneratedExpectedResult[] => {
  if (!Array.isArray(value)) {
    return [];
  }
  return value
    .map((entry, index) => {
      const record = asRecord(entry);
      if (!record) {
        return null;
      }
      return {
        id: asString(record.id, `exp-${index + 1}`),
        caseId: asString(record.caseId),
        result: asString(record.result),
      };
    })
    .filter((entry): entry is GeneratedExpectedResult => entry !== null);
};

const normalizeGeneratedFile = (value: Record<string, unknown>): TestingGenerationFile | null => {
  const requirementsRaw = value.requirements;
  if (!Array.isArray(requirementsRaw)) {
    return null;
  }

  const requirements: GeneratedRequirement[] = [];
  requirementsRaw.forEach((entry, index) => {
    const record = asRecord(entry);
    if (!record) {
      return;
    }

    const requirement: GeneratedRequirement = {
      id: asString(record.id, `REQ-${String(index + 1).padStart(3, "0")}`),
      description: asString(record.description),
      priority: asPriority(record.priority),
      acceptanceCriteria: asStringArray(record.acceptanceCriteria),
      sourceField: asString(record.sourceField, "文档解析"),
      requirementType: normalizeRequirementType(record.requirementType),
      sortOrder: typeof record.sortOrder === "number" ? record.sortOrder : index,
      "测试项": asGeneratedTestItems(record["测试项"]),
      "测试用例": asGeneratedTestCases(record["测试用例"]),
      "预期结果": asExpectedResults(record["预期结果"]),
    };

    const title = asString(record.title);
    const sectionUid = asString(record.sectionUid);
    const sectionNumber = asString(record.sectionNumber);
    const sectionTitle = asString(record.sectionTitle);
    const interfaceName = asString(record.interfaceName);
    const interfaceType = asString(record.interfaceType);
    const dataSource = asString(record.dataSource);
    const dataDestination = asString(record.dataDestination);

    if (title) {
      requirement.title = title;
    }
    if (sectionUid) {
      requirement.sectionUid = sectionUid;
    }
    if (sectionNumber) {
      requirement.sectionNumber = sectionNumber;
    }
    if (sectionTitle) {
      requirement.sectionTitle = sectionTitle;
    }
    if (interfaceName) {
      requirement.interfaceName = interfaceName;
    }
    if (interfaceType) {
      requirement.interfaceType = interfaceType;
    }
    if (dataSource) {
      requirement.dataSource = dataSource;
    }
    if (dataDestination) {
      requirement.dataDestination = dataDestination;
    }

    requirements.push(requirement);
  });

  return {
    sourceDocument: asString(value.sourceDocument, "导入需求文件"),
    sourceJobId: typeof value.sourceJobId === "number" ? value.sourceJobId : null,
    generatedAt: asString(value.generatedAt, new Date().toISOString()),
    totalRequirements:
      typeof value.totalRequirements === "number" ? value.totalRequirements : requirements.length,
    knowledgeBaseId: typeof value.knowledgeBaseId === "number" ? value.knowledgeBaseId : null,
    knowledgeBaseName: asString(value.knowledgeBaseName) || null,
    requirements,
  };
};

const flattenRecord = <T,>(value: Record<string, T[]>): T[] => {
  return Object.values(value).reduce<T[]>((acc, current) => {
    acc.push(...current);
    return acc;
  }, []);
};

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

const toExtraction = (file: TestingGenerationFile): RequirementExtractionResult => {
  const requirements: RequirementItem[] = file.requirements.map((item) => ({
    id: item.id,
    title: item.title,
    description: item.description,
    priority: item.priority,
    acceptanceCriteria: item.acceptanceCriteria,
    sourceField: item.sourceField,
    sectionUid: item.sectionUid,
    sectionNumber: item.sectionNumber,
    sectionTitle: item.sectionTitle,
    requirementType: item.requirementType,
    interfaceName: item.interfaceName,
    interfaceType: item.interfaceType,
    dataSource: item.dataSource,
    dataDestination: item.dataDestination,
    sortOrder: item.sortOrder,
  }));

  return {
    documentName: file.sourceDocument,
    generatedAt: file.generatedAt,
    requirements,
  };
};

export default function TestCaseGenerationPage() {
  const [inputFile, setInputFile] = useState<File | null>(null);
  const [requirementData, setRequirementData] =
    useState<RequirementExtractionResult | null>(null);
  const [sourceSrsJobId, setSourceSrsJobId] = useState<number | null>(null);
  const [generation, setGeneration] = useState<TestingGenerationFile | null>(null);
  const [activeGenerationJobId, setActiveGenerationJobId] = useState<number | null>(null);
  const [selectedRequirementId, setSelectedRequirementId] = useState<string | null>(null);
  const [isParsing, setIsParsing] = useState(false);
  const [isGenerating, setIsGenerating] = useState(false);
  const [generationProgress, setGenerationProgress] = useState("");
  const [srsHistoryItems, setSrsHistoryItems] = useState<SrsHistoryItem[]>([]);
  const [isSrsHistoryLoading, setIsSrsHistoryLoading] = useState(false);
  const [isSrsHistoryOpen, setIsSrsHistoryOpen] = useState(false);
  const [knowledgeBases, setKnowledgeBases] = useState<KnowledgeBaseSummary[]>([]);
  const [isKbDialogOpen, setIsKbDialogOpen] = useState(false);
  const [selectedKnowledgeBaseId, setSelectedKnowledgeBaseId] = useState<number | null>(null);
  const [isKbLoading, setIsKbLoading] = useState(false);
  const [testingHistoryItems, setTestingHistoryItems] = useState<TestingGenerationHistoryItem[]>([]);
  const [isTestingHistoryLoading, setIsTestingHistoryLoading] = useState(false);
  const [isTestingHistoryOpen, setIsTestingHistoryOpen] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const { toast } = useToast();

  const selectedKnowledgeBaseName = useMemo(() => {
    if (selectedKnowledgeBaseId === null) {
      return "不使用知识库";
    }
    const hit = knowledgeBases.find((item) => item.id === selectedKnowledgeBaseId);
    return hit ? hit.name : `知识库 #${selectedKnowledgeBaseId}`;
  }, [knowledgeBases, selectedKnowledgeBaseId]);

  const selectedRequirement = generation?.requirements.find(
    (item) => item.id === selectedRequirementId
  );

  const loadSrsHistory = useCallback(async () => {
    setIsSrsHistoryLoading(true);
    try {
      const items = await listSrsHistory();
      setSrsHistoryItems(items);
    } catch {
      setSrsHistoryItems([]);
    } finally {
      setIsSrsHistoryLoading(false);
    }
  }, []);

  const loadKnowledgeBaseList = useCallback(async () => {
    setIsKbLoading(true);
    try {
      const items = await listKnowledgeBases();
      setKnowledgeBases(items);
    } catch {
      setKnowledgeBases([]);
    } finally {
      setIsKbLoading(false);
    }
  }, []);

  const loadTestingHistory = useCallback(async () => {
    setIsTestingHistoryLoading(true);
    try {
      const items = await listTestingHistory();
      setTestingHistoryItems(items);
    } catch {
      setTestingHistoryItems([]);
    } finally {
      setIsTestingHistoryLoading(false);
    }
  }, []);

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

  const parseRequirementFile = async (file: File) => {
    setIsParsing(true);
    try {
      const text = await file.text();
      const parsed = parseRequirementJson(text);
      setRequirementData(parsed);
      setSourceSrsJobId(null);
      setGeneration(null);
      setActiveGenerationJobId(null);
      setSelectedRequirementId(null);
      toast({
        title: "解析成功",
        description: `已识别 ${parsed.requirements.length} 条需求。`,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : "JSON 解析失败";
      toast({
        title: "解析失败",
        description: message,
        variant: "destructive",
      });
    } finally {
      setIsParsing(false);
    }
  };

  const onDrop = useCallback(
    async (acceptedFiles: File[]) => {
      const file = acceptedFiles[0];
      if (!file) {
        return;
      }
      setInputFile(file);
      await parseRequirementFile(file);
    },
    [parseRequirementFile]
  );

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    maxFiles: 1,
    accept: {
      "application/json": [".json"],
      "text/json": [".json"],
    },
  });

  const handleChooseFile = () => {
    fileInputRef.current?.click();
  };

  const handleFileInput = async (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) {
      return;
    }

    setInputFile(file);
    await parseRequirementFile(file);
    event.target.value = "";
  };

  const handleLoadSrsHistory = async (jobId: number) => {
    try {
      const result = await getSrsJobResult(jobId);
      const extraction = toExtractionResult(result);
      setRequirementData(extraction);
      setInputFile(null);
      setSourceSrsJobId(jobId);
      setGeneration(null);
      setSelectedRequirementId(null);
      setActiveGenerationJobId(null);
      setIsSrsHistoryOpen(false);
      toast({
        title: "加载成功",
        description: `已加载 ${extraction.documentName}`,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : "加载历史文件失败";
      toast({
        title: "加载失败",
        description: message,
        variant: "destructive",
      });
    }
  };

  const handleLoadTestingHistory = async (jobId: number) => {
    try {
      const result = await getTestingGenerationResult(jobId);
      const normalized = normalizeGeneratedFile(result.generatedFile);
      if (!normalized) {
        throw new Error("历史文件格式不正确");
      }

      const next: TestingGenerationFile = {
        ...normalized,
        sourceJobId: result.sourceJobId ?? normalized.sourceJobId ?? null,
        knowledgeBaseId: result.knowledgeBaseId ?? normalized.knowledgeBaseId ?? null,
      };

      setGeneration(next);
      setSelectedRequirementId(next.requirements[0]?.id ?? null);
      setRequirementData(toExtraction(next));
      setSourceSrsJobId(result.sourceJobId ?? null);
      setSelectedKnowledgeBaseId(result.knowledgeBaseId ?? null);
      setActiveGenerationJobId(result.jobId);
      setIsTestingHistoryOpen(false);
      toast({
        title: "加载成功",
        description: `已加载历史文件 #${result.jobId}`,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : "加载历史文件失败";
      toast({
        title: "加载失败",
        description: message,
        variant: "destructive",
      });
    }
  };

  const handleDeleteTestingHistory = async (jobId: number) => {
    try {
      await deleteTestingGeneration(jobId);
      if (activeGenerationJobId === jobId) {
        setGeneration(null);
        setActiveGenerationJobId(null);
        setSelectedRequirementId(null);
      }
      await loadTestingHistory();
      toast({
        title: "删除成功",
        description: "历史文件已删除。",
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : "删除历史文件失败";
      toast({
        title: "删除失败",
        description: message,
        variant: "destructive",
      });
    }
  };

  const applyTestingGenerationResult = async (jobId: number) => {
    const result = await getTestingGenerationResult(jobId);
    const normalized = normalizeGeneratedFile(result.generatedFile);
    if (!normalized) {
      throw new Error("生成结果格式不正确");
    }

    const file: TestingGenerationFile = {
      ...normalized,
      sourceJobId: result.sourceJobId ?? normalized.sourceJobId ?? null,
      knowledgeBaseId: result.knowledgeBaseId ?? normalized.knowledgeBaseId ?? null,
      knowledgeBaseName: selectedKnowledgeBaseName,
    };

    setGeneration(file);
    setSelectedRequirementId(file.requirements[0]?.id ?? null);
    setActiveGenerationJobId(jobId);
    await loadTestingHistory();
    return file;
  };

  const handleGenerate = async () => {
    if (!requirementData) {
      toast({
        title: "缺少输入",
        description: "请先上传并解析需求 JSON 文件。",
        variant: "destructive",
      });
      return;
    }

    setIsGenerating(true);
    setGenerationProgress("准备开始...");
    try {
      const generatedRequirements: GeneratedRequirement[] = [];

      for (let index = 0; index < requirementData.requirements.length; index += 1) {
        const req = requirementData.requirements[index];
        setGenerationProgress(`正在生成 ${index + 1}/${requirementData.requirements.length}：${req.id}`);

        const description = req.description.trim();
        if (!description) {
          generatedRequirements.push({
            ...req,
            "测试项": [],
            "测试用例": [],
            "预期结果": [],
          });
          continue;
        }

        const result = await generateTestingContent(description, selectedKnowledgeBaseId ?? undefined);
        const testItems = flattenRecord(result.test_items).map((item) => ({
          id: item.id,
          content: item.content,
        }));
        const testCases = flattenRecord(result.test_cases).map((item) => ({
          id: item.id,
          itemId: item.item_id,
          testContent: item.test_content,
          operationSteps: item.operation_steps,
          expectedResultPlaceholder: item.expected_result_placeholder,
        }));
        const expectedResults = flattenRecord(result.expected_results).map((item) => ({
          id: item.id,
          caseId: item.case_id,
          result: item.result,
        }));

        generatedRequirements.push({
          ...req,
          "测试项": testItems,
          "测试用例": testCases,
          "预期结果": expectedResults,
        });
      }

      const generatedAt = new Date().toISOString();
      const file: TestingGenerationFile = {
        sourceDocument: requirementData.documentName,
        sourceJobId: sourceSrsJobId,
        generatedAt,
        totalRequirements: generatedRequirements.length,
        knowledgeBaseId: selectedKnowledgeBaseId,
        knowledgeBaseName: selectedKnowledgeBaseName,
        requirements: generatedRequirements,
      };

      setGeneration(file);
      setSelectedRequirementId(file.requirements[0]?.id ?? null);
      setActiveGenerationJobId(null);

      const payload: TestingGenerationSaveRequest = {
        source_document_name: file.sourceDocument,
        generated_file: file as unknown as Record<string, unknown>,
      };
      if (sourceSrsJobId !== null) {
        payload.source_job_id = sourceSrsJobId;
      }
      if (selectedKnowledgeBaseId !== null) {
        payload.knowledge_base_id = selectedKnowledgeBaseId;
      }

      try {
        const saved = await saveTestingGeneration(payload);
        setActiveGenerationJobId(saved.jobId);
        await loadTestingHistory();
        toast({
          title: "生成完成",
          description: `已处理 ${generatedRequirements.length} 条需求，并保存到历史文件。`,
        });
      } catch (saveError) {
        const saveMessage =
          saveError instanceof Error ? saveError.message : "历史文件保存失败";
        toast({
          title: "生成完成",
          description: `已处理 ${generatedRequirements.length} 条需求，但未保存到历史文件：${saveMessage}`,
          variant: "destructive",
        });
      }
    } catch (error) {
      const message = error instanceof Error ? error.message : "生成失败，请重试";
      toast({
        title: "生成失败",
        description: message,
        variant: "destructive",
      });
    } finally {
      setIsGenerating(false);
      setGenerationProgress("");
    }
  };

  const handleGenerateWithJob = async () => {
    if (!requirementData) {
      toast({
        title: "缺少输入",
        description: "请先上传并解析需求 JSON 文件。",
        variant: "destructive",
      });
      return;
    }

    setIsGenerating(true);
    setGeneration(null);
    setSelectedRequirementId(null);
    setGenerationProgress("准备提交生成任务...");

    try {
      const created = await createTestingGenerationJob({
        source_document_name: requirementData.documentName,
        source_job_id: sourceSrsJobId ?? undefined,
        knowledge_base_id: selectedKnowledgeBaseId ?? undefined,
        requirements: requirementData.requirements.map((item, index) => ({
          id: item.id,
          description: item.description,
          priority: item.priority,
          acceptanceCriteria: item.acceptanceCriteria,
          sourceField: item.sourceField,
          sectionUid: item.sectionUid,
          sectionNumber: item.sectionNumber,
          sectionTitle: item.sectionTitle,
          requirementType: item.requirementType,
          interfaceName: item.interfaceName,
          interfaceType: item.interfaceType,
          dataSource: item.dataSource,
          dataDestination: item.dataDestination,
          sortOrder: typeof item.sortOrder === "number" ? item.sortOrder : index,
        })),
      });

      setActiveGenerationJobId(created.job_id);

      let pollCount = 0;
      while (true) {
        pollCount += 1;
        const status = await getTestingGenerationJobStatus(created.job_id);

        if (status.status === "pending") {
          setGenerationProgress("任务排队中...");
        } else if (status.status === "processing") {
          const currentStep = status.current_step ?? 0;
          const totalSteps = status.total_steps ?? requirementData.requirements.length;
          const currentRequirementId = status.current_requirement_id ?? "";
          setGenerationProgress(
            currentRequirementId
              ? `正在生成 ${currentStep}/${totalSteps}：${currentRequirementId}`
              : `正在生成 ${currentStep}/${totalSteps}`
          );
        } else if (status.status === "failed") {
          throw new Error(status.error_message || "生成任务失败");
        } else if (status.status === "completed") {
          setGenerationProgress("正在加载生成结果...");
          const result = await getTestingGenerationResult(created.job_id);
          const normalized = normalizeGeneratedFile(result.generatedFile);
          if (!normalized) {
            throw new Error("生成结果格式不正确");
          }

          const file: TestingGenerationFile = {
            ...normalized,
            sourceJobId: result.sourceJobId ?? normalized.sourceJobId ?? null,
            knowledgeBaseId: result.knowledgeBaseId ?? normalized.knowledgeBaseId ?? null,
            knowledgeBaseName: selectedKnowledgeBaseName,
          };

          setGeneration(file);
          setSelectedRequirementId(file.requirements[0]?.id ?? null);
          await loadTestingHistory();
          toast({
            title: "生成完成",
            description: `已处理 ${file.totalRequirements} 条需求，并保存到历史文件。`,
          });
          return;
        }

        if (pollCount % 5 === 0) {
          try {
            const file = await applyTestingGenerationResult(created.job_id);
            toast({
              title: "生成完成",
              description: `已处理 ${file.totalRequirements} 条需求，并保存到历史文件。`,
            });
            return;
          } catch {
            await loadTestingHistory();
          }
        }

        await sleep(3000);
      }
    } catch (error) {
      const message = error instanceof Error ? error.message : "生成失败，请重试";
      toast({
        title: "生成失败",
        description: message,
        variant: "destructive",
      });
    } finally {
      setIsGenerating(false);
      setGenerationProgress("");
    }
  };

  const handleExportJson = () => {
    if (!generation) {
      return;
    }

    const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
    downloadJson(`testing-generation-${timestamp}.json`, generation);
    toast({
      title: "导出成功",
      description: "生成结果 JSON 已下载。",
    });
  };

  const getKnowledgeBaseName = (kbId?: number | null) => {
    if (!kbId) {
      return "未使用";
    }
    const kb = knowledgeBases.find((item) => item.id === kbId);
    return kb?.name || `知识库 #${kbId}`;
  };

  return (
    <DashboardLayout>
      <div className="space-y-6">
        <Card>
          <CardHeader>
            <CardTitle className="text-2xl">文档处理 · 测试用例生成</CardTitle>
            <CardDescription>
              上传或选择历史需求文件，按每条需求描述生成测试项、测试用例与预期结果。
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            <div
              {...getRootProps()}
              className={cn(
                "rounded-lg border-2 border-dashed p-8 text-center transition-colors",
                isDragActive
                  ? "border-primary bg-primary/5"
                  : "border-border hover:border-primary/40"
              )}
            >
              <input {...getInputProps()} />
              <Upload className="mx-auto h-10 w-10 text-muted-foreground" />
              <p className="mt-3 text-sm font-medium">拖拽上传需求 JSON 文件</p>
              <p className="text-xs text-muted-foreground mt-1">支持 .json</p>
              {inputFile && (
                <div className="mt-4 inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs">
                  <FileJson className="h-3.5 w-3.5" />
                  {inputFile.name}
                </div>
              )}
            </div>

            <div className="flex flex-wrap gap-3">
              <Button variant="outline" onClick={handleChooseFile} disabled={isParsing}>
                {isParsing ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <FileJson className="mr-2 h-4 w-4" />
                )}
                选择 JSON 文件
              </Button>

              <Dialog open={isSrsHistoryOpen} onOpenChange={setIsSrsHistoryOpen}>
                <DialogTrigger asChild>
                  <Button variant="outline" onClick={() => void loadSrsHistory()}>
                    <History className="mr-2 h-4 w-4" />
                    需求提取历史
                  </Button>
                </DialogTrigger>
                <DialogContent className="max-w-3xl">
                  <DialogHeader>
                    <DialogTitle>选择需求提取历史文件</DialogTitle>
                    <DialogDescription>
                      选择“需求提取”页面已生成的历史文件作为当前输入来源。
                    </DialogDescription>
                  </DialogHeader>
                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead>文档名称</TableHead>
                        <TableHead>需求数</TableHead>
                        <TableHead>提取时间</TableHead>
                        <TableHead className="text-right">操作</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {isSrsHistoryLoading && (
                        <TableRow>
                          <TableCell colSpan={4} className="text-center text-muted-foreground">
                            正在加载历史文件...
                          </TableCell>
                        </TableRow>
                      )}
                      {!isSrsHistoryLoading && srsHistoryItems.length === 0 && (
                        <TableRow>
                          <TableCell colSpan={4} className="text-center text-muted-foreground">
                            暂无历史文件
                          </TableCell>
                        </TableRow>
                      )}
                      {!isSrsHistoryLoading &&
                        srsHistoryItems.map((item) => (
                          <TableRow key={item.jobId}>
                            <TableCell>{item.documentName}</TableCell>
                            <TableCell>{item.totalRequirements}</TableCell>
                            <TableCell>{formatDateTime(item.generatedAt)}</TableCell>
                            <TableCell className="text-right">
                              <Button
                                size="sm"
                                variant="outline"
                                onClick={() => void handleLoadSrsHistory(item.jobId)}
                              >
                                选择
                              </Button>
                            </TableCell>
                          </TableRow>
                        ))}
                    </TableBody>
                  </Table>
                </DialogContent>
              </Dialog>

              <Dialog open={isKbDialogOpen} onOpenChange={setIsKbDialogOpen}>
                <DialogTrigger asChild>
                  <Button variant="outline" onClick={() => void loadKnowledgeBaseList()}>
                    <Database className="mr-2 h-4 w-4" />
                    选择知识库
                  </Button>
                </DialogTrigger>
                <DialogContent className="max-w-3xl">
                  <DialogHeader>
                    <DialogTitle>选择知识库</DialogTitle>
                    <DialogDescription>
                      生成时将基于所选知识库增强内容。不选择则仅按需求文本生成。
                    </DialogDescription>
                  </DialogHeader>

                  <div className="flex justify-end">
                    <Button
                      variant="secondary"
                      size="sm"
                      onClick={() => {
                        setSelectedKnowledgeBaseId(null);
                        setIsKbDialogOpen(false);
                      }}
                    >
                      不使用知识库
                    </Button>
                  </div>

                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead>知识库名称</TableHead>
                        <TableHead>描述</TableHead>
                        <TableHead className="text-right">操作</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {isKbLoading && (
                        <TableRow>
                          <TableCell colSpan={3} className="text-center text-muted-foreground">
                            正在加载知识库...
                          </TableCell>
                        </TableRow>
                      )}
                      {!isKbLoading && knowledgeBases.length === 0 && (
                        <TableRow>
                          <TableCell colSpan={3} className="text-center text-muted-foreground">
                            暂无可用知识库
                          </TableCell>
                        </TableRow>
                      )}
                      {!isKbLoading &&
                        knowledgeBases.map((item) => (
                          <TableRow key={item.id}>
                            <TableCell>{item.name}</TableCell>
                            <TableCell className="text-muted-foreground">
                              {item.description || "-"}
                            </TableCell>
                            <TableCell className="text-right">
                              <Button
                                size="sm"
                                variant={selectedKnowledgeBaseId === item.id ? "secondary" : "outline"}
                                onClick={() => {
                                  setSelectedKnowledgeBaseId(item.id);
                                  setIsKbDialogOpen(false);
                                }}
                              >
                                {selectedKnowledgeBaseId === item.id ? "已选择" : "选择"}
                              </Button>
                            </TableCell>
                          </TableRow>
                        ))}
                    </TableBody>
                  </Table>
                </DialogContent>
              </Dialog>

              <Button onClick={handleGenerateWithJob} disabled={!requirementData || isGenerating}>
                {isGenerating ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <Sparkles className="mr-2 h-4 w-4" />
                )}
                生成测试用例
              </Button>

              <Button variant="outline" onClick={handleExportJson} disabled={!generation}>
                <Download className="mr-2 h-4 w-4" />
                导出 JSON
              </Button>

              <Dialog open={isTestingHistoryOpen} onOpenChange={setIsTestingHistoryOpen}>
                <DialogTrigger asChild>
                  <Button variant="outline" onClick={() => void loadTestingHistory()}>
                    <History className="mr-2 h-4 w-4" />
                    生成历史
                  </Button>
                </DialogTrigger>
                <DialogContent className="max-w-4xl">
                  <DialogHeader>
                    <DialogTitle>测试生成历史文件</DialogTitle>
                    <DialogDescription>
                      支持查看、加载、删除历史生成文件。
                    </DialogDescription>
                  </DialogHeader>
                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead>来源文档</TableHead>
                        <TableHead>需求数</TableHead>
                        <TableHead>知识库</TableHead>
                        <TableHead>生成时间</TableHead>
                        <TableHead className="text-right">操作</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {isTestingHistoryLoading && (
                        <TableRow>
                          <TableCell colSpan={5} className="text-center text-muted-foreground">
                            正在加载历史文件...
                          </TableCell>
                        </TableRow>
                      )}
                      {!isTestingHistoryLoading && testingHistoryItems.length === 0 && (
                        <TableRow>
                          <TableCell colSpan={5} className="text-center text-muted-foreground">
                            暂无历史文件
                          </TableCell>
                        </TableRow>
                      )}
                      {!isTestingHistoryLoading &&
                        testingHistoryItems.map((item) => (
                          <TableRow key={item.jobId}>
                            <TableCell>{item.sourceDocumentName}</TableCell>
                            <TableCell>{item.totalRequirements}</TableCell>
                            <TableCell>{getKnowledgeBaseName(item.knowledgeBaseId)}</TableCell>
                            <TableCell>{formatDateTime(item.generatedAt)}</TableCell>
                            <TableCell className="text-right">
                              <div className="flex justify-end gap-2">
                                <Button
                                  size="sm"
                                  variant="outline"
                                  onClick={() => void handleLoadTestingHistory(item.jobId)}
                                >
                                  查看
                                </Button>
                                <Button
                                  size="sm"
                                  variant="destructive"
                                  onClick={() => void handleDeleteTestingHistory(item.jobId)}
                                >
                                  <Trash2 className="mr-1 h-3.5 w-3.5" />
                                  删除
                                </Button>
                              </div>
                            </TableCell>
                          </TableRow>
                        ))}
                    </TableBody>
                  </Table>
                </DialogContent>
              </Dialog>

              <input
                ref={fileInputRef}
                type="file"
                accept="application/json,.json"
                className="hidden"
                onChange={handleFileInput}
              />
            </div>

            {requirementData && (
              <div className="space-y-1 text-sm text-muted-foreground">
                <p>
                  来源: {requirementData.documentName} · 需求数: {requirementData.requirements.length}
                </p>
                <p>知识库: {selectedKnowledgeBaseName}</p>
                {generationProgress && <p>{generationProgress}</p>}
              </div>
            )}
          </CardContent>
        </Card>

        <div className="grid gap-6 lg:grid-cols-[360px_1fr]">
          <Card className="min-h-[500px]">
            <CardHeader>
              <CardTitle className="text-lg">需求列表</CardTitle>
              <CardDescription>每条需求都新增测试项、测试用例、预期结果字段</CardDescription>
            </CardHeader>
            <CardContent>
              {!generation && (
                <div className="rounded-lg border border-dashed p-6 text-sm text-muted-foreground text-center">
                  暂无生成结果，请先选择输入并执行生成。
                </div>
              )}

              {generation && (
                <div className="space-y-3 max-h-[520px] overflow-y-auto pr-1">
                  {generation.requirements.map((item) => {
                    const active = item.id === selectedRequirementId;
                    return (
                      <button
                        key={item.id}
                        onClick={() => setSelectedRequirementId(item.id)}
                        className={cn(
                          "w-full rounded-lg border p-3 text-left transition-colors",
                          active
                            ? "border-primary bg-primary/5"
                            : "hover:border-primary/40"
                        )}
                      >
                        <div className="flex items-center justify-between gap-2">
                          <p className="text-sm font-medium line-clamp-1">
                            {item.title || item.description || item.id}
                          </p>
                          <Badge>{item.priority}</Badge>
                        </div>
                        <p className="mt-2 text-xs text-muted-foreground">
                          {item.id} · 测试项 {item["测试项"].length} · 用例 {item["测试用例"].length}
                        </p>
                      </button>
                    );
                  })}
                </div>
              )}
            </CardContent>
          </Card>

          <Card className="min-h-[500px]">
            <CardHeader>
              <CardTitle className="text-lg">生成详情</CardTitle>
              <CardDescription>查看当前需求项的测试项、测试用例与预期结果</CardDescription>
            </CardHeader>
            <CardContent>
              {!selectedRequirement && (
                <div className="rounded-lg border border-dashed p-6 text-sm text-muted-foreground text-center">
                  请选择左侧需求项。
                </div>
              )}

              {selectedRequirement && (
                <div className="space-y-5">
                  <div>
                    <h3 className="text-base font-semibold">
                      {selectedRequirement.title || selectedRequirement.id}
                    </h3>
                    <p className="text-sm text-muted-foreground mt-1">
                      需求编号: {selectedRequirement.id}
                    </p>
                  </div>

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

                  <div>
                    <h4 className="text-sm font-medium mb-2">测试项</h4>
                    <ul className="space-y-2 text-sm text-muted-foreground">
                      {selectedRequirement["测试项"].map((line, index) => (
                        <li key={`${selectedRequirement.id}-item-${line.id}`} className="rounded-md border p-2">
                          {index + 1}. {line.content || line.id}
                        </li>
                      ))}
                      {selectedRequirement["测试项"].length === 0 && (
                        <li className="rounded-md border border-dashed p-2">暂无测试项</li>
                      )}
                    </ul>
                  </div>

                  <div>
                    <h4 className="text-sm font-medium mb-2">测试用例</h4>
                    <ul className="space-y-2 text-sm text-muted-foreground">
                      {selectedRequirement["测试用例"].map((item, index) => (
                        <li key={`${selectedRequirement.id}-case-${item.id}`} className="rounded-md border p-2">
                          <p className="font-medium text-foreground">{index + 1}. {item.testContent || item.id}</p>
                          <p className="mt-1">步骤: {item.operationSteps.join("；") || "-"}</p>
                          <p className="mt-1">占位预期: {item.expectedResultPlaceholder || "-"}</p>
                        </li>
                      ))}
                      {selectedRequirement["测试用例"].length === 0 && (
                        <li className="rounded-md border border-dashed p-2">暂无测试用例</li>
                      )}
                    </ul>
                  </div>

                  <div>
                    <h4 className="text-sm font-medium mb-2">预期结果</h4>
                    <ul className="space-y-2 text-sm text-muted-foreground">
                      {selectedRequirement["预期结果"].map((item, index) => (
                        <li key={`${selectedRequirement.id}-expected-${item.id}`} className="rounded-md border p-2">
                          {index + 1}. {item.result || item.id}
                        </li>
                      ))}
                      {selectedRequirement["预期结果"].length === 0 && (
                        <li className="rounded-md border border-dashed p-2">暂无预期结果</li>
                      )}
                    </ul>
                  </div>

                  <div>
                    <h4 className="text-sm font-medium mb-2">JSON 预览</h4>
                    <pre className="max-h-[220px] overflow-auto rounded-md border bg-muted/40 p-3 text-xs text-foreground whitespace-pre-wrap break-words">
                      {JSON.stringify(selectedRequirement, null, 2)}
                    </pre>
                  </div>
                </div>
              )}
            </CardContent>
          </Card>
        </div>
      </div>
    </DashboardLayout>
  );
}
