import { Result } from '@core/shared/domain/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { Driver } from '../../domain/entities/Driver';
import type { Team } from '../../domain/entities/Team';
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
import type { TeamJoinRequest } from '../../domain/types/TeamMembership';

export type GetTeamJoinRequestsInput = {
  teamId: string;
};

export type GetTeamJoinRequestsErrorCode = 'TEAM_NOT_FOUND' | 'REPOSITORY_ERROR';

export type TeamJoinRequestWithDriver = TeamJoinRequest & {
  driver: Driver;
};

export type GetTeamJoinRequestsResult = {
  team: Team;
  joinRequests: TeamJoinRequestWithDriver[];
};

export class GetTeamJoinRequestsUseCase {
  constructor(private readonly membershipRepository: TeamMembershipRepository,
    private readonly driverRepository: DriverRepository,
    private readonly teamRepository: TeamRepository) {}

  async execute(
    input: GetTeamJoinRequestsInput,
  ): Promise<Result<GetTeamJoinRequestsResult, ApplicationErrorCode<GetTeamJoinRequestsErrorCode, { message: string }>>> {
    try {
      const team = await this.teamRepository.findById(input.teamId);

      if (!team) {
        return Result.err({
          code: 'TEAM_NOT_FOUND',
          details: { message: 'Team not found' },
        });
      }

      const joinRequests = await this.membershipRepository.getJoinRequests(input.teamId);
      const driverIds = [...new Set(joinRequests.map(request => request.driverId))];
      const drivers = await Promise.all(driverIds.map(id => this.driverRepository.findById(id)));

      const driverMap = new Map(
        drivers.filter((driver): driver is Driver => driver !== null).map(driver => [driver.id, driver]),
      );

      const enrichedJoinRequests: TeamJoinRequestWithDriver[] = joinRequests
        .filter(request => driverMap.has(request.driverId))
        .map(request => ({
          ...request,
          driver: driverMap.get(request.driverId)!,
        }));

      const result: GetTeamJoinRequestsResult = {
        team,
        joinRequests: enrichedJoinRequests,
      };

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

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