import type { IDriverRepository } from '../../domain/repositories/IDriverRepository'; import type { IRankingService } from '../../domain/services/IRankingService'; import type { IDriverStatsService } from '../../domain/services/IDriverStatsService'; import type { GetDriverAvatarInputPort } from '../ports/input/GetDriverAvatarInputPort'; import type { GetDriverAvatarOutputPort } from '../ports/output/GetDriverAvatarOutputPort'; import type { DriversLeaderboardOutputPort, DriverLeaderboardItemOutputPort } from '../ports/output/DriversLeaderboardOutputPort'; import type { SkillLevel } from '../../domain/services/SkillLevelService'; import type { AsyncUseCase, Logger } from '@core/shared/application'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; /** * Use Case for retrieving driver leaderboard data. * Orchestrates domain logic and returns result. */ export class GetDriversLeaderboardUseCase implements AsyncUseCase { constructor( private readonly driverRepository: IDriverRepository, private readonly rankingService: IRankingService, private readonly driverStatsService: IDriverStatsService, private readonly getDriverAvatar: (input: GetDriverAvatarInputPort) => Promise, private readonly logger: Logger, ) {} async execute(): Promise>> { this.logger.debug('Executing GetDriversLeaderboardUseCase'); try { const drivers = await this.driverRepository.findAll(); const rankings = this.rankingService.getAllDriverRankings(); const avatarUrls: Record = {}; for (const driver of drivers) { const avatarResult = await this.getDriverAvatar({ driverId: driver.id }); avatarUrls[driver.id] = avatarResult.avatarUrl; } const driverItems: DriverLeaderboardItemOutputPort[] = drivers.map(driver => { const ranking = rankings.find(r => r.driverId === driver.id); const stats = this.driverStatsService.getDriverStats(driver.id); return { id: driver.id, name: driver.name.value, rating: ranking?.rating ?? 0, skillLevel: 'Pro' as SkillLevel, // TODO: map from domain nationality: driver.country.value, racesCompleted: stats?.totalRaces ?? 0, wins: stats?.wins ?? 0, podiums: stats?.podiums ?? 0, isActive: true, // TODO: determine from domain rank: ranking?.overallRank ?? 0, avatarUrl: avatarUrls[driver.id], }; }); // Calculate totals const totalRaces = driverItems.reduce((sum, d) => sum + d.racesCompleted, 0); const totalWins = driverItems.reduce((sum, d) => sum + d.wins, 0); const activeCount = driverItems.filter(d => d.isActive).length; const result: DriversLeaderboardOutputPort = { drivers: driverItems.sort((a, b) => b.rating - a.rating), totalRaces, totalWins, activeCount, }; this.logger.debug('Successfully retrieved drivers leaderboard.'); return Result.ok(result); } catch (error) { this.logger.error('Error executing GetDriversLeaderboardUseCase', error instanceof Error ? error : new Error(String(error))); return Result.err({ code: 'REPOSITORY_ERROR', details: { message: error instanceof Error ? error.message : 'Unknown error occurred' }, }); } } }