import type { Logger } from '@core/shared/domain/Logger';
import { describe, expect, it, vi } from 'vitest';
import type { DriverLivery } from '../../domain/entities/DriverLivery';
import { LiveryRepository } from '../../domain/repositories/LiveryRepository';
import { GetDriverLiveriesUseCase, type GetDriverLiveriesInput } from './GetDriverLiveriesUseCase';

describe('GetDriverLiveriesUseCase', () => {
  const mockLiveryRepository: LiveryRepository = {
    findDriverLiveryById: vi.fn(),
    findDriverLiveriesByDriverId: vi.fn(),
    findDriverLiveryByDriverAndCar: vi.fn(),
    findDriverLiveriesByGameId: vi.fn(),
    findDriverLiveryByDriverAndGame: vi.fn(),
    createDriverLivery: vi.fn(),
    updateDriverLivery: vi.fn(),
    deleteDriverLivery: vi.fn(),
    findTemplateById: vi.fn(),
    findTemplatesBySeasonId: vi.fn(),
    findTemplateBySeasonAndCar: vi.fn(),
    createTemplate: vi.fn(),
    updateTemplate: vi.fn(),
    deleteTemplate: vi.fn(),
  };

  const mockLogger: Logger = {
    debug: vi.fn(),
    info: vi.fn(),
    warn: vi.fn(),
    error: vi.fn(),
  };

  it('should return driver liveries successfully', async () => {
    const useCase = new GetDriverLiveriesUseCase(mockLiveryRepository, mockLogger);

    const mockLiveries: DriverLivery[] = [
      {
        id: 'livery1',
        driverId: { value: 'driver1' },
        gameId: { value: 'game1' },
        carId: { value: 'car1' },
        uploadedImageUrl: { value: 'http://example.com/livery1.png' },
        userDecals: [],
        leagueOverrides: [],
        createdAt: new Date('2023-01-01'),
        updatedAt: undefined,
        validatedAt: undefined,
      } as DriverLivery,
      {
        id: 'livery2',
        driverId: { value: 'driver1' },
        gameId: { value: 'game1' },
        carId: { value: 'car2' },
        uploadedImageUrl: { value: 'http://example.com/livery2.png' },
        userDecals: [],
        leagueOverrides: [],
        createdAt: new Date('2023-01-02'),
        updatedAt: undefined,
        validatedAt: undefined,
      } as DriverLivery,
    ];

    mockLiveryRepository.findDriverLiveriesByDriverId.mockResolvedValue(mockLiveries);

    const input: GetDriverLiveriesInput = { driverId: 'driver1' };

    const result = await useCase.execute(input);

    expect(result.isOk()).toBe(true);
    expect(result.unwrap()).toEqual(mockLiveries);
    expect(mockLiveryRepository.findDriverLiveriesByDriverId).toHaveBeenCalledWith('driver1');
  });

  it('should return empty array when no liveries found', async () => {
    const useCase = new GetDriverLiveriesUseCase(mockLiveryRepository, mockLogger);

    mockLiveryRepository.findDriverLiveriesByDriverId.mockResolvedValue([]);

    const input: GetDriverLiveriesInput = { driverId: 'driver1' };

    const result = await useCase.execute(input);

    expect(result.isOk()).toBe(true);
    expect(result.unwrap()).toEqual([]);
  });

  it('should return error when repository throws', async () => {
    const useCase = new GetDriverLiveriesUseCase(mockLiveryRepository, mockLogger);

    const error = new Error('Repository error');
    mockLiveryRepository.findDriverLiveriesByDriverId.mockRejectedValue(error);

    const input: GetDriverLiveriesInput = { driverId: 'driver1' };

    const result = await useCase.execute(input);

    expect(result.isErr()).toBe(true);
    const err = result.unwrapErr();
    expect(err.code).toBe('REPOSITORY_ERROR');
    expect(err.details.message).toBe('Repository error');
  });
});