import { describe, it, expect } from 'vitest';
import { RaceStatus, type RaceStatusValue } from './RaceStatus';
import { RacingDomainValidationError } from '../errors/RacingDomainError';

describe('RaceStatus', () => {
  it('creates a status and exposes stable value/toString/props', () => {
    const status = RaceStatus.create('scheduled');
    expect(status.value).toBe('scheduled');
    expect(status.toString()).toBe('scheduled');
    expect(status.props).toEqual({ value: 'scheduled' });
  });

  it('rejects missing value', () => {
    expect(() => RaceStatus.create('' as unknown as RaceStatusValue)).toThrow(
      RacingDomainValidationError,
    );
    expect(() => RaceStatus.create('' as unknown as RaceStatusValue)).toThrow(
      'Race status is required',
    );
  });

  it('supports lifecycle guard helpers', () => {
    expect(RaceStatus.create('scheduled').canStart()).toBe(true);
    expect(RaceStatus.create('running').canStart()).toBe(false);

    expect(RaceStatus.create('running').canComplete()).toBe(true);
    expect(RaceStatus.create('scheduled').canComplete()).toBe(false);

    expect(RaceStatus.create('scheduled').canCancel()).toBe(true);
    expect(RaceStatus.create('running').canCancel()).toBe(true);
    expect(RaceStatus.create('completed').canCancel()).toBe(false);

    expect(RaceStatus.create('completed').canReopen()).toBe(true);
    expect(RaceStatus.create('cancelled').canReopen()).toBe(true);
    expect(RaceStatus.create('running').canReopen()).toBe(false);

    expect(RaceStatus.create('completed').isTerminal()).toBe(true);
    expect(RaceStatus.create('cancelled').isTerminal()).toBe(true);
    expect(RaceStatus.create('running').isTerminal()).toBe(false);

    expect(RaceStatus.create('running').isRunning()).toBe(true);
    expect(RaceStatus.create('completed').isCompleted()).toBe(true);
    expect(RaceStatus.create('scheduled').isScheduled()).toBe(true);
    expect(RaceStatus.create('cancelled').isCancelled()).toBe(true);
  });

  it('validates allowed transitions', () => {
    const scheduled = RaceStatus.create('scheduled');
    const running = RaceStatus.create('running');
    const completed = RaceStatus.create('completed');
    const cancelled = RaceStatus.create('cancelled');

    expect(scheduled.canTransitionTo('running')).toEqual({ valid: true });
    expect(scheduled.canTransitionTo('cancelled')).toEqual({ valid: true });

    expect(running.canTransitionTo('completed')).toEqual({ valid: true });
    expect(running.canTransitionTo('cancelled')).toEqual({ valid: true });

    expect(completed.canTransitionTo('scheduled')).toEqual({ valid: true });
    expect(cancelled.canTransitionTo('scheduled')).toEqual({ valid: true });
  });

  it('rejects disallowed transitions with a helpful error', () => {
    const scheduled = RaceStatus.create('scheduled');
    const result = scheduled.canTransitionTo('completed');
    expect(result.valid).toBe(false);
    expect(result.error).toBe('Cannot transition from scheduled to completed');
  });

  it('equals compares by value', () => {
    const a = RaceStatus.create('scheduled');
    const b = RaceStatus.create('scheduled');
    const c = RaceStatus.create('running');
    expect(a.equals(b)).toBe(true);
    expect(a.equals(c)).toBe(false);
  });

  it('only allowed status values compile (type-level)', () => {
    const allowed: RaceStatusValue[] = ['scheduled', 'running', 'completed', 'cancelled'];
    expect(allowed).toHaveLength(4);
  });
});