import { describe, it, expect } from 'vitest';
import { State, reduce, initial } from './change-request.machine';

const editingWith = (draft: Partial<{ straat: string; postcode: string; woonplaats: string }>): State => ({
  tag: 'Editing',
  draft: { straat: '', postcode: '', woonplaats: '', ...draft },
  errors: {},
});

describe('change-request reduce', () => {
  it('SetField updates the draft while editing', () => {
    const s = reduce(initial, { tag: 'SetField', key: 'straat', value: 'Lange Voorhout 9' });
    expect(s.tag).toBe('Editing');
    expect((s as Extract<State, { tag: 'Editing' }>).draft.straat).toBe('Lange Voorhout 9');
  });

  it('Submit with an invalid draft stays Editing and reports field errors', () => {
    const s = reduce(editingWith({ straat: '', postcode: 'nope' }), { tag: 'Submit' });
    expect(s.tag).toBe('Editing');
    const errors = (s as Extract<State, { tag: 'Editing' }>).errors;
    expect(errors.straat).toBeTruthy();
    expect(errors.postcode).toBeTruthy();
  });

  it('Submit with a valid draft moves to Submitting with parsed (normalised) data', () => {
    const s = reduce(editingWith({ straat: 'Lange Voorhout 9', postcode: '2514ea' }), { tag: 'Submit' });
    expect(s.tag).toBe('Submitting');
    expect((s as Extract<State, { tag: 'Submitting' }>).data.postcode).toBe('2514 EA');
  });

  it('confirms and fails only from Submitting; Retry re-submits a failure', () => {
    const submitting = reduce(editingWith({ straat: 'A 1', postcode: '2514 EA' }), { tag: 'Submit' });
    const ok = reduce(submitting, { tag: 'SubmitConfirmed', referentie: 'BIG-2026-1' });
    expect(ok).toMatchObject({ tag: 'Submitted', referentie: 'BIG-2026-1' });

    const failed = reduce(submitting, { tag: 'SubmitFailed', error: 'boom' });
    expect(failed).toMatchObject({ tag: 'Failed', error: 'boom' });
    expect(reduce(failed, { tag: 'Retry' }).tag).toBe('Submitting');
  });

  it('Reset returns to the initial editing state', () => {
    const submitting = reduce(editingWith({ straat: 'A 1', postcode: '2514 EA' }), { tag: 'Submit' });
    expect(reduce(submitting, { tag: 'Reset' })).toEqual(initial);
  });
});
