import { describe, expect, it, vi } from 'vitest';
import { LeagueController } from './LeagueController';
import { LeagueService } from './LeagueService';

describe('LeagueController - Standings Endpoints', () => {
  let controller: LeagueController;
  let mockService: ReturnType<typeof vi.mocked<LeagueService>>;

  beforeEach(() => {
    mockService = {
      getLeagueStandings: vi.fn(),
    } as never;

    controller = new LeagueController(mockService);
  });

  describe('getLeagueStandings', () => {
    it('should return league standings', async () => {
      const mockResult = {
        standings: [
          {
            driverId: 'driver-1',
            driver: {
              id: 'driver-1',
              iracingId: '12345',
              name: 'John Doe',
              country: 'US',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 1,
            points: 150,
            races: 12,
            wins: 5,
            podiums: 8,
          },
          {
            driverId: 'driver-2',
            driver: {
              id: 'driver-2',
              iracingId: '67890',
              name: 'Jane Smith',
              country: 'UK',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 2,
            points: 145,
            races: 12,
            wins: 4,
            podiums: 7,
          },
          {
            driverId: 'driver-3',
            driver: {
              id: 'driver-3',
              iracingId: '11111',
              name: 'Bob Johnson',
              country: 'CA',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 3,
            points: 140,
            races: 12,
            wins: 3,
            podiums: 6,
          },
        ],
      };
      mockService.getLeagueStandings.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueStandings('league-1');

      expect(result).toEqual(mockResult);
      expect(mockService.getLeagueStandings).toHaveBeenCalledWith('league-1');
    });

    it('should return empty standings for league with no races', async () => {
      const mockResult = { standings: [] };
      mockService.getLeagueStandings.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueStandings('league-1');

      expect(result).toEqual(mockResult);
      expect(result.standings).toHaveLength(0);
    });

    it('should handle standings with single driver', async () => {
      const mockResult = {
        standings: [
          {
            driverId: 'driver-1',
            driver: {
              id: 'driver-1',
              iracingId: '12345',
              name: 'John Doe',
              country: 'US',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 1,
            points: 100,
            races: 10,
            wins: 10,
            podiums: 10,
          },
        ],
      };
      mockService.getLeagueStandings.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueStandings('league-1');

      expect(result).toEqual(mockResult);
      expect(result.standings).toHaveLength(1);
      expect(result.standings[0]?.position).toBe(1);
      expect(result.standings[0]?.points).toBe(100);
    });

    it('should handle standings with many drivers', async () => {
      const mockResult = {
        standings: Array.from({ length: 20 }, (_, i) => ({
          driverId: `driver-${i + 1}`,
          driver: {
            id: `driver-${i + 1}`,
            iracingId: `${10000 + i}`,
            name: `Driver ${i + 1}`,
            country: 'US',
            joinedAt: '2024-01-01T00:00:00Z',
          },
          position: i + 1,
          points: 100 - i,
          races: 12,
          wins: Math.max(0, 5 - i),
          podiums: Math.max(0, 10 - i),
        })),
      };
      mockService.getLeagueStandings.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueStandings('league-1');

      expect(result).toEqual(mockResult);
      expect(result.standings).toHaveLength(20);
      expect(result.standings[0]?.position).toBe(1);
      expect(result.standings[19]?.position).toBe(20);
    });

    it('should handle standings with tied points', async () => {
      const mockResult = {
        standings: [
          {
            driverId: 'driver-1',
            driver: {
              id: 'driver-1',
              iracingId: '12345',
              name: 'John Doe',
              country: 'US',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 1,
            points: 150,
            races: 12,
            wins: 5,
            podiums: 8,
          },
          {
            driverId: 'driver-2',
            driver: {
              id: 'driver-2',
              iracingId: '67890',
              name: 'Jane Smith',
              country: 'UK',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 2,
            points: 150,
            races: 12,
            wins: 5,
            podiums: 7,
          },
          {
            driverId: 'driver-3',
            driver: {
              id: 'driver-3',
              iracingId: '11111',
              name: 'Bob Johnson',
              country: 'CA',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 3,
            points: 145,
            races: 12,
            wins: 4,
            podiums: 6,
          },
        ],
      };
      mockService.getLeagueStandings.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueStandings('league-1');

      expect(result).toEqual(mockResult);
      expect(result.standings).toHaveLength(3);
      expect(result.standings[0]?.points).toBe(150);
      expect(result.standings[1]?.points).toBe(150);
      expect(result.standings[2]?.points).toBe(145);
    });

    it('should handle standings with varying race counts', async () => {
      const mockResult = {
        standings: [
          {
            driverId: 'driver-1',
            driver: {
              id: 'driver-1',
              iracingId: '12345',
              name: 'John Doe',
              country: 'US',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 1,
            points: 150,
            races: 12,
            wins: 5,
            podiums: 8,
          },
          {
            driverId: 'driver-2',
            driver: {
              id: 'driver-2',
              iracingId: '67890',
              name: 'Jane Smith',
              country: 'UK',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 2,
            points: 140,
            races: 10,
            wins: 4,
            podiums: 6,
          },
          {
            driverId: 'driver-3',
            driver: {
              id: 'driver-3',
              iracingId: '11111',
              name: 'Bob Johnson',
              country: 'CA',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 3,
            points: 130,
            races: 8,
            wins: 3,
            podiums: 5,
          },
        ],
      };
      mockService.getLeagueStandings.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueStandings('league-1');

      expect(result).toEqual(mockResult);
      expect(result.standings).toHaveLength(3);
      expect(result.standings[0]?.races).toBe(12);
      expect(result.standings[1]?.races).toBe(10);
      expect(result.standings[2]?.races).toBe(8);
    });

    it('should handle standings with varying win counts', async () => {
      const mockResult = {
        standings: [
          {
            driverId: 'driver-1',
            driver: {
              id: 'driver-1',
              iracingId: '12345',
              name: 'John Doe',
              country: 'US',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 1,
            points: 150,
            races: 12,
            wins: 10,
            podiums: 12,
          },
          {
            driverId: 'driver-2',
            driver: {
              id: 'driver-2',
              iracingId: '67890',
              name: 'Jane Smith',
              country: 'UK',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 2,
            points: 140,
            races: 12,
            wins: 2,
            podiums: 8,
          },
          {
            driverId: 'driver-3',
            driver: {
              id: 'driver-3',
              iracingId: '11111',
              name: 'Bob Johnson',
              country: 'CA',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 3,
            points: 130,
            races: 12,
            wins: 0,
            podiums: 4,
          },
        ],
      };
      mockService.getLeagueStandings.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueStandings('league-1');

      expect(result).toEqual(mockResult);
      expect(result.standings).toHaveLength(3);
      expect(result.standings[0]?.wins).toBe(10);
      expect(result.standings[1]?.wins).toBe(2);
      expect(result.standings[2]?.wins).toBe(0);
    });

    it('should handle standings with varying podium counts', async () => {
      const mockResult = {
        standings: [
          {
            driverId: 'driver-1',
            driver: {
              id: 'driver-1',
              iracingId: '12345',
              name: 'John Doe',
              country: 'US',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 1,
            points: 150,
            races: 12,
            wins: 5,
            podiums: 12,
          },
          {
            driverId: 'driver-2',
            driver: {
              id: 'driver-2',
              iracingId: '67890',
              name: 'Jane Smith',
              country: 'UK',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 2,
            points: 140,
            races: 12,
            wins: 4,
            podiums: 8,
          },
          {
            driverId: 'driver-3',
            driver: {
              id: 'driver-3',
              iracingId: '11111',
              name: 'Bob Johnson',
              country: 'CA',
              joinedAt: '2024-01-01T00:00:00Z',
            },
            position: 3,
            points: 130,
            races: 12,
            wins: 3,
            podiums: 4,
          },
        ],
      };
      mockService.getLeagueStandings.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueStandings('league-1');

      expect(result).toEqual(mockResult);
      expect(result.standings).toHaveLength(3);
      expect(result.standings[0]?.podiums).toBe(12);
      expect(result.standings[1]?.podiums).toBe(8);
      expect(result.standings[2]?.podiums).toBe(4);
    });
  });
});
