import type { IRaceRepository } from '../../domain/repositories/IRaceRepository'; import type { IProtestRepository } from '../../domain/repositories/IProtestRepository'; import type { IDriverRepository } from '../../domain/repositories/IDriverRepository'; import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import { Result } from '@core/shared/application/Result'; import type { UseCaseOutputPort } from '@core/shared/application'; import type { Race } from '../../domain/entities/Race'; import type { Protest } from '../../domain/entities/Protest'; import type { Driver } from '../../domain/entities/Driver'; import type { League } from '../../domain/entities/League'; export interface GetLeagueProtestsInput { leagueId: string; } export type GetLeagueProtestsErrorCode = 'LEAGUE_NOT_FOUND' | 'REPOSITORY_ERROR'; export interface LeagueProtestWithEntities { protest: Protest; race: Race | null; protestingDriver: Driver | null; accusedDriver: Driver | null; } export interface GetLeagueProtestsResult { league: League; protests: LeagueProtestWithEntities[]; } export class GetLeagueProtestsUseCase { constructor( private readonly raceRepository: IRaceRepository, private readonly protestRepository: IProtestRepository, private readonly driverRepository: IDriverRepository, private readonly leagueRepository: ILeagueRepository, private readonly output: UseCaseOutputPort, ) {} get outputPort(): UseCaseOutputPort { return this.output; } async execute( input: GetLeagueProtestsInput, ): Promise>> { try { const league = await this.leagueRepository.findById(input.leagueId); if (!league) { return Result.err({ code: 'LEAGUE_NOT_FOUND', details: { message: 'League not found' }, }); } const races = await this.raceRepository.findByLeagueId(input.leagueId); const protests: Protest[] = []; const racesById: Record = {}; const driversById: Record = {}; const driverIds = new Set(); for (const race of races) { racesById[race.id] = race; const raceProtests = await this.protestRepository.findByRaceId(race.id); for (const protest of raceProtests) { protests.push(protest); driverIds.add(protest.protestingDriverId); driverIds.add(protest.accusedDriverId); } } for (const driverId of driverIds) { const driver = await this.driverRepository.findById(driverId); if (driver) { driversById[driver.id] = driver; } } const protestsWithEntities: LeagueProtestWithEntities[] = protests.map(protest => ({ protest, race: racesById[protest.raceId] ?? null, protestingDriver: driversById[protest.protestingDriverId] ?? null, accusedDriver: driversById[protest.accusedDriverId] ?? null, })); const result: GetLeagueProtestsResult = { league, protests: protestsWithEntities, }; this.output.present(result); return Result.ok(undefined); } catch (error: unknown) { const message = error instanceof Error && error.message ? error.message : 'Failed to load league protests'; return Result.err({ code: 'REPOSITORY_ERROR', details: { message }, }); } } }