/* eslint-disable @typescript-eslint/no-explicit-any */
import { Result } from '@core/shared/domain/Result';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { DriverService } from './DriverService';

describe('DriverService', () => {
  const logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() };
  
  // Mocks for use cases
  const getDriversLeaderboardUseCase = { execute: vi.fn() };
  const getTotalDriversUseCase = { execute: vi.fn() };
  const getDriverLiveriesUseCase = { execute: vi.fn() };
  const completeDriverOnboardingUseCase = { execute: vi.fn() };
  const isDriverRegisteredForRaceUseCase = { execute: vi.fn() };
  const updateDriverProfileUseCase = { execute: vi.fn() };
  const getProfileOverviewUseCase = { execute: vi.fn() };
  const getDriverUseCase = { execute: vi.fn() };
  
  // Mocks for presenters
  const driversLeaderboardPresenter = { present: vi.fn(), getResponseModel: vi.fn() };
  const driverStatsPresenter = { present: vi.fn(), getResponseModel: vi.fn() };
  const completeOnboardingPresenter = { present: vi.fn(), getResponseModel: vi.fn() };
  const driverRegistrationStatusPresenter = { present: vi.fn(), getResponseModel: vi.fn() };
  const driverPresenter = { present: vi.fn(), getResponseModel: vi.fn() };
  const driverProfilePresenter = { present: vi.fn(), getResponseModel: vi.fn() };
  const getDriverLiveriesPresenter = { present: vi.fn(), getResponseModel: vi.fn() };

  beforeEach(() => {
    vi.clearAllMocks();
    
    // Default successful responses
    getDriversLeaderboardUseCase.execute.mockResolvedValue(Result.ok(undefined));
    getTotalDriversUseCase.execute.mockResolvedValue(Result.ok(undefined));
    getDriverLiveriesUseCase.execute.mockResolvedValue(Result.ok(undefined));
    completeDriverOnboardingUseCase.execute.mockResolvedValue(Result.ok(undefined));
    isDriverRegisteredForRaceUseCase.execute.mockResolvedValue(Result.ok(undefined));
    updateDriverProfileUseCase.execute.mockResolvedValue(Result.ok(undefined));
    getProfileOverviewUseCase.execute.mockResolvedValue(Result.ok(undefined));
    getDriverUseCase.execute.mockResolvedValue(Result.ok(null));
    
    driversLeaderboardPresenter.getResponseModel.mockReturnValue({ items: [] });
    driverStatsPresenter.getResponseModel.mockReturnValue({ totalDrivers: 0 });
    completeOnboardingPresenter.getResponseModel.mockReturnValue({ success: true });
    driverRegistrationStatusPresenter.getResponseModel.mockReturnValue({ isRegistered: false });
    driverPresenter.getResponseModel.mockReturnValue(null);
    driverProfilePresenter.getResponseModel.mockReturnValue({ profile: {} });
    getDriverLiveriesPresenter.getResponseModel.mockReturnValue({ liveries: [] });
  });

  const createService = () => {
    return new DriverService(
      getDriversLeaderboardUseCase as never,
      getTotalDriversUseCase as never,
      getDriverLiveriesUseCase as never,
      completeDriverOnboardingUseCase as never,
      isDriverRegisteredForRaceUseCase as never,
      updateDriverProfileUseCase as never,
      getProfileOverviewUseCase as never,
      getDriverUseCase as never,
      logger as never,
      driversLeaderboardPresenter as never,
      driverStatsPresenter as never,
      completeOnboardingPresenter as never,
      driverRegistrationStatusPresenter as never,
      driverPresenter as never,
      driverProfilePresenter as never,
      getDriverLiveriesPresenter as never,
    );
  };

  it('getDriversLeaderboard executes use case and returns presenter model', async () => {
    const service = createService();
    driversLeaderboardPresenter.getResponseModel.mockReturnValue({ items: [] });

    await expect(service.getDriversLeaderboard()).resolves.toEqual({ items: [] });
    expect(getDriversLeaderboardUseCase.execute).toHaveBeenCalledWith({});
    expect(driversLeaderboardPresenter.getResponseModel).toHaveBeenCalled();
  });

  it('getTotalDrivers executes use case and returns presenter model', async () => {
    const service = createService();
    driverStatsPresenter.getResponseModel.mockReturnValue({ totalDrivers: 123 });

    await expect(service.getTotalDrivers()).resolves.toEqual({ totalDrivers: 123 });
    expect(getTotalDriversUseCase.execute).toHaveBeenCalledWith({});
    expect(driverStatsPresenter.getResponseModel).toHaveBeenCalled();
  });

  it('completeOnboarding passes optional bio only when provided', async () => {
    const service = createService();

    await service.completeOnboarding('u1', {
      firstName: 'F',
      lastName: 'L',
      displayName: 'D',
      country: 'DE',
    } as never);

    expect(completeDriverOnboardingUseCase.execute).toHaveBeenCalledWith({
      userId: 'u1',
      firstName: 'F',
      lastName: 'L',
      displayName: 'D',
      country: 'DE',
    });

    completeDriverOnboardingUseCase.execute.mockClear();

    await service.completeOnboarding('u1', {
      firstName: 'F',
      lastName: 'L',
      displayName: 'D',
      country: 'DE',
      bio: 'bio',
    } as never);

    expect(completeDriverOnboardingUseCase.execute).toHaveBeenCalledWith({
      userId: 'u1',
      firstName: 'F',
      lastName: 'L',
      displayName: 'D',
      country: 'DE',
      bio: 'bio',
    });
  });

  it('getDriverRegistrationStatus passes raceId and driverId and returns presenter model', async () => {
    const service = createService();
    driverRegistrationStatusPresenter.getResponseModel.mockReturnValue({ isRegistered: true });

    await expect(
      service.getDriverRegistrationStatus({ raceId: 'r1', driverId: 'd1' } as never),
    ).resolves.toEqual({ isRegistered: true });

    expect(isDriverRegisteredForRaceUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1', driverId: 'd1' });
    expect(driverRegistrationStatusPresenter.getResponseModel).toHaveBeenCalled();
  });

  it('getCurrentDriver calls use case and returns presenter model', async () => {
    const service = createService();
    getDriverUseCase.execute.mockResolvedValue(Result.ok(null));

    await expect(service.getCurrentDriver('u1')).resolves.toBeNull();
    expect(getDriverUseCase.execute).toHaveBeenCalledWith({ driverId: 'u1' });
    expect(driverPresenter.getResponseModel).toHaveBeenCalled();
  });

  it('updateDriverProfile builds optional input and returns presenter model', async () => {
    const service = createService();
    driverPresenter.getResponseModel.mockReturnValue({ driver: { id: 'd1' } });

    await service.updateDriverProfile('d1');
    expect(updateDriverProfileUseCase.execute).toHaveBeenCalledWith({ driverId: 'd1' });

    updateDriverProfileUseCase.execute.mockClear();

    await service.updateDriverProfile('d1', 'bio');
    expect(updateDriverProfileUseCase.execute).toHaveBeenCalledWith({ driverId: 'd1', bio: 'bio' });

    updateDriverProfileUseCase.execute.mockClear();

    await service.updateDriverProfile('d1', undefined, 'DE');
    expect(updateDriverProfileUseCase.execute).toHaveBeenCalledWith({ driverId: 'd1', country: 'DE' });

    updateDriverProfileUseCase.execute.mockClear();

    await service.updateDriverProfile('d1', 'bio', 'DE');
    expect(updateDriverProfileUseCase.execute).toHaveBeenCalledWith({ driverId: 'd1', bio: 'bio', country: 'DE' });

    expect(driverPresenter.getResponseModel).toHaveBeenCalled();
  });

  it('getDriver calls use case and returns presenter model', async () => {
    const service = createService();
    getDriverUseCase.execute.mockResolvedValue(Result.ok(null));

    await expect(service.getDriver('d1')).resolves.toBeNull();
    expect(getDriverUseCase.execute).toHaveBeenCalledWith({ driverId: 'd1' });
  });

  it('getDriverProfile executes use case and returns presenter model', async () => {
    const service = createService();
    driverProfilePresenter.getResponseModel.mockReturnValue({ profile: { id: 'd1' } });

    await expect(service.getDriverProfile('d1')).resolves.toEqual({ profile: { id: 'd1' } });
    expect(getProfileOverviewUseCase.execute).toHaveBeenCalledWith({ driverId: 'd1' });
    expect(driverProfilePresenter.getResponseModel).toHaveBeenCalled();
  });

  it('getDriverLiveries executes use case and returns presenter model', async () => {
    const service = createService();
    getDriverLiveriesPresenter.getResponseModel.mockReturnValue({ liveries: [] });

    await expect(service.getDriverLiveries('d1')).resolves.toEqual({ liveries: [] });
    expect(getDriverLiveriesUseCase.execute).toHaveBeenCalledWith({ driverId: 'd1' });
    expect(getDriverLiveriesPresenter.present).toHaveBeenCalled();
    expect(getDriverLiveriesPresenter.getResponseModel).toHaveBeenCalled();
  });
});
