import { League } from '@core/racing/domain/entities/League';
import { beforeEach, describe, expect, it } from 'vitest';
import { AllLeaguesWithCapacityPresenter } from './AllLeaguesWithCapacityPresenter';

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

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

  describe('present', () => {
    it('should map empty leagues array to DTO', () => {
      presenter.present({ leagues: [] });

      const vm = presenter.getViewModel();

      expect(vm).toEqual({
        leagues: [],
        totalCount: 0,
      });
    });

    it('should map leagues with basic information', () => {
      const league = League.create({
        id: 'league-1',
        name: 'Test League',
        description: 'A test league',
        ownerId: 'owner-1',
        settings: {
          pointsSystem: 'f1-2024',
          maxDrivers: 20,
        },
        createdAt: new Date('2024-01-01T00:00:00Z'),
      });

      presenter.present({
        leagues: [
          {
            league,
            currentDrivers: 5,
            maxDrivers: 20,
          },
        ],
      });

      const vm = presenter.getViewModel();

      expect(vm.leagues).toHaveLength(1);
      expect(vm.leagues[0]!.id).toBe('league-1');
      expect(vm.leagues[0]!.name).toBe('Test League');
      expect(vm.leagues[0]!.description).toBe('A test league');
      expect(vm.leagues[0]!.ownerId).toBe('owner-1');
      expect(vm.leagues[0]!.createdAt).toBe('2024-01-01T00:00:00.000Z');
      expect(vm.leagues[0]!.settings.maxDrivers).toBe(20);
      expect(vm.leagues[0]!.usedSlots).toBe(5);
      expect(vm.totalCount).toBe(1);
    });

    it('should map leagues with social links', () => {
      const league = League.create({
        id: 'league-1',
        name: 'Test League',
        description: 'A test league',
        ownerId: 'owner-1',
        settings: { pointsSystem: 'f1-2024' },
        socialLinks: {
          discordUrl: 'https://discord.gg/test',
          youtubeUrl: 'https://youtube.com/test',
          websiteUrl: 'https://test.com',
        },
      });

      presenter.present({
        leagues: [
          {
            league,
            currentDrivers: 3,
            maxDrivers: 32,
          },
        ],
      });

      const vm = presenter.getViewModel();

      expect(vm.leagues[0]!.socialLinks).toEqual({
        discordUrl: 'https://discord.gg/test',
        youtubeUrl: 'https://youtube.com/test',
        websiteUrl: 'https://test.com',
      });
    });

    it('should handle leagues without social links', () => {
      const league = League.create({
        id: 'league-1',
        name: 'Test League',
        description: 'A test league',
        ownerId: 'owner-1',
        settings: { pointsSystem: 'f1-2024' },
      });

      presenter.present({
        leagues: [
          {
            league,
            currentDrivers: 2,
            maxDrivers: 32,
          },
        ],
      });

      const vm = presenter.getViewModel();

      expect(vm.leagues[0]!.socialLinks).toEqual({});
    });

    it('should handle multiple leagues with different configurations', () => {
      const league1 = League.create({
        id: 'league-1',
        name: 'League One',
        description: 'First league',
        ownerId: 'owner-1',
        settings: { pointsSystem: 'f1-2024', maxDrivers: 20 },
      });

      const league2 = League.create({
        id: 'league-2',
        name: 'League Two',
        description: 'Second league',
        ownerId: 'owner-2',
        settings: { pointsSystem: 'indycar', maxDrivers: 40 },
        socialLinks: { discordUrl: 'https://discord.gg/league2' },
      });

      presenter.present({
        leagues: [
          {
            league: league1,
            currentDrivers: 10,
            maxDrivers: 20,
          },
          {
            league: league2,
            currentDrivers: 25,
            maxDrivers: 40,
          },
        ],
      });

      const vm = presenter.getViewModel();

      expect(vm.leagues).toHaveLength(2);
      expect(vm.totalCount).toBe(2);
      expect(vm.leagues[0]!.id).toBe('league-1');
      expect(vm.leagues[0]!.settings.maxDrivers).toBe(20);
      expect(vm.leagues[0]!.usedSlots).toBe(10);
      expect(vm.leagues[1]!.id).toBe('league-2');
      expect(vm.leagues[1]!.socialLinks?.discordUrl).toBe('https://discord.gg/league2');
      expect(vm.leagues[1]!.settings.maxDrivers).toBe(40);
      expect(vm.leagues[1]!.usedSlots).toBe(25);
    });

    it('should handle leagues with zero drivers', () => {
      const league = League.create({
        id: 'league-1',
        name: 'Empty League',
        description: 'No drivers yet',
        ownerId: 'owner-1',
        settings: { pointsSystem: 'f1-2024', maxDrivers: 32 },
      });

      presenter.present({
        leagues: [
          {
            league,
            currentDrivers: 0,
            maxDrivers: 32,
          },
        ],
      });

      const vm = presenter.getViewModel();

      expect(vm.leagues[0]!.usedSlots).toBe(0);
    });

    it('should handle leagues with description containing special characters', () => {
      const league = League.create({
        id: 'league-1',
        name: 'Test League',
        description: 'A test league with "quotes" and <tags> & symbols!',
        ownerId: 'owner-1',
        settings: { pointsSystem: 'f1-2024' },
      });

      presenter.present({
        leagues: [
          {
            league,
            currentDrivers: 5,
            maxDrivers: 32,
          },
        ],
      });

      const vm = presenter.getViewModel();

      expect(vm.leagues[0]!.description).toBe('A test league with "quotes" and <tags> & symbols!');
    });
  });

  describe('getViewModel', () => {
    it('should throw error when not presented', () => {
      expect(() => presenter.getViewModel()).toThrow('Presenter not presented');
    });

    it('should return the model when presented', () => {
      presenter.present({ leagues: [] });

      const vm = presenter.getViewModel();

      expect(vm).toEqual({
        leagues: [],
        totalCount: 0,
      });
    });
  });
});