import { Result } from '@core/shared/domain/Result'; import { Inject, Injectable } from '@nestjs/common'; import { CompleteOnboardingInputDTO } from './dtos/CompleteOnboardingInputDTO'; import { CompleteOnboardingOutputDTO } from './dtos/CompleteOnboardingOutputDTO'; import { DriverRegistrationStatusDTO } from './dtos/DriverRegistrationStatusDTO'; import { DriversLeaderboardDTO } from './dtos/DriversLeaderboardDTO'; import { DriverStatsDTO } from './dtos/DriverStatsDTO'; import { GetDriverLiveriesOutputDTO } from './dtos/GetDriverLiveriesOutputDTO'; import { GetDriverOutputDTO } from './dtos/GetDriverOutputDTO'; import { GetDriverProfileOutputDTO } from './dtos/GetDriverProfileOutputDTO'; import { GetDriverRegistrationStatusQueryDTO } from './dtos/GetDriverRegistrationStatusQueryDTO'; // Use cases import { CompleteDriverOnboardingUseCase } from '@core/racing/application/use-cases/CompleteDriverOnboardingUseCase'; import { GetDriverLiveriesUseCase } from '@core/racing/application/use-cases/GetDriverLiveriesUseCase'; import { GetDriversLeaderboardUseCase } from '@core/racing/application/use-cases/GetDriversLeaderboardUseCase'; import { GetDriverUseCase } from '@core/racing/application/use-cases/GetDriverUseCase'; import { GetProfileOverviewUseCase } from '@core/racing/application/use-cases/GetProfileOverviewUseCase'; import { GetTotalDriversUseCase } from '@core/racing/application/use-cases/GetTotalDriversUseCase'; import { IsDriverRegisteredForRaceUseCase } from '@core/racing/application/use-cases/IsDriverRegisteredForRaceUseCase'; import { UpdateDriverProfileUseCase, type UpdateDriverProfileInput } from '@core/racing/application/use-cases/UpdateDriverProfileUseCase'; // Presenters import { CompleteOnboardingPresenter } from './presenters/CompleteOnboardingPresenter'; import { DriverPresenter } from './presenters/DriverPresenter'; import { DriverProfilePresenter } from './presenters/DriverProfilePresenter'; import { DriverRegistrationStatusPresenter } from './presenters/DriverRegistrationStatusPresenter'; import { DriversLeaderboardPresenter } from './presenters/DriversLeaderboardPresenter'; import { DriverStatsPresenter } from './presenters/DriverStatsPresenter'; import { GetDriverLiveriesPresenter } from './presenters/GetDriverLiveriesPresenter'; // Tokens import type { Logger } from '@core/shared/domain/Logger'; import { COMPLETE_DRIVER_ONBOARDING_USE_CASE_TOKEN, GET_DRIVER_LIVERIES_USE_CASE_TOKEN, GET_DRIVER_USE_CASE_TOKEN, GET_DRIVERS_LEADERBOARD_USE_CASE_TOKEN, GET_PROFILE_OVERVIEW_USE_CASE_TOKEN, GET_TOTAL_DRIVERS_USE_CASE_TOKEN, IS_DRIVER_REGISTERED_FOR_RACE_USE_CASE_TOKEN, LOGGER_TOKEN, UPDATE_DRIVER_PROFILE_USE_CASE_TOKEN, } from './DriverTokens'; @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(GET_DRIVER_LIVERIES_USE_CASE_TOKEN) private readonly getDriverLiveriesUseCase: GetDriverLiveriesUseCase, @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(GET_DRIVER_USE_CASE_TOKEN) private readonly getDriverUseCase: GetDriverUseCase, @Inject(LOGGER_TOKEN) private readonly logger: Logger, // Injected presenters (optional for module test compatibility) private readonly driversLeaderboardPresenter?: DriversLeaderboardPresenter, private readonly driverStatsPresenter?: DriverStatsPresenter, private readonly completeOnboardingPresenter?: CompleteOnboardingPresenter, private readonly driverRegistrationStatusPresenter?: DriverRegistrationStatusPresenter, private readonly driverPresenter?: DriverPresenter, private readonly driverProfilePresenter?: DriverProfilePresenter, private readonly getDriverLiveriesPresenter?: GetDriverLiveriesPresenter, ) { // Presenters are configured by providers, no need to configure here } async getDriversLeaderboard(): Promise { this.logger.debug('[DriverService] Fetching drivers leaderboard.'); const result = await this.getDriversLeaderboardUseCase.execute({}); if (result.isErr()) { throw new Error(result.unwrapErr().details.message); } await this.driversLeaderboardPresenter!.present(result.unwrap()); return this.driversLeaderboardPresenter!.getResponseModel(); } 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().details.message); } await this.driverStatsPresenter!.present(result.unwrap()); return this.driverStatsPresenter!.getResponseModel(); } 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, ...(input.bio !== undefined ? { bio: input.bio } : {}), }); if (result.isErr()) { throw new Error(result.unwrapErr().details.message); } await this.completeOnboardingPresenter!.present(result.unwrap()); return this.completeOnboardingPresenter!.getResponseModel(); } 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(result.unwrapErr().details.message); } await this.driverRegistrationStatusPresenter!.present(result.unwrap()); return this.driverRegistrationStatusPresenter!.getResponseModel(); } async getCurrentDriver(userId: string): Promise { this.logger.debug(`[DriverService] Fetching current driver for userId: ${userId}`); const result = await this.getDriverUseCase.execute({ driverId: userId }); if (result.isErr()) { throw new Error(result.unwrapErr().message); } await this.driverPresenter!.present(Result.ok(result.unwrap())); return this.driverPresenter!.getResponseModel(); } async updateDriverProfile( driverId: string, bio?: string, country?: string, ): Promise { this.logger.debug(`[DriverService] Updating driver profile for driverId: ${driverId}`); const input: UpdateDriverProfileInput = { driverId }; if (bio !== undefined) input.bio = bio; if (country !== undefined) input.country = country; await this.updateDriverProfileUseCase.execute(input); // Get the updated driver and present it const result = await this.getDriverUseCase.execute({ driverId }); if (result.isErr()) { throw new Error(result.unwrapErr().message); } await this.driverPresenter!.present(Result.ok(result.unwrap())); return this.driverPresenter!.getResponseModel(); } async getDriver(driverId: string): Promise { this.logger.debug(`[DriverService] Fetching driver for driverId: ${driverId}`); const result = await this.getDriverUseCase.execute({ driverId }); if (result.isErr()) { throw new Error(result.unwrapErr().message); } const driver = result.unwrap(); if (!driver) { return null; } await this.driverPresenter!.present(Result.ok(driver)); return this.driverPresenter!.getResponseModel(); } 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(result.unwrapErr().details.message); } await this.driverProfilePresenter!.present(result.unwrap()); return this.driverProfilePresenter!.getResponseModel(); } async getDriverLiveries(driverId: string): Promise { this.logger.debug(`[DriverService] Fetching driver liveries for driverId: ${driverId}`); const result = await this.getDriverLiveriesUseCase.execute({ driverId }); if (result.isErr()) { throw new Error(result.unwrapErr().details.message); } await this.getDriverLiveriesPresenter!.present(result); return this.getDriverLiveriesPresenter!.getResponseModel()!; } }