/**
 * Application Use Case: FileProtestUseCase
 *
 * Allows a driver to file a protest against another driver for an incident during a race.
 */

import { Protest } from '../../domain/entities/Protest';
import type { IProtestRepository } from '../../domain/repositories/IProtestRepository';
import type { IRaceRepository } from '../../domain/repositories/IRaceRepository';
import type { ILeagueMembershipRepository } from '../../domain/repositories/ILeagueMembershipRepository';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { ProtestIncident } from '../../domain/entities/Protest';
import { randomUUID } from 'crypto';

export interface FileProtestCommand {
  raceId: string;
  protestingDriverId: string;
  accusedDriverId: string;
  incident: ProtestIncident;
  comment?: string;
  proofVideoUrl?: string;
}

export class FileProtestUseCase {
  constructor(
    private readonly protestRepository: IProtestRepository,
    private readonly raceRepository: IRaceRepository,
    private readonly leagueMembershipRepository: ILeagueMembershipRepository,
  ) {}

  async execute(command: FileProtestCommand): Promise<Result<{ protestId: string }, ApplicationErrorCode<'RACE_NOT_FOUND' | 'SELF_PROTEST' | 'NOT_MEMBER', { message: string }>>> {
    // Validate race exists
    const race = await this.raceRepository.findById(command.raceId);
    if (!race) {
      return Result.err({ code: 'RACE_NOT_FOUND', details: { message: 'Race not found' } });
    }

    // Validate drivers are not the same
    if (command.protestingDriverId === command.accusedDriverId) {
      return Result.err({ code: 'SELF_PROTEST', details: { message: 'Cannot file a protest against yourself' } });
    }

    // Validate protesting driver is a member of the league
    const memberships = await this.leagueMembershipRepository.getLeagueMembers(race.leagueId);
    const protestingDriverMembership = memberships.find(
      m => m.driverId === command.protestingDriverId && m.status === 'active'
    );

    if (!protestingDriverMembership) {
      return Result.err({ code: 'NOT_MEMBER', details: { message: 'Protesting driver is not an active member of this league' } });
    }

    // Create the protest
    const protest = Protest.create({
      id: randomUUID(),
      raceId: command.raceId,
      protestingDriverId: command.protestingDriverId,
      accusedDriverId: command.accusedDriverId,
      incident: command.incident,
      ...(command.comment !== undefined ? { comment: command.comment } : {}),
      ...(command.proofVideoUrl !== undefined ? { proofVideoUrl: command.proofVideoUrl } : {}),
      status: 'pending',
      filedAt: new Date(),
    });

    await this.protestRepository.create(protest);

    return Result.ok({ protestId: protest.id });
  }
}