import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { LeagueScoringPreset } from '../../domain/types/LeagueScoringPreset';
import {
    ListLeagueScoringPresetsUseCase,
    type ListLeagueScoringPresetsErrorCode,
    type ListLeagueScoringPresetsInput,
} from './ListLeagueScoringPresetsUseCase';

describe('ListLeagueScoringPresetsUseCase', () => {
  let useCase: ListLeagueScoringPresetsUseCase;
  beforeEach(() => {
    const mockPresets = [
      {
        id: 'preset-1',
        name: 'Preset 1',
        description: 'Desc 1',
        primaryChampionshipType: 'driver' as const,
        dropPolicySummary: 'Drop 1',
        sessionSummary: 'Session 1',
        bonusSummary: 'Bonus 1',
        defaultTimings: {
          practiceMinutes: 15,
          qualifyingMinutes: 10,
          sprintRaceMinutes: 20,
          mainRaceMinutes: 30,
          sessionCount: 2,
        },
        createConfig: vi.fn(),
      },
      {
        id: 'preset-2',
        name: 'Preset 2',
        description: 'Desc 2',
        primaryChampionshipType: 'team' as const,
        dropPolicySummary: 'Drop 2',
        sessionSummary: 'Session 2',
        bonusSummary: 'Bonus 2',
        defaultTimings: {
          practiceMinutes: 20,
          qualifyingMinutes: 15,
          sprintRaceMinutes: 25,
          mainRaceMinutes: 40,
          sessionCount: 3,
        },
        createConfig: vi.fn(),
      },
    ];

    useCase = new ListLeagueScoringPresetsUseCase(mockPresets as unknown as LeagueScoringPreset[]);
  });

  it('should list presets successfully', async () => {
    const input: ListLeagueScoringPresetsInput = {};

    const result = await useCase.execute(input);

    expect(result.isOk()).toBe(true);
    const presented = result.unwrap();

    expect(presented).toEqual({
      presets: [
        {
          id: 'preset-1',
          name: 'Preset 1',
          description: 'Desc 1',
          primaryChampionshipType: 'driver',
          sessionSummary: 'Session 1',
          bonusSummary: 'Bonus 1',
          dropPolicySummary: 'Drop 1',
          defaultTimings: {
            practiceMinutes: 15,
            qualifyingMinutes: 10,
            sprintRaceMinutes: 20,
            mainRaceMinutes: 30,
            sessionCount: 2,
          },
        },
        {
          id: 'preset-2',
          name: 'Preset 2',
          description: 'Desc 2',
          primaryChampionshipType: 'team',
          sessionSummary: 'Session 2',
          bonusSummary: 'Bonus 2',
          dropPolicySummary: 'Drop 2',
          defaultTimings: {
            practiceMinutes: 20,
            qualifyingMinutes: 15,
            sprintRaceMinutes: 25,
            mainRaceMinutes: 40,
            sessionCount: 3,
          },
        },
      ],
    });
  });

  it('should return repository error when mapping fails', async () => {
    const failingPresets = {
      map: () => {
        throw new Error('Repository failure');
      },
    } as unknown as LeagueScoringPreset[];

    useCase = new ListLeagueScoringPresetsUseCase(failingPresets);

    const input: ListLeagueScoringPresetsInput = {};

    const result = await useCase.execute(input);

    expect(result.isErr()).toBe(true);

    const error = result.unwrapErr() as ApplicationErrorCode<
      ListLeagueScoringPresetsErrorCode,
      { message: string }
    >;

    expect(error.code).toBe('REPOSITORY_ERROR');
    expect(error.details?.message).toBe('Repository failure');
  });
});
