import { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository';
import { RaceRegistration } from '@core/racing/domain/entities/RaceRegistration';
import { Logger } from '@core/shared/application';

export class InMemoryRaceRegistrationRepository implements IRaceRegistrationRepository {
  private registrations: Map<string, RaceRegistration> = new Map(); // Key: `${raceId}:${driverId}`

  constructor(private readonly logger: Logger) {
    this.logger.info('InMemoryRaceRegistrationRepository initialized.');
  }

  async isRegistered(raceId: string, driverId: string): Promise<boolean> {
    this.logger.debug(`[InMemoryRaceRegistrationRepository] Checking if driver ${driverId} is registered for race ${raceId}.`);
    const key = `${raceId}:${driverId}`;
    return Promise.resolve(this.registrations.has(key));
  }

  async getRegisteredDrivers(raceId: string): Promise<string[]> {
    this.logger.debug(`[InMemoryRaceRegistrationRepository] Getting registered drivers for race ${raceId}.`);
    const driverIds: string[] = [];
    for (const registration of this.registrations.values()) {
      if (registration.raceId.toString() === raceId) {
        driverIds.push(registration.driverId.toString());
      }
    }
    this.logger.info(`Found ${driverIds.length} registered drivers for race ${raceId}.`);
    return Promise.resolve(driverIds);
  }

  async getRegistrationCount(raceId: string): Promise<number> {
    this.logger.debug(`[InMemoryRaceRegistrationRepository] Getting registration count for race ${raceId}.`);
    const count = Array.from(this.registrations.values()).filter(reg => reg.raceId.toString() === raceId).length;
    this.logger.info(`Registration count for race ${raceId}: ${count}.`);
    return Promise.resolve(count);
  }

  async register(registration: RaceRegistration): Promise<void> {
    this.logger.debug(`[InMemoryRaceRegistrationRepository] Registering driver ${registration.driverId.toString()} for race ${registration.raceId.toString()}.`);
    if (await this.isRegistered(registration.raceId.toString(), registration.driverId.toString())) {
      this.logger.warn(`Driver ${registration.driverId.toString()} already registered for race ${registration.raceId.toString()}.`);
      throw new Error('Driver already registered for this race');
    }
    this.registrations.set(registration.id, registration);
    this.logger.info(`Driver ${registration.driverId.toString()} registered for race ${registration.raceId.toString()}.`);
    return Promise.resolve();
  }

  async withdraw(raceId: string, driverId: string): Promise<void> {
    this.logger.debug(`[InMemoryRaceRegistrationRepository] Withdrawing driver ${driverId} from race ${raceId}.`);
    const key = `${raceId}:${driverId}`;
    if (!this.registrations.has(key)) {
      this.logger.warn(`Driver ${driverId} not registered for race ${raceId}. No withdrawal needed.`);
      throw new Error('Driver not registered for this race');
    }
    this.registrations.delete(key);
    this.logger.info(`Driver ${driverId} withdrawn from race ${raceId}.`);
    return Promise.resolve();
  }

  async getDriverRegistrations(driverId: string): Promise<string[]> {
    this.logger.debug(`[InMemoryRaceRegistrationRepository] Getting registrations for driver: ${driverId}.`);
    const raceIds: string[] = [];
    for (const registration of this.registrations.values()) {
      if (registration.driverId.toString() === driverId) {
        raceIds.push(registration.raceId.toString());
      }
    }
    this.logger.info(`Found ${raceIds.length} registrations for driver ${driverId}.`);
    return Promise.resolve(raceIds);
  }

  async clearRaceRegistrations(raceId: string): Promise<void> {
    this.logger.debug(`[InMemoryRaceRegistrationRepository] Clearing all registrations for race: ${raceId}.`);
    const registrationsToDelete: string[] = [];
    for (const registration of this.registrations.values()) {
      if (registration.raceId.toString() === raceId) {
        registrationsToDelete.push(registration.id);
      }
    }
    for (const id of registrationsToDelete) {
      this.registrations.delete(id);
    }
    this.logger.info(`Cleared ${registrationsToDelete.length} registrations for race ${raceId}.`);
    return Promise.resolve();
  }
}
