import { describe, it, expect } from 'vitest';
import {
  DashboardOverviewViewModel,
  DriverViewModel,
  RaceViewModel,
  LeagueStandingViewModel,
  DashboardFeedItemSummaryViewModel,
  FriendViewModel,
} from './DashboardOverviewViewModel';
import type { DashboardOverviewDto } from '../api/dashboard/DashboardApiClient';

const createDashboardOverviewDto = (): DashboardOverviewDto => ({
  currentDriver: {
    id: 'driver-1',
    name: 'Test Driver',
    avatarUrl: 'https://example.com/avatar.jpg',
    country: 'DE',
    totalRaces: 10,
    wins: 3,
    podiums: 5,
    rating: 2500,
    globalRank: 42,
    consistency: 88,
  },
  nextRace: {
    id: 'race-1',
    track: 'Spa-Francorchamps',
    car: 'GT3',
    scheduledAt: '2025-01-01T12:00:00Z',
    isMyLeague: true,
    leagueName: 'Pro League',
  },
  upcomingRaces: [
    {
      id: 'race-2',
      track: 'Nürburgring',
      car: 'GT4',
      scheduledAt: '2025-01-02T12:00:00Z',
      isMyLeague: false,
      leagueName: undefined,
    },
  ],
  leagueStandings: [
    {
      leagueId: 'league-1',
      leagueName: 'Pro League',
      position: 1,
      points: 120,
      totalDrivers: 50,
    },
  ],
  feedItems: [
    {
      id: 'feed-1',
      type: 'news',
      headline: 'Big race announced',
      body: 'Details about the big race.',
      timestamp: '2025-01-01T10:00:00Z',
      ctaHref: '/races/race-1',
      ctaLabel: 'View race',
    },
  ],
  friends: [
    {
      id: 'friend-1',
      name: 'Racing Buddy',
      avatarUrl: 'https://example.com/friend.jpg',
      country: 'US',
    },
  ],
  activeLeaguesCount: 3,
});

describe('DashboardOverviewViewModel', () => {
  it('wraps the current driver DTO in a DriverViewModel', () => {
    const dto = createDashboardOverviewDto();
    const viewModel = new DashboardOverviewViewModel(dto);

    const currentDriver = viewModel.currentDriver;

    expect(currentDriver).toBeInstanceOf(DriverViewModel);
    expect(currentDriver.id).toBe('driver-1');
    expect(currentDriver.name).toBe('Test Driver');
    expect(currentDriver.avatarUrl).toBe('https://example.com/avatar.jpg');
    expect(currentDriver.country).toBe('DE');
    expect(currentDriver.totalRaces).toBe(10);
    expect(currentDriver.wins).toBe(3);
    expect(currentDriver.podiums).toBe(5);
    expect(currentDriver.rating).toBe(2500);
    expect(currentDriver.globalRank).toBe(42);
    expect(currentDriver.consistency).toBe(88);
  });

  it('wraps nextRace DTO into a RaceViewModel and returns null when absent', () => {
    const dtoWithRace = createDashboardOverviewDto();
    const viewModelWithRace = new DashboardOverviewViewModel(dtoWithRace);

    const nextRace = viewModelWithRace.nextRace;

    expect(nextRace).toBeInstanceOf(RaceViewModel);
    expect(nextRace?.id).toBe('race-1');
    expect(nextRace?.track).toBe('Spa-Francorchamps');
    expect(nextRace?.car).toBe('GT3');
    expect(nextRace?.isMyLeague).toBe(true);
    expect(nextRace?.leagueName).toBe('Pro League');
    expect(nextRace?.scheduledAt).toBeInstanceOf(Date);

    const dtoWithoutRace: DashboardOverviewDto = {
      ...dtoWithRace,
      nextRace: null,
    };

    const viewModelWithoutRace = new DashboardOverviewViewModel(dtoWithoutRace);

    expect(viewModelWithoutRace.nextRace).toBeNull();
  });

  it('maps upcoming races, league standings, feed items and friends into their respective view models', () => {
    const dto = createDashboardOverviewDto();
    const viewModel = new DashboardOverviewViewModel(dto);

    expect(viewModel.upcomingRaces).toHaveLength(1);
    expect(viewModel.upcomingRaces[0]).toBeInstanceOf(RaceViewModel);
    expect(viewModel.upcomingRaces[0].id).toBe('race-2');

    expect(viewModel.leagueStandings).toHaveLength(1);
    expect(viewModel.leagueStandings[0]).toBeInstanceOf(LeagueStandingViewModel);
    expect(viewModel.leagueStandings[0].leagueId).toBe('league-1');

    expect(viewModel.feedItems).toHaveLength(1);
    expect(viewModel.feedItems[0]).toBeInstanceOf(DashboardFeedItemSummaryViewModel);
    expect(viewModel.feedItems[0].id).toBe('feed-1');
    expect(viewModel.feedItems[0].timestamp).toBeInstanceOf(Date);

    expect(viewModel.friends).toHaveLength(1);
    expect(viewModel.friends[0]).toBeInstanceOf(FriendViewModel);
    expect(viewModel.friends[0].id).toBe('friend-1');
  });

  it('exposes the activeLeaguesCount from the DTO', () => {
    const dto = createDashboardOverviewDto();
    const viewModel = new DashboardOverviewViewModel(dto);

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