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

import { createLlmClient } from "../core/llm-client.ts";
import { extractProcurementListFromMultimodalInputs } from "./procurement-extraction-llm.ts";

vi.mock("../core/llm-client.ts", async (importOriginal) => {
  const actual = await importOriginal<typeof import("../core/llm-client.ts")>();
  return {
    ...actual,
    createLlmClient: vi.fn(),
  };
});

const createMock = vi.mocked(createLlmClient);

function makeRuntime(content: string) {
  const completionsCreate = vi.fn().mockResolvedValue({
    choices: [{ message: { content } }],
  });
  return {
    client: {
      chat: {
        completions: {
          create: completionsCreate,
        },
      },
    },
    config: {
      baseURL: "https://api.xiaomimimo.com/v1",
      apiKey: "redacted",
      model: "mimo-v2.5",
      provider: "mimo",
    },
  } as unknown as Awaited<ReturnType<typeof createLlmClient>>;
}

const validResponse = JSON.stringify({
  file_profile: {
    file_type: "image",
    document_title: "",
    drawing_no: "",
    page_count: 1,
    diagnostics: [],
  },
  purchase_objects: [
    {
      object_role: "primary_item",
      original_name: "塑料保护罩覆盖",
      recommended_name: "螺栓孔塑料保护罩",
      fields: {
        specification: "盾构区间螺栓保护罩",
        material_requirement: "低烟无卤原生材料",
        technical_requirement: "燃烧性能不低于 B1 级",
        test_requirement: "按 GB8624-2012 5.2.3 检测",
        technical_standard: "GB8624-2012",
        applicable_conditions: "盾构区间",
        main_dimensions: "",
        tolerance: "",
        performance_indicators: "氧指数 >=23",
        accessory_materials: "",
        supply_form: "",
        acceptance_documents: "",
        quantity: 130000,
        unit: "个",
        invoice_type: "13%专票",
        delivery_address: "江苏省南京市建邺区",
        remarks: "",
        pending_confirmations: [],
      },
      evidence: [],
      warnings: [],
      confidence: 0.9,
    },
  ],
  warnings: [],
});

describe("extractProcurementListFromMultimodalInputs", () => {
  afterEach(() => {
    vi.clearAllMocks();
  });

  it("uses the document_extraction stage provider config and sends a multimodal JSON request", async () => {
    const runtime = makeRuntime(validResponse);
    createMock.mockResolvedValue(runtime);
    const completionsCreate = runtime.client.chat.completions.create as ReturnType<typeof vi.fn>;

    const result = await extractProcurementListFromMultimodalInputs({
      fileProfiles: [
        {
          source_file_name: "塑料保护罩覆盖.pdf",
          file_type: "cad_drawing_pdf",
          document_title: "嵌缝与螺栓防水构造图",
          drawing_no: "005A",
          page_count: 1,
          diagnostics: ["文本层较少"],
        },
      ],
      imageInputs: [
        {
          source_file_name: "塑料保护罩覆盖.pdf",
          source_type: "pdf_render",
          label: "PDF 首页高清裁剪图",
          dataUrl: "data:image/png;base64,cGRm",
        },
      ],
      excelRows: [],
    });

    expect(createMock).toHaveBeenCalledWith({ maxRetries: 2, stage: "document_extraction" });
    expect(result.model).toBe("mimo-v2.5");
    expect(result.provider).toBe("mimo");
    expect(result.payload.purchase_objects[0]?.fields.performance_indicators).toBe("氧指数 >=23");
    expect(completionsCreate).toHaveBeenCalledWith(expect.objectContaining({
      model: "mimo-v2.5",
      response_format: { type: "json_object" },
    }));
    const request = completionsCreate.mock.calls[0]?.[0] as {
      messages: Array<{ role: string; content: unknown }>;
    };
    const userContent = request.messages[1]?.content as Array<Record<string, unknown>>;
    expect(userContent[0]).toEqual({
      type: "image_url",
      image_url: { url: "data:image/png;base64,cGRm" },
    });
  });

  it("fails clearly when the multimodal model returns invalid JSON", async () => {
    const runtime = makeRuntime("无法识别图片");
    createMock.mockResolvedValue(runtime);

    await expect(extractProcurementListFromMultimodalInputs({
      fileProfiles: [],
      imageInputs: [
        {
          source_file_name: "附件.jpeg",
          source_type: "image",
          label: "性能指标图",
          dataUrl: "data:image/jpeg;base64,anBlZw==",
        },
      ],
      excelRows: [],
    })).rejects.toThrow(/采购清单多模态模型返回内容不是合法 JSON/);
  });
});
