import type { ILeagueMembershipRepository } from '../../domain/repositories/ILeagueMembershipRepository'; import type { IRaceRepository } from '../../domain/repositories/IRaceRepository'; import type { LeagueStatsOutputPort } from '../ports/output/LeagueStatsOutputPort'; import type { GetDriverRatingInputPort } from '../ports/input/GetDriverRatingInputPort'; import type { GetDriverRatingOutputPort } from '../ports/output/GetDriverRatingOutputPort'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; export interface GetLeagueStatsUseCaseParams { leagueId: string; } export class GetLeagueStatsUseCase { constructor( private readonly leagueMembershipRepository: ILeagueMembershipRepository, private readonly raceRepository: IRaceRepository, private readonly getDriverRating: (input: GetDriverRatingInputPort) => Promise, ) {} async execute(params: GetLeagueStatsUseCaseParams): Promise>> { try { const memberships = await this.leagueMembershipRepository.getLeagueMembers(params.leagueId); const races = await this.raceRepository.findByLeagueId(params.leagueId); const driverIds = memberships.map(m => m.driverId); // Get ratings for all drivers using clean ports const ratingPromises = driverIds.map(driverId => this.getDriverRating({ driverId }) ); const ratingResults = await Promise.all(ratingPromises); const validRatings = ratingResults .map(result => result.rating) .filter((rating): rating is number => rating !== null); const averageRating = validRatings.length > 0 ? Math.round(validRatings.reduce((sum, r) => sum + r, 0) / validRatings.length) : 0; const viewModel: LeagueStatsOutputPort = { totalMembers: memberships.length, totalRaces: races.length, averageRating, }; return Result.ok(viewModel); } catch { return Result.err({ code: 'REPOSITORY_ERROR', message: 'Failed to fetch league stats' }); } } }