import { describe, expect, it, vi, type Mock } from 'vitest';
import { PrizeType, type Prize } from '../../domain/entities/Prize';
import type { PrizeRepository } from '../../domain/repositories/PrizeRepository';
import { DeletePrizeUseCase, type DeletePrizeInput } from './DeletePrizeUseCase';

describe('DeletePrizeUseCase', () => {
  let prizeRepository: { findById: Mock; delete: Mock };
  let useCase: DeletePrizeUseCase;

  beforeEach(() => {
    prizeRepository = {
      findById: vi.fn(),
      delete: vi.fn(),
    };

    useCase = new DeletePrizeUseCase(
      prizeRepository as unknown as PrizeRepository,
    );
  });

  it('returns PRIZE_NOT_FOUND when prize does not exist', async () => {
    prizeRepository.findById.mockResolvedValue(null);

    const input: DeletePrizeInput = { prizeId: 'prize-1' };
    const result = await useCase.execute(input);

    expect(result.isErr()).toBe(true);
    expect(result.unwrapErr().code).toBe('PRIZE_NOT_FOUND');
    expect(prizeRepository.delete).not.toHaveBeenCalled();
  });

  it('returns CANNOT_DELETE_AWARDED_PRIZE when prize is awarded', async () => {
    const prize: Prize = {
      id: 'prize-1',
      leagueId: 'league-1',
      seasonId: 'season-1',
      position: 1,
      name: 'Winner',
      amount: 100,
      type: PrizeType.CASH,
      awarded: true,
      awardedTo: 'driver-1',
      awardedAt: new Date(),
      createdAt: new Date(),
    };
    prizeRepository.findById.mockResolvedValue(prize);

    const input: DeletePrizeInput = { prizeId: 'prize-1' };
    const result = await useCase.execute(input);

    expect(result.isErr()).toBe(true);
    expect(result.unwrapErr().code).toBe('CANNOT_DELETE_AWARDED_PRIZE');
    expect(prizeRepository.delete).not.toHaveBeenCalled();
  });

  it('deletes prize and returns success', async () => {
    const prize: Prize = {
      id: 'prize-1',
      leagueId: 'league-1',
      seasonId: 'season-1',
      position: 1,
      name: 'Winner',
      amount: 100,
      type: PrizeType.CASH,
      awarded: false,
      createdAt: new Date(),
    };
    prizeRepository.findById.mockResolvedValue(prize);
    prizeRepository.delete.mockResolvedValue(undefined);

    const input: DeletePrizeInput = { prizeId: 'prize-1' };
    const result = await useCase.execute(input);

    expect(result.isOk()).toBe(true);
    expect(prizeRepository.delete).toHaveBeenCalledWith('prize-1');
    const value = result.value;
    expect(value.success).toBe(true);
  });
});