import type { IRaceRepository } from '../../domain/repositories/IRaceRepository'; import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository'; import type { IResultRepository } from '../../domain/repositories/IResultRepository'; import type { IStandingRepository } from '../../domain/repositories/IStandingRepository'; import { Result } from '../../domain/entities/Result'; import type { AsyncUseCase } from '@gridpilot/shared/application'; import { BusinessRuleViolationError, EntityNotFoundError, } from '../errors/RacingApplicationError'; import type { IImportRaceResultsPresenter, ImportRaceResultsSummaryViewModel, } from '../presenters/IImportRaceResultsPresenter'; export interface ImportRaceResultDTO { id: string; raceId: string; driverId: string; position: number; fastestLap: number; incidents: number; startPosition: number; } export interface ImportRaceResultsParams { raceId: string; results: ImportRaceResultDTO[]; } export class ImportRaceResultsUseCase implements AsyncUseCase { constructor( private readonly raceRepository: IRaceRepository, private readonly leagueRepository: ILeagueRepository, private readonly resultRepository: IResultRepository, private readonly standingRepository: IStandingRepository, public readonly presenter: IImportRaceResultsPresenter, ) {} async execute(params: ImportRaceResultsParams): Promise { const { raceId, results } = params; const race = await this.raceRepository.findById(raceId); if (!race) { throw new EntityNotFoundError({ entity: 'race', id: raceId }); } const league = await this.leagueRepository.findById(race.leagueId); if (!league) { throw new EntityNotFoundError({ entity: 'league', id: race.leagueId }); } const existing = await this.resultRepository.existsByRaceId(raceId); if (existing) { throw new BusinessRuleViolationError('Results already exist for this race'); } const entities = results.map((dto) => Result.create({ id: dto.id, raceId: dto.raceId, driverId: dto.driverId, position: dto.position, fastestLap: dto.fastestLap, incidents: dto.incidents, startPosition: dto.startPosition, }), ); await this.resultRepository.createMany(entities); await this.standingRepository.recalculate(league.id); const viewModel: ImportRaceResultsSummaryViewModel = { importedCount: results.length, standingsRecalculated: true, }; this.presenter.present(viewModel); } }