import { describe, expect, it, vi } from "vitest";
import { createAttachmentApi } from "../attachmentApi";
import { detail, result, summary } from "../../documents/__tests__/fixtures";

const attachment = {
  ...summary,
  id: "7",
  documentType: "ATTACHMENT" as const,
  attachmentType: "POLICY",
  mountedPlanCount: 2,
};
const page = { items: [attachment], page: 1, pageSize: 20, total: 1, totalPages: 1 };

describe("attachmentApi and F4-C1", () => {
  it("附件列表接受不含 fileSize 的 DocumentSummary，且不逐项请求详情", async () => {
    const client = { get: vi.fn().mockResolvedValue(result(page)) };
    const data = await createAttachmentApi(client).list({ keyword: "法规", page: 1, pageSize: 20 });
    expect(data.items[0]).not.toHaveProperty("fileSize");
    expect(client.get).toHaveBeenCalledTimes(1);
    expect(client.get).toHaveBeenCalledWith("attachments", {
      query: { keyword: "法规", page: 1, pageSize: 20 },
      signal: undefined,
    });
  });

  it("附件详情通过 /attachments/{id} 解析 fileSize", async () => {
    const attachmentDetail = { ...detail, ...attachment, originalFileName: "policy.pdf", fileSize: 4096 };
    const client = { get: vi.fn().mockResolvedValue(result(attachmentDetail)) };
    await expect(createAttachmentApi(client).detail("7")).resolves.toMatchObject({ id: "7", fileSize: 4096 });
    expect(client.get).toHaveBeenCalledWith("attachments/7", { signal: undefined });
  });

  it("反向挂载 MainPlanBrief 仅使用字符串主案 ID，不要求 bindingId", async () => {
    const brief = { id: "1", documentName: "主案", categoryName: "分类", securityLevel: "INTERNAL" };
    const client = { get: vi.fn().mockResolvedValue(result({ items: [brief], total: 1 })) };
    const data = await createAttachmentApi(client).mainPlans("7");
    expect(data).toEqual([brief]);
    expect(data[0]).not.toHaveProperty("bindingId");
    expect(client.get).toHaveBeenCalledWith("attachments/7/main-plans", { signal: undefined });
  });

  it("反向挂载拒绝 number 主案 ID", async () => {
    const client = { get: vi.fn().mockResolvedValue(result({ items: [{ id: 1, documentName: "主案", categoryName: null, securityLevel: "INTERNAL" }], total: 1 })) };
    await expect(createAttachmentApi(client).mainPlans("7")).rejects.toMatchObject({ code: "INTERNAL_ERROR" });
  });

  it("正向挂载严格解析字符串 bindingId 和整数 bindingSortNo", async () => {
    const binding = { ...attachment, bindingId: "19", bindingSortNo: 10 };
    const client = { get: vi.fn().mockResolvedValue(result({ ...page, items: [binding] })) };
    const data = await createAttachmentApi(client).mountedByMainPlan("1", { page: 1, pageSize: 20 });
    expect(data.items[0]).toMatchObject({ id: "7", bindingId: "19", bindingSortNo: 10 });
    expect(client.get).toHaveBeenCalledWith("main-plans/1/attachments", {
      query: { page: 1, pageSize: 20 },
      signal: undefined,
    });
  });

  it("已挂载附件透传类型、时间和分页组合", async () => {
    const binding = { ...attachment, bindingId: "19", bindingSortNo: 10 };
    const client = { get: vi.fn().mockResolvedValue(result({ ...page, items: [binding] })) };
    const query = {
      keyword: "法规",
      attachmentType: "POLICY" as const,
      updatedFrom: "2026-08-01T00:00:00.000Z",
      updatedTo: "2026-08-04T00:00:00.000Z",
      page: 2,
      pageSize: 20,
    };
    await createAttachmentApi(client).mountedByMainPlan("1", query);
    expect(client.get).toHaveBeenCalledWith("main-plans/1/attachments", {
      query,
      signal: undefined,
    });
  });

  it("正向挂载不放宽 binding DTO 校验", async () => {
    const client = { get: vi.fn().mockResolvedValue(result({ ...page, items: [{ ...attachment, bindingId: 19, bindingSortNo: "10" }] })) };
    await expect(createAttachmentApi(client).mountedByMainPlan("1", {})).rejects.toMatchObject({ code: "INTERNAL_ERROR" });
  });
});
