import { describe, expect, it } from "vitest";

import {
  parseDocumentMaterialExtractionPayload,
  toProcurementMaterialInsert,
} from "./document-extraction-contract.ts";

describe("parseDocumentMaterialExtractionPayload", () => {
  it("normalizes valid JSON into the fixed English-field extraction contract", () => {
    const parsed = parseDocumentMaterialExtractionPayload(JSON.stringify({
      items: [
        {
          material_name: " 球墨铸铁井盖 ",
          specification: "DN700",
          quantity: 12,
          unit: "套",
          technical_standard: "GB/T 23858",
          material_requirement: "QT500-7",
          technical_requirement: "承重 D400",
          applicable_conditions: "市政道路",
          test_requirement: "出厂检测",
          acceptance_note: "按图验收",
          warranty_period: "2年",
          deadline: "2026-05-10",
          invoice_type: "增值税专用发票",
          brand: "不限",
          remarks: "含防盗链",
          delivery_address: "上海仓库",
        },
      ],
      extraction_summary: "提取 1 项",
      warnings: ["品牌未指定"],
    }));

    expect(parsed).toEqual({
      items: [
        {
          material_name: "球墨铸铁井盖",
          specification: "DN700",
          quantity: 12,
          unit: "套",
          technical_standard: "GB/T 23858",
          material_requirement: "QT500-7",
          technical_requirement: "承重 D400",
          applicable_conditions: "市政道路",
          test_requirement: "出厂检测",
          acceptance_note: "按图验收",
          warranty_period: "2年",
          deadline: "2026-05-10",
          invoice_type: "增值税专用发票",
          brand: "",
          remarks: "含防盗链",
          delivery_address: "上海仓库",
        },
      ],
      extraction_summary: "提取 1 项",
      warnings: ["品牌未指定"],
    });
  });

  it("parses quantity strings and filters rows without a material name", () => {
    const parsed = parseDocumentMaterialExtractionPayload({
      items: [
        {
          material_name: "镀锌钢管",
          quantity: "1,200.5 米",
          unit: "米",
        },
        {
          material_name: "  ",
          quantity: "99",
          unit: "个",
        },
      ],
      extraction_summary: null,
      warnings: [123, "注意复核数量"],
    });

    expect(parsed.items).toHaveLength(1);
    expect(parsed.items[0]?.quantity).toBe(1200.5);
    expect(parsed.items[0]?.specification).toBe("");
    expect(parsed.warnings).toEqual(["123", "注意复核数量"]);
    expect(parsed.extraction_summary).toBe("提取了 1 项物料");
  });

  it("normalizes Chinese field aliases returned by the model", () => {
    const parsed = parseDocumentMaterialExtractionPayload({
      items: [
        {
          名称: "塑料保护罩",
          规格型号: "200x150x100mm",
          数量: "500",
          单位: "个",
          材质要求: "ABS材质",
          技术要求: "壁厚2mm，防尘防水IP65",
          "备注/附件": "覆盖设备顶部接口",
        },
        {
          名称: "密封胶圈",
          规格型号: "200x150mm",
          数量: "500",
          单位: "件",
          材质要求: "硅胶材质",
          技术要求: "耐高温150℃",
          "备注/附件": "配合保护罩使用",
        },
      ],
      extraction_summary: "从文档中提取了2项物料。",
    });

    expect(parsed.items).toEqual([
      expect.objectContaining({
        material_name: "塑料保护罩",
        specification: "200x150x100mm",
        quantity: 500,
        unit: "个",
        material_requirement: "ABS材质",
        technical_requirement: "壁厚2mm，防尘防水IP65",
        remarks: "覆盖设备顶部接口",
      }),
      expect.objectContaining({
        material_name: "密封胶圈",
        specification: "200x150mm",
        quantity: 500,
        unit: "件",
        material_requirement: "硅胶材质",
        technical_requirement: "耐高温150℃",
        remarks: "配合保护罩使用",
      }),
    ]);
  });

  it("throws a clear error for non-JSON model output", () => {
    expect(() => parseDocumentMaterialExtractionPayload("```json\n{}\n```"))
      .toThrow(/文档提取模型返回内容不是合法 JSON/);
  });

  it("throws a clear error when items is missing", () => {
    expect(() => parseDocumentMaterialExtractionPayload({ extraction_summary: "none", warnings: [] }))
      .toThrow(/items: Required/);
  });

  it("throws a clear error when all items are filtered out", () => {
    expect(() => parseDocumentMaterialExtractionPayload({ items: [{ material_name: "暂无" }], warnings: [] }))
      .toThrow(/文档提取结果为空/);
  });

  it("fills missing optional fields and filters empty warnings", () => {
    const parsed = parseDocumentMaterialExtractionPayload({
      items: [{ material_name: "桥架", quantity: "6 米" }],
      warnings: ["", "需复核规格"],
    });

    expect(parsed).toEqual({
      items: [
        {
          material_name: "桥架",
          specification: "",
          quantity: 6,
          unit: "",
          technical_standard: "",
          material_requirement: "",
          technical_requirement: "",
          applicable_conditions: "",
          test_requirement: "",
          acceptance_note: "",
          warranty_period: "",
          deadline: "",
          invoice_type: "",
          brand: "",
          remarks: "",
          delivery_address: "",
        },
      ],
      extraction_summary: "提取了 1 项物料",
      warnings: ["需复核规格"],
    });
  });
});

describe("toProcurementMaterialInsert", () => {
  it("converts contract items directly to procurement material insert rows", () => {
    const parsed = parseDocumentMaterialExtractionPayload({
      items: [{ material_name: "配电箱", quantity: "2", unit: "台", brand: "正泰" }],
      extraction_summary: "1 item",
      warnings: [],
    });

    expect(toProcurementMaterialInsert(parsed.items[0]!, {
      batchId: "batch-001",
      sourceFile: "清单.pdf",
      sourceFileId: "source-file-001",
      createdBy: "user-001",
    })).toEqual({
      material_name: "配电箱",
      specification: "",
      quantity: 2,
      unit: "台",
      technical_standard: "",
      material_requirement: "",
      technical_requirement: "",
      applicable_conditions: "",
      test_requirement: "",
      acceptance_note: "",
      warranty_period: "",
      deadline: "",
      invoice_type: "",
      brand: "正泰",
      remarks: "",
      delivery_address: "",
      source_file: "清单.pdf",
      source_file_id: "source-file-001",
      batch_id: "batch-001",
      created_by: "user-001",
    });
  });
});
