import { describe, expect, it, vi } from 'vitest';

import { createUploadEditCoordinator } from './uploadEditCoordinator';

const context = (field: string, recordId = 'record') => ({ modelId: 'model', recordId, field, taskId: 'task' });
const value = (field: string) => ({ draftId: field, revision: 1, files: [] });

describe('dMS form attachment coordinator', () => {
  it('batches positions while preserving each result and makes a fresh request for submission', async () => {
    const load = vi.fn(async (contexts) => ({ data: contexts.map((item: any) => value(item.field)) }));
    const coordinator = createUploadEditCoordinator(load);
    const result = await Promise.all([coordinator.loadShared(context('main')), coordinator.loadShared(context('child'))]);
    expect(load).toHaveBeenCalledTimes(1);
    expect(result.map((item) => item.data.draftId)).toEqual(['main', 'child']);
    await coordinator.loadShared(context('main'));
    expect(load).toHaveBeenCalledTimes(2);
  });
  it('does not combine different records, swallow denial, or return partial batch results', async () => {
    const load = vi.fn(async () => ({ data: [value('file')] }));
    const coordinator = createUploadEditCoordinator(load);
    await Promise.all([coordinator.loadShared(context('main')), coordinator.loadShared(context('main', 'other'))]);
    expect(load).toHaveBeenCalledTimes(2);
    const partial = await Promise.allSettled([coordinator.loadShared(context('main')), coordinator.loadShared(context('child'))]);
    expect(partial.every((item) => item.status === 'rejected')).toBe(true);
    load.mockRejectedValueOnce(new Error('denied'));
    await expect(coordinator.loadShared(context('main'))).rejects.toThrow('denied');
  });
  it('waits for editor finalization before preparing the confirmed manifest', async () => {
    const coordinator = createUploadEditCoordinator(vi.fn());
    let finish!: () => void;
    const closing = new Promise<void>((resolve) => {
      finish = resolve;
    });
    const prepare = vi.fn(async () => undefined);
    const work = coordinator.prepare([{ settle: () => closing, prepare }]);
    await Promise.resolve();
    expect(prepare).not.toHaveBeenCalled();
    finish();
    await work;
    expect(prepare).toHaveBeenCalledOnce();
  });
  it('rejects pending and new reads after disposal', async () => {
    const coordinator = createUploadEditCoordinator(vi.fn());
    const pending = coordinator.loadShared(context('main'));
    coordinator.dispose();
    await expect(pending).rejects.toThrow('表单已关闭');
    await expect(coordinator.loadShared(context('main'))).rejects.toThrow('表单已关闭');
  });
});
