import { describe, it, expect } from 'vitest';
import { RaceStewardingViewModel } from './RaceStewardingViewModel';

const createRaceStewardingDto = () => ({
  raceDetail: {
    race: {
      id: 'race-1',
      track: 'Spa-Francorchamps',
      scheduledAt: '2024-01-01T20:00:00Z',
      status: 'completed',
    },
    league: {
      id: 'league-1',
      name: 'Test League',
    },
  },
  protests: {
    protests: [
      {
        id: 'p1',
        protestingDriverId: 'd1',
        accusedDriverId: 'd2',
        incident: { lap: 1, description: 'Turn 1 divebomb' },
        filedAt: '2024-01-01T21:00:00Z',
        status: 'pending',
      },
      {
        id: 'p2',
        protestingDriverId: 'd3',
        accusedDriverId: 'd4',
        incident: { lap: 5, description: 'Blocking' },
        filedAt: '2024-01-01T21:05:00Z',
        status: 'under_review',
      },
      {
        id: 'p3',
        protestingDriverId: 'd5',
        accusedDriverId: 'd6',
        incident: { lap: 10, description: 'Contact' },
        filedAt: '2024-01-01T21:10:00Z',
        status: 'upheld',
      },
      {
        id: 'p4',
        protestingDriverId: 'd7',
        accusedDriverId: 'd8',
        incident: { lap: 12, description: 'Off-track overtake' },
        filedAt: '2024-01-01T21:15:00Z',
        status: 'dismissed',
      },
      {
        id: 'p5',
        protestingDriverId: 'd9',
        accusedDriverId: 'd10',
        incident: { lap: 15, description: 'Withdrawn protest' },
        filedAt: '2024-01-01T21:20:00Z',
        status: 'withdrawn',
      },
    ],
    driverMap: {
      d1: { id: 'd1', name: 'Driver 1' },
      d2: { id: 'd2', name: 'Driver 2' },
    },
  },
  penalties: {
    penalties: [
      {
        id: 'pen1',
        driverId: 'd2',
        type: 'time',
        value: 5,
        reason: 'Avoidable contact',
      },
      {
        id: 'pen2',
        driverId: 'd3',
        type: 'points',
        value: 2,
        reason: 'Reckless driving',
      },
    ],
    driverMap: {
      d3: { id: 'd3', name: 'Driver 3' },
      d4: { id: 'd4', name: 'Driver 4' },
    },
  },
});

describe('RaceStewardingViewModel', () => {
  it('maps core race, league, protests, penalties and driver map', () => {
    const dto = createRaceStewardingDto();

    const viewModel = new RaceStewardingViewModel(dto as any);

    expect(viewModel.race).toEqual(dto.raceDetail.race);
    expect(viewModel.league).toEqual(dto.raceDetail.league);
    expect(viewModel.protests).toEqual(dto.protests.protests);
    expect(viewModel.penalties).toEqual(dto.penalties.penalties);
    expect(viewModel.driverMap).toEqual({
      ...dto.protests.driverMap,
      ...dto.penalties.driverMap,
    });
  });

  it('derives pending and resolved protest buckets and counts', () => {
    const dto = createRaceStewardingDto();

    const viewModel = new RaceStewardingViewModel(dto as any);

    const pendingIds = viewModel.pendingProtests.map(p => p.id);
    const resolvedIds = viewModel.resolvedProtests.map(p => p.id);

    expect(pendingIds.sort()).toEqual(['p1', 'p2']);
    expect(resolvedIds.sort()).toEqual(['p3', 'p4', 'p5']);
    expect(viewModel.pendingCount).toBe(2);
    expect(viewModel.resolvedCount).toBe(3);
  });

  it('derives penalties count from penalties list', () => {
    const dto = createRaceStewardingDto();

    const viewModel = new RaceStewardingViewModel(dto as any);

    expect(viewModel.penaltiesCount).toBe(2);
  });

  it('handles empty protests and penalties gracefully', () => {
    const dto = createRaceStewardingDto();
    dto.protests.protests = [];
    dto.penalties.penalties = [];

    const viewModel = new RaceStewardingViewModel(dto as any);

    expect(viewModel.pendingProtests).toEqual([]);
    expect(viewModel.resolvedProtests).toEqual([]);
    expect(viewModel.pendingCount).toBe(0);
    expect(viewModel.resolvedCount).toBe(0);
    expect(viewModel.penaltiesCount).toBe(0);
  });
});
