import { describe, it, expect } from 'vitest';
import { runDirectUpload } from './runDirectUpload';
import type { DirectUploadGateway } from './ports';
import type { DirectContext, DirectEvent, StagedFile } from '../domain';

const sf = (p: string): StagedFile => ({ name: p.slice(p.lastIndexOf('/') + 1), relativePath: p, size: 1 });
const ctx = (files: StagedFile[]): DirectContext => ({
  dataType: 'dicom',
  groupByStudy: false,
  files,
  progress: 0,
  errors: [],
  createdTaskIds: [],
});

const okGateway: DirectUploadGateway = {
  async upload() {
    return { uploadedCount: 0, dedupedCount: 0, paths: [] };
  },
};

describe('runDirectUpload (application use-case)', () => {
  it('dispatches only VALIDATE_FAIL when staging is invalid (no files)', async () => {
    const events: DirectEvent[] = [];
    await runDirectUpload({ gateway: okGateway, datasetId: 'd1', context: ctx([]), files: [], dispatch: (e) => events.push(e) });
    expect(events.map((e) => e.type)).toEqual(['VALIDATE_FAIL']);
  });

  it('on success: VALIDATE_OK -> UPLOAD_PROGRESS -> UPLOAD_OK -> PROCESS_OK(paths)', async () => {
    const events: DirectEvent[] = [];
    const gateway: DirectUploadGateway = {
      async upload({ onProgress }) {
        onProgress?.(50);
        return { uploadedCount: 2, dedupedCount: 1, paths: ['a.dcm', 'b.dcm'] };
      },
    };
    await runDirectUpload({
      gateway,
      datasetId: 'd1',
      context: ctx([sf('a.dcm'), sf('b.dcm')]),
      files: [],
      dispatch: (e) => events.push(e),
    });
    expect(events.map((e) => e.type)).toEqual(['VALIDATE_OK', 'UPLOAD_PROGRESS', 'UPLOAD_OK', 'PROCESS_OK']);
    const done = events.find((e) => e.type === 'PROCESS_OK');
    expect(done?.type === 'PROCESS_OK' && done.taskIds).toEqual(['a.dcm', 'b.dcm']);
  });

  it('on gateway throw: VALIDATE_OK -> UPLOAD_FAIL with a GATEWAY_ERROR', async () => {
    const events: DirectEvent[] = [];
    const gateway: DirectUploadGateway = {
      async upload() {
        throw new Error('boom');
      },
    };
    await runDirectUpload({ gateway, datasetId: 'd1', context: ctx([sf('a.dcm')]), files: [], dispatch: (e) => events.push(e) });
    expect(events.map((e) => e.type)).toEqual(['VALIDATE_OK', 'UPLOAD_FAIL']);
    const fail = events.find((e) => e.type === 'UPLOAD_FAIL');
    expect(fail?.type === 'UPLOAD_FAIL' && fail.errors?.[0].code).toBe('GATEWAY_ERROR');
  });
});
