import { describe, expect, it, vi } from "vitest";
import { detail } from "../../documents/__tests__/fixtures";
import {
  applyBatchResult,
  createBatchDraft,
  createExclusiveRunner,
  retainFailedDrafts,
} from "../mutationState";

const fileA = new File(["a"], "a.pdf");
const fileB = new File(["b"], "b.pdf");

describe("batch state and duplicate-submit protection", () => {
  it("拖入/选择文件创建稳定顺序的草稿，待上传项可删除", () => {
    const drafts = [
      createBatchDraft(fileA, { documentName: "A" }),
      createBatchDraft(fileB, { documentName: "B" }),
    ];
    expect(drafts.map((draft) => draft.file.name)).toEqual(["a.pdf", "b.pdf"]);
    expect(drafts.filter((draft) => draft.key !== drafts[0].key)).toHaveLength(1);
  });

  it("HTTP 200批量结果仍逐项区分部分成功", () => {
    const drafts = [
      createBatchDraft(fileA, { documentName: "A" }),
      createBatchDraft(fileB, { documentName: "B" }),
    ];
    const applied = applyBatchResult(drafts, {
      total: 2,
      successCount: 1,
      failureCount: 1,
      items: [
        { index: 0, originalFileName: "a.pdf", success: true, document: detail },
        { index: 1, originalFileName: "b.pdf", success: false, errorCode: "UNSUPPORTED_FILE_TYPE", errorMessage: "不支持" },
      ],
    });
    expect(applied[0].result?.success).toBe(true);
    expect(applied[1].result?.success).toBe(false);
    expect(retainFailedDrafts(applied).map((draft) => draft.file.name)).toEqual(["b.pdf"]);
  });

  it("全成功、全失败和结果无法对应均有明确行为", () => {
    const draft = createBatchDraft(fileA, { documentName: "A" });
    expect(retainFailedDrafts(applyBatchResult([draft], {
      total: 1, successCount: 1, failureCount: 0,
      items: [{ index: 0, originalFileName: "a.pdf", success: true, document: detail }],
    }))).toEqual([]);
    expect(retainFailedDrafts(applyBatchResult([draft], {
      total: 1, successCount: 0, failureCount: 1,
      items: [{ index: 0, originalFileName: "a.pdf", success: false, errorCode: "X", errorMessage: "失败" }],
    }))).toHaveLength(1);
    expect(() => applyBatchResult([draft], { total: 0, successCount: 0, failureCount: 0, items: [] })).toThrow("无法对应");
  });

  it("同一runner在请求结束前忽略重复提交", async () => {
    const run = createExclusiveRunner();
    let resolve!: (value: string) => void;
    const operation = vi.fn(() => new Promise<string>((done) => { resolve = done; }));
    const first = run(operation);
    await expect(run(operation)).resolves.toBeUndefined();
    expect(operation).toHaveBeenCalledTimes(1);
    resolve("ok");
    await expect(first).resolves.toBe("ok");
  });
});
