import type { IRaceRepository } from '../../domain/repositories/IRaceRepository'; import type { IProtestRepository } from '../../domain/repositories/IProtestRepository'; import type { IDriverRepository } from '../../domain/repositories/IDriverRepository'; import type { AsyncUseCase } from '@core/shared/application'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { GetLeagueProtestsOutputPort, ProtestOutputPort, RaceOutputPort, DriverOutputPort } from '../ports/output/GetLeagueProtestsOutputPort'; export interface GetLeagueProtestsUseCaseParams { leagueId: string; } export class GetLeagueProtestsUseCase implements AsyncUseCase { constructor( private readonly raceRepository: IRaceRepository, private readonly protestRepository: IProtestRepository, private readonly driverRepository: IDriverRepository, ) {} async execute(params: GetLeagueProtestsUseCaseParams): Promise>> { const races = await this.raceRepository.findByLeagueId(params.leagueId); const protests: ProtestOutputPort[] = []; const racesById: Record = {}; const driversById: Record = {}; const driverIds = new Set(); for (const race of races) { racesById[race.id] = { id: race.id, leagueId: race.leagueId, scheduledAt: race.scheduledAt.toISOString(), track: race.track, trackId: race.trackId, car: race.car, carId: race.carId, sessionType: race.sessionType.toString(), status: race.status, strengthOfField: race.strengthOfField, registeredCount: race.registeredCount, maxParticipants: race.maxParticipants, }; const raceProtests = await this.protestRepository.findByRaceId(race.id); for (const protest of raceProtests) { protests.push({ id: protest.id, raceId: protest.raceId, protestingDriverId: protest.protestingDriverId, accusedDriverId: protest.accusedDriverId, incident: { lap: protest.incident.lap, description: protest.incident.description, timeInRace: protest.incident.timeInRace, }, comment: protest.comment, proofVideoUrl: protest.proofVideoUrl, status: protest.status.toString(), reviewedBy: protest.reviewedBy, decisionNotes: protest.decisionNotes, filedAt: protest.filedAt.toISOString(), reviewedAt: protest.reviewedAt?.toISOString(), defense: protest.defense ? { statement: protest.defense.statement.toString(), videoUrl: protest.defense.videoUrl?.toString(), submittedAt: protest.defense.submittedAt.toDate().toISOString(), } : undefined, defenseRequestedAt: protest.defenseRequestedAt?.toISOString(), defenseRequestedBy: protest.defenseRequestedBy, }); 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] = { id: driver.id, iracingId: driver.iracingId.toString(), name: driver.name.toString(), country: driver.country.toString(), bio: driver.bio?.toString(), joinedAt: driver.joinedAt.toDate().toISOString(), }; } } return Result.ok({ protests, racesById, driversById, }); } }