import { Injectable, Inject } from '@nestjs/common'; import { CompleteOnboardingInputDTO } from './dtos/CompleteOnboardingInputDTO'; import { GetDriverRegistrationStatusQueryDTO } from './dtos/GetDriverRegistrationStatusQueryDTO'; // Use cases import { GetDriversLeaderboardUseCase } from '@core/racing/application/use-cases/GetDriversLeaderboardUseCase'; import { GetTotalDriversUseCase } from '@core/racing/application/use-cases/GetTotalDriversUseCase'; import { CompleteDriverOnboardingUseCase } from '@core/racing/application/use-cases/CompleteDriverOnboardingUseCase'; import { IsDriverRegisteredForRaceUseCase } from '@core/racing/application/use-cases/IsDriverRegisteredForRaceUseCase'; import { GetProfileOverviewUseCase } from '@core/racing/application/use-cases/GetProfileOverviewUseCase'; import { UpdateDriverProfileUseCase } from '@core/racing/application/use-cases/UpdateDriverProfileUseCase'; // Presenters import { DriverStatsPresenter } from './presenters/DriverStatsPresenter'; import { DriversLeaderboardPresenter } from './presenters/DriversLeaderboardPresenter'; import { CompleteOnboardingPresenter } from './presenters/CompleteOnboardingPresenter'; import { DriverRegistrationStatusPresenter } from './presenters/DriverRegistrationStatusPresenter'; import { DriverPresenter } from './presenters/DriverPresenter'; import { DriverProfilePresenter } from './presenters/DriverProfilePresenter'; // Tokens import { GET_DRIVERS_LEADERBOARD_USE_CASE_TOKEN, GET_TOTAL_DRIVERS_USE_CASE_TOKEN, COMPLETE_DRIVER_ONBOARDING_USE_CASE_TOKEN, IS_DRIVER_REGISTERED_FOR_RACE_USE_CASE_TOKEN, UPDATE_DRIVER_PROFILE_USE_CASE_TOKEN, GET_PROFILE_OVERVIEW_USE_CASE_TOKEN, LOGGER_TOKEN, DRIVER_REPOSITORY_TOKEN, } from './DriverProviders'; import type { Logger } from '@core/shared/application'; import { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository'; @Injectable() export class DriverService { constructor( @Inject(GET_DRIVERS_LEADERBOARD_USE_CASE_TOKEN) private readonly getDriversLeaderboardUseCase: GetDriversLeaderboardUseCase, @Inject(GET_TOTAL_DRIVERS_USE_CASE_TOKEN) private readonly getTotalDriversUseCase: GetTotalDriversUseCase, @Inject(COMPLETE_DRIVER_ONBOARDING_USE_CASE_TOKEN) private readonly completeDriverOnboardingUseCase: CompleteDriverOnboardingUseCase, @Inject(IS_DRIVER_REGISTERED_FOR_RACE_USE_CASE_TOKEN) private readonly isDriverRegisteredForRaceUseCase: IsDriverRegisteredForRaceUseCase, @Inject(UPDATE_DRIVER_PROFILE_USE_CASE_TOKEN) private readonly updateDriverProfileUseCase: UpdateDriverProfileUseCase, @Inject(GET_PROFILE_OVERVIEW_USE_CASE_TOKEN) private readonly getProfileOverviewUseCase: GetProfileOverviewUseCase, @Inject(DRIVER_REPOSITORY_TOKEN) private readonly driverRepository: IDriverRepository, @Inject(LOGGER_TOKEN) private readonly logger: Logger, ) {} async getDriversLeaderboard(): Promise { this.logger.debug('[DriverService] Fetching drivers leaderboard.'); const result = await this.getDriversLeaderboardUseCase.execute(); if (result.isErr()) { throw new Error(`Failed to fetch drivers leaderboard: ${result.unwrapErr().details.message}`); } const presenter = new DriversLeaderboardPresenter(); presenter.reset(); presenter.present(result.unwrap()); return presenter; } async getTotalDrivers(): Promise { this.logger.debug('[DriverService] Fetching total drivers count.'); const result = await this.getTotalDriversUseCase.execute(); if (result.isErr()) { throw new Error(result.unwrapErr().code); } const presenter = new DriverStatsPresenter(); presenter.reset(); presenter.present(result.unwrap()); return presenter; } async completeOnboarding(userId: string, input: CompleteOnboardingInputDTO): Promise { this.logger.debug('Completing onboarding for user:', userId); const result = await this.completeDriverOnboardingUseCase.execute({ userId, firstName: input.firstName, lastName: input.lastName, displayName: input.displayName, country: input.country, timezone: input.timezone, bio: input.bio, }); const presenter = new CompleteOnboardingPresenter(); presenter.reset(); if (result.isOk()) { presenter.present(result.value); } else { presenter.presentError(result.error.code); } return presenter; } async getDriverRegistrationStatus( query: GetDriverRegistrationStatusQueryDTO, ): Promise { this.logger.debug('Checking driver registration status:', query); const result = await this.isDriverRegisteredForRaceUseCase.execute({ raceId: query.raceId, driverId: query.driverId, }); if (result.isErr()) { throw new Error(`Failed to check registration status: ${result.unwrapErr().code}`); } const presenter = new DriverRegistrationStatusPresenter(); presenter.reset(); const output = result.unwrap(); presenter.present(output.isRegistered, output.raceId, output.driverId); return presenter; } async getCurrentDriver(userId: string): Promise { this.logger.debug(`[DriverService] Fetching current driver for userId: ${userId}`); const driver = await this.driverRepository.findById(userId); const presenter = new DriverPresenter(); presenter.reset(); presenter.present(driver ?? null); return presenter; } async updateDriverProfile( driverId: string, bio?: string, country?: string, ): Promise { this.logger.debug(`[DriverService] Updating driver profile for driverId: ${driverId}`); const result = await this.updateDriverProfileUseCase.execute({ driverId, bio, country }); const presenter = new DriverPresenter(); presenter.reset(); if (result.isErr()) { this.logger.error(`Failed to update driver profile: ${result.error.code}`); presenter.present(null); return presenter; } presenter.present(result.value); return presenter; } async getDriver(driverId: string): Promise { this.logger.debug(`[DriverService] Fetching driver for driverId: ${driverId}`); const driver = await this.driverRepository.findById(driverId); const presenter = new DriverPresenter(); presenter.reset(); presenter.present(driver ?? null); return presenter; } async getDriverProfile(driverId: string): Promise { this.logger.debug(`[DriverService] Fetching driver profile for driverId: ${driverId}`); const result = await this.getProfileOverviewUseCase.execute({ driverId }); if (result.isErr()) { throw new Error(`Failed to fetch driver profile: ${result.error.code}`); } const presenter = new DriverProfilePresenter(); presenter.reset(); presenter.present(result.value); return presenter; } }