import { Result } from '@core/shared/application/Result'; import type { Driver } from '@core/racing/domain/entities/Driver'; import type { GetDriverOutputDTO } from '../dtos/GetDriverOutputDTO'; import type { IDriverStatsRepository } from '@core/racing/domain/repositories/IDriverStatsRepository'; import type { MediaResolverPort } from '@core/ports/media/MediaResolverPort'; import { MediaReference } from '@core/domain/media/MediaReference'; export class DriverPresenter { private responseModel: GetDriverOutputDTO | null = null; private mediaResolver: MediaResolverPort | undefined; constructor( private readonly driverStatsRepository: IDriverStatsRepository, mediaResolver?: MediaResolverPort ) { this.mediaResolver = mediaResolver; } setMediaResolver(resolver: MediaResolverPort | undefined): void { this.mediaResolver = resolver; } // eslint-disable-next-line @typescript-eslint/no-explicit-any async present(result: Result): Promise { if (result.isErr()) { const error = result.unwrapErr(); throw new Error(error.details?.message ?? 'Failed to get driver'); } const driver = result.unwrap(); if (!driver) { this.responseModel = null; return; } // Get stats from repository (synchronously for now, could be async) const stats = this.driverStatsRepository.getDriverStatsSync(driver.id); // Resolve avatar URL using MediaResolverPort let avatarUrl: string | null = null; if (this.mediaResolver) { const ref = driver.avatarRef ?? MediaReference.createNone(); const resolvedRef = ref instanceof MediaReference ? ref : MediaReference.fromJSON(ref); const resolvedUrl = await this.mediaResolver.resolve(resolvedRef); avatarUrl = resolvedUrl ?? null; } const dto: GetDriverOutputDTO = { id: driver.id, iracingId: driver.iracingId.toString(), name: driver.name.toString(), country: driver.country.toString(), joinedAt: driver.joinedAt.toDate().toISOString(), avatarUrl, ...(driver.bio ? { bio: driver.bio.toString() } : {}), ...(driver.category ? { category: driver.category } : {}), // Add stats fields ...(stats ? { rating: stats.rating, wins: stats.wins, podiums: stats.podiums, totalRaces: stats.totalRaces, experienceLevel: this.getExperienceLevel(stats.rating), } : {}), }; this.responseModel = dto; } getResponseModel(): GetDriverOutputDTO | null { return this.responseModel; } private getExperienceLevel(rating: number): string { if (rating >= 1700) return 'veteran'; if (rating >= 1300) return 'advanced'; if (rating >= 1000) return 'intermediate'; return 'beginner'; } }