import { describe, it, expect } from 'vitest';
import { cloudReducer } from './reducer';
import { initialCloudMachine, type CloudEvent, type CloudMachine } from './states';

const run = (events: CloudEvent[]): CloudMachine => events.reduce(cloudReducer, initialCloudMachine);

describe('cloudReducer §4', () => {
  it('happy path: StorageNotReady -> Complete', () => {
    const m = run([
      { type: 'STORAGE_VERIFIED', storageMethodId: 'sm-1' },
      { type: 'PREPARE_LIST' },
      { type: 'SET_ITEMS_LIST', json: '[]' },
      { type: 'IMPORT_DATA' },
      { type: 'VALIDATE_OK', tasks: [{ name: 't', items: ['b/a.dcm'] }] },
      { type: 'TASKS_CREATED', taskIds: ['t1'] },
    ]);
    expect(m.state).toBe('Complete');
    expect(m.context.storageMethodId).toBe('sm-1');
    expect(m.context.createdTaskIds).toEqual(['t1']);
  });

  it('C1: cannot prepare a list before storage is ready', () => {
    expect(cloudReducer(initialCloudMachine, { type: 'PREPARE_LIST' }).state).toBe('StorageNotReady');
  });

  it("the literal 'public' source is a valid verified storage", () => {
    expect(cloudReducer(initialCloudMachine, { type: 'STORAGE_VERIFIED', storageMethodId: 'public' }).state).toBe(
      'StorageReady',
    );
  });

  it('VALIDATE_FAIL returns to PreparingItemsList with errors', () => {
    const m = run([
      { type: 'STORAGE_VERIFIED', storageMethodId: 'sm' },
      { type: 'PREPARE_LIST' },
      { type: 'IMPORT_DATA' },
      { type: 'VALIDATE_FAIL', errors: [{ code: 'PATH_NOT_BUCKET_RELATIVE', message: 'x' }] },
    ]);
    expect(m.state).toBe('PreparingItemsList');
    expect(m.context.errors).toHaveLength(1);
  });

  it('IMPORT_FAIL -> ImportError -> RETRY -> CreatingTasks', () => {
    let m = run([
      { type: 'STORAGE_VERIFIED', storageMethodId: 'sm' },
      { type: 'PREPARE_LIST' },
      { type: 'IMPORT_DATA' },
      { type: 'VALIDATE_OK', tasks: [] },
      { type: 'IMPORT_FAIL' },
    ]);
    expect(m.state).toBe('ImportError');
    m = cloudReducer(m, { type: 'RETRY' });
    expect(m.state).toBe('CreatingTasks');
  });
});
