/**
 * Use Case: GetRaceProtestsUseCase
 *
 * Returns all protests filed for a specific race, with driver details.
 * Orchestrates domain logic and delegates presentation to the presenter.
 */

import { Result } from '@core/shared/domain/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { Driver } from '../../domain/entities/Driver';
import type { Protest } from '../../domain/entities/Protest';
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
import type { ProtestRepository } from '../../domain/repositories/ProtestRepository';

export interface GetRaceProtestsInput {
  raceId: string;
}

export type GetRaceProtestsErrorCode = 'REPOSITORY_ERROR';

export interface GetRaceProtestsResult {
  protests: Protest[];
  drivers: Driver[];
}

export class GetRaceProtestsUseCase {
  constructor(
    private readonly protestRepository: ProtestRepository,
    private readonly driverRepository: DriverRepository,
  ) {}

  async execute(
    input: GetRaceProtestsInput,
  ): Promise<Result<GetRaceProtestsResult, ApplicationErrorCode<GetRaceProtestsErrorCode, { message: string }>>> {
    try {
      const protests = await this.protestRepository.findByRaceId(input.raceId);

      const driverIds = new Set<string>();
      protests.forEach((protest) => {
        driverIds.add(protest.protestingDriverId);
        driverIds.add(protest.accusedDriverId);
        if (protest.reviewedBy) {
          driverIds.add(protest.reviewedBy);
        }
      });

      const drivers = await Promise.all(
        Array.from(driverIds).map((id) => this.driverRepository.findById(id)),
      );

      const validDrivers = drivers.filter((driver): driver is NonNullable<typeof driver> => driver !== null);

      const result: GetRaceProtestsResult = {
        protests,
        drivers: validDrivers,
      };

      return Result.ok(result);
    } catch (error: unknown) {
      const message =
        error instanceof Error && error.message
          ? error.message
          : 'Failed to load race protests';

      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: { message },
      });
    }
  }
}