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

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

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

    controller = new LeagueController(mockService);
  });

  describe('getAllLeaguesWithCapacity', () => {
    it('should return leagues with capacity information', async () => {
      const mockResult = {
        leagues: [
          {
            id: 'league-1',
            name: 'GT3 Masters',
            description: 'A GT3 racing league',
            ownerId: 'owner-1',
            maxDrivers: 32,
            currentDrivers: 25,
            isPublic: true,
          },
        ],
        totalCount: 1,
      };
      mockService.getAllLeaguesWithCapacity.mockResolvedValue(mockResult as never);

      const result = await controller.getAllLeaguesWithCapacity();

      expect(result).toEqual(mockResult);
      expect(mockService.getAllLeaguesWithCapacity).toHaveBeenCalledTimes(1);
    });

    it('should return empty array when no leagues exist', async () => {
      const mockResult = { leagues: [], totalCount: 0 };
      mockService.getAllLeaguesWithCapacity.mockResolvedValue(mockResult as never);

      const result = await controller.getAllLeaguesWithCapacity();

      expect(result).toEqual(mockResult);
      expect(result.leagues).toHaveLength(0);
      expect(result.totalCount).toBe(0);
    });

    it('should handle multiple leagues with different capacities', async () => {
      const mockResult = {
        leagues: [
          {
            id: 'league-1',
            name: 'Small League',
            description: 'Small league',
            ownerId: 'owner-1',
            maxDrivers: 10,
            currentDrivers: 8,
            isPublic: true,
          },
          {
            id: 'league-2',
            name: 'Large League',
            description: 'Large league',
            ownerId: 'owner-2',
            maxDrivers: 50,
            currentDrivers: 45,
            isPublic: true,
          },
        ],
        totalCount: 2,
      };
      mockService.getAllLeaguesWithCapacity.mockResolvedValue(mockResult as never);

      const result = await controller.getAllLeaguesWithCapacity();

      expect(result).toEqual(mockResult);
      expect(result.leagues).toHaveLength(2);
      expect(result.leagues[0]?.maxDrivers).toBe(10);
      expect(result.leagues[1]?.maxDrivers).toBe(50);
    });
  });

  describe('getAllLeaguesWithCapacityAndScoring', () => {
    it('should return leagues with capacity and scoring information', async () => {
      const mockResult = {
        leagues: [
          {
            id: 'league-1',
            name: 'GT3 Masters',
            description: 'A GT3 racing league',
            ownerId: 'owner-1',
            maxDrivers: 32,
            currentDrivers: 25,
            isPublic: true,
            scoringConfig: {
              pointsSystem: 'standard',
              pointsPerRace: 25,
              bonusPoints: true,
            },
          },
        ],
        totalCount: 1,
      };
      mockService.getAllLeaguesWithCapacityAndScoring.mockResolvedValue(mockResult as never);

      const result = await controller.getAllLeaguesWithCapacityAndScoring();

      expect(result).toEqual(mockResult);
      expect(mockService.getAllLeaguesWithCapacityAndScoring).toHaveBeenCalledTimes(1);
    });

    it('should return empty array when no leagues exist', async () => {
      const mockResult = { leagues: [], totalCount: 0 };
      mockService.getAllLeaguesWithCapacityAndScoring.mockResolvedValue(mockResult as never);

      const result = await controller.getAllLeaguesWithCapacityAndScoring();

      expect(result).toEqual(mockResult);
      expect(result.leagues).toHaveLength(0);
      expect(result.totalCount).toBe(0);
    });

    it('should handle leagues with different scoring configurations', async () => {
      const mockResult = {
        leagues: [
          {
            id: 'league-1',
            name: 'Standard League',
            description: 'Standard scoring',
            ownerId: 'owner-1',
            maxDrivers: 32,
            currentDrivers: 20,
            isPublic: true,
            scoringConfig: {
              pointsSystem: 'standard',
              pointsPerRace: 25,
              bonusPoints: true,
            },
          },
          {
            id: 'league-2',
            name: 'Custom League',
            description: 'Custom scoring',
            ownerId: 'owner-2',
            maxDrivers: 20,
            currentDrivers: 15,
            isPublic: true,
            scoringConfig: {
              pointsSystem: 'custom',
              pointsPerRace: 50,
              bonusPoints: false,
            },
          },
        ],
        totalCount: 2,
      };
      mockService.getAllLeaguesWithCapacityAndScoring.mockResolvedValue(mockResult as never);

      const result = await controller.getAllLeaguesWithCapacityAndScoring();

      expect(result).toEqual(mockResult);
      expect(result.leagues).toHaveLength(2);
      expect(result.leagues[0]?.scoringConfig.pointsSystem).toBe('standard');
      expect(result.leagues[1]?.scoringConfig.pointsSystem).toBe('custom');
    });
  });

  describe('getTotalLeagues', () => {
    it('should return total leagues count', async () => {
      const mockResult = { totalLeagues: 42 };
      mockService.getTotalLeagues.mockResolvedValue(mockResult as never);

      const result = await controller.getTotalLeagues();

      expect(result).toEqual(mockResult);
      expect(mockService.getTotalLeagues).toHaveBeenCalledTimes(1);
    });

    it('should return zero when no leagues exist', async () => {
      const mockResult = { totalLeagues: 0 };
      mockService.getTotalLeagues.mockResolvedValue(mockResult as never);

      const result = await controller.getTotalLeagues();

      expect(result).toEqual(mockResult);
      expect(result.totalLeagues).toBe(0);
    });

    it('should handle large league counts', async () => {
      const mockResult = { totalLeagues: 1000 };
      mockService.getTotalLeagues.mockResolvedValue(mockResult as never);

      const result = await controller.getTotalLeagues();

      expect(result).toEqual(mockResult);
      expect(result.totalLeagues).toBe(1000);
    });
  });
});
