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 { SkillLevelService, 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); const rating = ranking?.rating ?? 0; const racesCompleted = stats?.totalRaces ?? 0; const skillLevel: SkillLevel = SkillLevelService.getSkillLevel(rating); return { id: driver.id, name: driver.name.value, rating, skillLevel, nationality: driver.country.value, racesCompleted, wins: stats?.wins ?? 0, podiums: stats?.podiums ?? 0, isActive: racesCompleted > 0, 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' }, }); } } }