/** * Application Use Case: SubmitProtestDefenseUseCase * * Allows the accused driver to submit their defense statement for a protest. */ import { Logger } from '@core/shared/domain/Logger'; import { Result } from '@core/shared/domain/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { LeagueRepository } from '../../domain/repositories/LeagueRepository'; import type { ProtestRepository } from '../../domain/repositories/ProtestRepository'; export type SubmitProtestDefenseInput = { leagueId: string; protestId: string; driverId: string; defenseText: string; videoUrl?: string; }; export type SubmitProtestDefenseResult = { leagueId: string; protestId: string; driverId: string; status: 'defense_submitted'; }; export type SubmitProtestDefenseErrorCode = | 'LEAGUE_NOT_FOUND' | 'PROTEST_NOT_FOUND' | 'DRIVER_NOT_ALLOWED' | 'INVALID_PROTEST_STATE' | 'REPOSITORY_ERROR'; export class SubmitProtestDefenseUseCase { constructor(private readonly leagueRepository: LeagueRepository, private readonly protestRepository: ProtestRepository, private readonly logger: Logger) {} async execute( input: SubmitProtestDefenseInput, ): 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 protest = await this.protestRepository.findById(input.protestId); if (!protest) { return Result.err({ code: 'PROTEST_NOT_FOUND', details: { message: 'Protest not found' }, }); } if (protest.accusedDriverId !== input.driverId) { return Result.err({ code: 'DRIVER_NOT_ALLOWED', details: { message: 'Driver is not allowed to submit a defense for this protest' }, }); } if (!protest.canSubmitDefense()) { return Result.err({ code: 'INVALID_PROTEST_STATE', details: { message: 'Defense cannot be submitted for this protest' }, }); } const updatedProtest = protest.submitDefense(input.defenseText, input.videoUrl); await this.protestRepository.update(updatedProtest); const result: SubmitProtestDefenseResult = { leagueId: input.leagueId, protestId: protest.id, driverId: input.driverId, status: 'defense_submitted', }; return Result.ok(result); } catch (error: unknown) { const message = error instanceof Error && typeof error.message === 'string' ? error.message : 'Failed to submit protest defense'; this.logger.error( 'SubmitProtestDefenseUseCase.execute failed', error instanceof Error ? error : undefined, ); return Result.err({ code: 'REPOSITORY_ERROR', details: { message }, }); } } }