import { describe, expect, it } from 'vitest';
import type { RaceDetailLeagueDTO } from '../types/generated/RaceDetailLeagueDTO';
import type { RaceDetailRaceDTO } from '../types/generated/RaceDetailRaceDTO';
import type { RaceDetailRegistrationDTO } from '../types/generated/RaceDetailRegistrationDTO';
import type { RaceDetailUserResultDTO } from '../types/generated/RaceDetailUserResultDTO';
import type { RaceDetailEntryDTO } from '../types/RaceDetailEntryDTO';
import { RaceDetailViewModel } from './RaceDetailViewModel';

describe('RaceDetailViewModel', () => {
  const createMockRace = (overrides?: Partial<RaceDetailRaceDTO>): RaceDetailRaceDTO => ({
    id: 'race-123',
    title: 'Test Race',
    scheduledAt: '2023-12-31T20:00:00Z',
    status: 'upcoming',
    ...overrides,
  });

  const createMockLeague = (): RaceDetailLeagueDTO => ({
    id: 'league-123',
    name: 'Test League',
  });

  const createMockRegistration = (
    overrides?: Partial<RaceDetailRegistrationDTO>
  ): RaceDetailRegistrationDTO => ({
    isRegistered: false,
    canRegister: true,
    ...overrides,
  });

  it('should create instance with all properties', () => {
    const race = createMockRace();
    const league = createMockLeague();
    const entries: RaceDetailEntryDTO[] = [];
    const registration = createMockRegistration();
    const userResult: RaceDetailUserResultDTO | null = null;

    const viewModel = new RaceDetailViewModel({
      race,
      league,
      entryList: entries,
      registration,
      userResult,
    }, 'current-driver');

    expect(viewModel.race).toBe(race);
    expect(viewModel.league).toBe(league);
    expect(viewModel.entryList).toHaveLength(0);
    expect(viewModel.registration).toBe(registration);
    expect(viewModel.userResult).toBe(userResult);
  });

  it('should handle null race and league', () => {
    const viewModel = new RaceDetailViewModel({
      race: null,
      league: null,
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    expect(viewModel.race).toBeNull();
    expect(viewModel.league).toBeNull();
  });

  it('should return correct isRegistered value', () => {
    const registeredVm = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration({ isRegistered: true }),
      userResult: null,
    });

    const notRegisteredVm = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration({ isRegistered: false }),
      userResult: null,
    });

    expect(registeredVm.isRegistered).toBe(true);
    expect(notRegisteredVm.isRegistered).toBe(false);
  });

  it('should return correct canRegister value', () => {
    const canRegisterVm = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration({ canRegister: true }),
      userResult: null,
    });

    const cannotRegisterVm = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration({ canRegister: false }),
      userResult: null,
    });

    expect(canRegisterVm.canRegister).toBe(true);
    expect(cannotRegisterVm.canRegister).toBe(false);
  });

  it('should format race status correctly', () => {
    const upcomingVm = new RaceDetailViewModel({
      race: createMockRace({ status: 'upcoming' }),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    const liveVm = new RaceDetailViewModel({
      race: createMockRace({ status: 'live' }),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    const finishedVm = new RaceDetailViewModel({
      race: createMockRace({ status: 'finished' }),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    expect(upcomingVm.raceStatusDisplay).toBe('Upcoming');
    expect(liveVm.raceStatusDisplay).toBe('Live');
    expect(finishedVm.raceStatusDisplay).toBe('Finished');
  });

  it('should return Unknown for status when race is null', () => {
    const viewModel = new RaceDetailViewModel({
      race: null,
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    expect(viewModel.raceStatusDisplay).toBe('Unknown');
  });

  it('should format scheduled time correctly', () => {
    const viewModel = new RaceDetailViewModel({
      race: createMockRace({ scheduledAt: '2023-12-31T20:00:00Z' }),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    const formatted = viewModel.formattedScheduledTime;

    expect(formatted).toContain('2023');
    expect(formatted).toContain('12/31');
  });

  it('should return empty string for formatted time when race is null', () => {
    const viewModel = new RaceDetailViewModel({
      race: null,
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    expect(viewModel.formattedScheduledTime).toBe('');
  });

  it('should return correct entry count', () => {
    const entries: RaceDetailEntryDTO[] = [
      { driverId: 'driver-1', carId: 'car-1' },
      { driverId: 'driver-2', carId: 'car-2' },
      { driverId: 'driver-3', carId: 'car-3' },
    ] as RaceDetailEntryDTO[];

    const viewModel = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: entries,
      registration: createMockRegistration(),
      userResult: null,
    });

    expect(viewModel.entryCount).toBe(3);
  });

  it('should return true for hasResults when userResult exists', () => {
    const viewModel = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: { position: 1, lapTime: 90.5 } as RaceDetailUserResultDTO,
    });

    expect(viewModel.hasResults).toBe(true);
  });

  it('should return false for hasResults when userResult is null', () => {
    const viewModel = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    expect(viewModel.hasResults).toBe(false);
  });

  it('should return correct registration status message when registered', () => {
    const viewModel = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration({ isRegistered: true }),
      userResult: null,
    });

    expect(viewModel.registrationStatusMessage).toBe('You are registered for this race');
  });

  it('should return correct registration status message when can register', () => {
    const viewModel = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration({ isRegistered: false, canRegister: true }),
      userResult: null,
    });

    expect(viewModel.registrationStatusMessage).toBe('You can register for this race');
  });

  it('should return correct registration status message when cannot register', () => {
    const viewModel = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration({ isRegistered: false, canRegister: false }),
      userResult: null,
    });

    expect(viewModel.registrationStatusMessage).toBe('Registration not available');
  });

  it('should expose canReopenRace for completed and cancelled statuses', () => {
    const completedVm = new RaceDetailViewModel({
      race: createMockRace({ status: 'completed' }),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    const cancelledVm = new RaceDetailViewModel({
      race: createMockRace({ status: 'cancelled' as any }),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    const upcomingVm = new RaceDetailViewModel({
      race: createMockRace({ status: 'upcoming' }),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    expect(completedVm.canReopenRace).toBe(true);
    expect(cancelledVm.canReopenRace).toBe(true);
    expect(upcomingVm.canReopenRace).toBe(false);
  });

  it('should handle error property', () => {
    const viewModel = new RaceDetailViewModel({
      race: createMockRace(),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
      error: 'Failed to load race details',
    });

    expect(viewModel.error).toBe('Failed to load race details');
  });

  it('should handle custom race status', () => {
    const viewModel = new RaceDetailViewModel({
      race: createMockRace({ status: 'cancelled' }),
      league: createMockLeague(),
      entryList: [],
      registration: createMockRegistration(),
      userResult: null,
    });

    expect(viewModel.raceStatusDisplay).toBe('cancelled');
  });
});