import { describe, it, expect, beforeEach } from 'vitest';
import { DriversLeaderboardPresenter } from './DriversLeaderboardPresenter';
import type { DriversLeaderboardResultDTO } from '../../../../../core/racing/application/presenters/IDriversLeaderboardPresenter';

describe('DriversLeaderboardPresenter', () => {
  let presenter: DriversLeaderboardPresenter;

  beforeEach(() => {
    presenter = new DriversLeaderboardPresenter();
  });

  describe('present', () => {
    it('should map core DTO to API view model correctly', () => {
      const dto: DriversLeaderboardResultDTO = {
        drivers: [
          {
            id: 'driver-1',
            name: 'Driver One',
            country: 'US',
            iracingId: '12345',
            joinedAt: new Date('2023-01-01'),
          },
          {
            id: 'driver-2',
            name: 'Driver Two',
            country: 'DE',
            iracingId: '67890',
            joinedAt: new Date('2023-01-02'),
          },
        ],
        rankings: [
          { driverId: 'driver-1', rating: 2500, overallRank: 1 },
          { driverId: 'driver-2', rating: 2400, overallRank: 2 },
        ],
        stats: {
          'driver-1': { racesCompleted: 50, wins: 10, podiums: 20 },
          'driver-2': { racesCompleted: 40, wins: 5, podiums: 15 },
        },
        avatarUrls: {
          'driver-1': 'https://example.com/avatar1.png',
          'driver-2': 'https://example.com/avatar2.png',
        },
      };

      presenter.present(dto);

      const result = presenter.viewModel;

      expect(result.drivers).toHaveLength(2);
      expect(result.drivers[0]).toEqual({
        id: 'driver-1',
        name: 'Driver One',
        rating: 2500,
        skillLevel: 'Pro',
        nationality: 'US',
        racesCompleted: 50,
        wins: 10,
        podiums: 20,
        isActive: true,
        rank: 1,
        avatarUrl: 'https://example.com/avatar1.png',
      });
      expect(result.drivers[1]).toEqual({
        id: 'driver-2',
        name: 'Driver Two',
        rating: 2400,
        skillLevel: 'Pro',
        nationality: 'DE',
        racesCompleted: 40,
        wins: 5,
        podiums: 15,
        isActive: true,
        rank: 2,
        avatarUrl: 'https://example.com/avatar2.png',
      });
      expect(result.totalRaces).toBe(90);
      expect(result.totalWins).toBe(15);
      expect(result.activeCount).toBe(2);
    });

    it('should sort drivers by rating descending', () => {
      const dto: DriversLeaderboardResultDTO = {
        drivers: [
          {
            id: 'driver-1',
            name: 'Driver One',
            country: 'US',
            iracingId: '12345',
            joinedAt: new Date(),
          },
          {
            id: 'driver-2',
            name: 'Driver Two',
            country: 'DE',
            iracingId: '67890',
            joinedAt: new Date(),
          },
        ],
        rankings: [
          { driverId: 'driver-1', rating: 2400, overallRank: 2 },
          { driverId: 'driver-2', rating: 2500, overallRank: 1 },
        ],
        stats: {},
        avatarUrls: {},
      };

      presenter.present(dto);

      const result = presenter.viewModel;

      expect(result.drivers[0].id).toBe('driver-2'); // Higher rating first
      expect(result.drivers[1].id).toBe('driver-1');
    });

    it('should handle missing stats gracefully', () => {
      const dto: DriversLeaderboardResultDTO = {
        drivers: [
          {
            id: 'driver-1',
            name: 'Driver One',
            country: 'US',
            iracingId: '12345',
            joinedAt: new Date(),
          },
        ],
        rankings: [
          { driverId: 'driver-1', rating: 2500, overallRank: 1 },
        ],
        stats: {}, // No stats
        avatarUrls: {},
      };

      presenter.present(dto);

      const result = presenter.viewModel;

      expect(result.drivers[0].racesCompleted).toBe(0);
      expect(result.drivers[0].wins).toBe(0);
      expect(result.drivers[0].podiums).toBe(0);
    });
  });

  describe('reset', () => {
    it('should reset the result', () => {
      const dto: DriversLeaderboardResultDTO = {
        drivers: [],
        rankings: [],
        stats: {},
        avatarUrls: {},
      };

      presenter.present(dto);
      expect(presenter.viewModel).toBeDefined();

      presenter.reset();
      expect(() => presenter.viewModel).toThrow('Presenter not presented');
    });
  });
});