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

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

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

    controller = new LeagueController(mockService);
  });

  describe('getLeagueSchedule', () => {
    it('should return league schedule', async () => {
      const mockResult = {
        seasonId: 'season-1',
        published: true,
        races: [
          {
            id: 'race-1',
            name: 'Spa Endurance',
            date: '2024-03-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-2',
            name: 'Monza Sprint',
            date: '2024-03-22T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-3',
            name: 'Nürburgring Endurance',
            date: '2024-03-29T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
        ],
      };
      mockService.getLeagueSchedule.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueSchedule('league-1', {});

      expect(result).toEqual(mockResult);
      expect(mockService.getLeagueSchedule).toHaveBeenCalledWith('league-1', {});
    });

    it('should return empty schedule for league with no races', async () => {
      const mockResult = {
        seasonId: 'season-1',
        published: false,
        races: [],
      };
      mockService.getLeagueSchedule.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueSchedule('league-1', {});

      expect(result).toEqual(mockResult);
      expect(result.races).toHaveLength(0);
      expect(result.published).toBe(false);
    });

    it('should handle schedule with specific season ID', async () => {
      const mockResult = {
        seasonId: 'season-2',
        published: true,
        races: [
          {
            id: 'race-10',
            name: 'Silverstone Endurance',
            date: '2024-08-01T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
        ],
      };
      mockService.getLeagueSchedule.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueSchedule('league-1', { seasonId: 'season-2' });

      expect(result).toEqual(mockResult);
      expect(mockService.getLeagueSchedule).toHaveBeenCalledWith('league-1', { seasonId: 'season-2' });
    });

    it('should handle schedule with multiple races on same track', async () => {
      const mockResult = {
        seasonId: 'season-1',
        published: true,
        races: [
          {
            id: 'race-1',
            name: 'Spa Endurance',
            date: '2024-03-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-2',
            name: 'Spa Sprint',
            date: '2024-04-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
        ],
      };
      mockService.getLeagueSchedule.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueSchedule('league-1', {});

      expect(result).toEqual(mockResult);
      expect(result.races).toHaveLength(2);
      expect(result.races[0]?.name).toContain('Spa');
      expect(result.races[1]?.name).toContain('Spa');
    });

    it('should handle schedule with different race names', async () => {
      const mockResult = {
        seasonId: 'season-1',
        published: true,
        races: [
          {
            id: 'race-1',
            name: 'Spa Endurance',
            date: '2024-01-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-2',
            name: 'Monza Sprint',
            date: '2024-02-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-3',
            name: 'Nürburgring Endurance',
            date: '2024-03-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-4',
            name: 'Silverstone Sprint',
            date: '2024-04-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
        ],
      };
      mockService.getLeagueSchedule.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueSchedule('league-1', {});

      expect(result).toEqual(mockResult);
      expect(result.races).toHaveLength(4);
      expect(result.races[0]?.name).toBe('Spa Endurance');
      expect(result.races[1]?.name).toBe('Monza Sprint');
      expect(result.races[2]?.name).toBe('Nürburgring Endurance');
      expect(result.races[3]?.name).toBe('Silverstone Sprint');
    });

    it('should handle schedule with different dates', async () => {
      const mockResult = {
        seasonId: 'season-1',
        published: true,
        races: [
          {
            id: 'race-1',
            name: 'Race 1',
            date: '2024-01-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-2',
            name: 'Race 2',
            date: '2024-02-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-3',
            name: 'Race 3',
            date: '2024-03-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
        ],
      };
      mockService.getLeagueSchedule.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueSchedule('league-1', {});

      expect(result).toEqual(mockResult);
      expect(result.races).toHaveLength(3);
      expect(result.races[0]?.date).toBe('2024-01-15T14:00:00Z');
      expect(result.races[1]?.date).toBe('2024-02-15T14:00:00Z');
      expect(result.races[2]?.date).toBe('2024-03-15T14:00:00Z');
    });

    it('should handle schedule with league name variations', async () => {
      const mockResult = {
        seasonId: 'season-1',
        published: true,
        races: [
          {
            id: 'race-1',
            name: 'Race 1',
            date: '2024-03-15T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-2',
            name: 'Race 2',
            date: '2024-03-22T14:00:00Z',
            leagueName: 'GT3 Masters',
          },
          {
            id: 'race-3',
            name: 'Race 3',
            date: '2024-03-29T14:00:00Z',
            leagueName: null,
          },
        ],
      };
      mockService.getLeagueSchedule.mockResolvedValue(mockResult as never);

      const result = await controller.getLeagueSchedule('league-1', {});

      expect(result).toEqual(mockResult);
      expect(result.races).toHaveLength(3);
      expect(result.races[0]?.leagueName).toBe('GT3 Masters');
      expect(result.races[1]?.leagueName).toBe('GT3 Masters');
      expect(result.races[2]?.leagueName).toBeNull();
    });
  });
});
