import type { DataSource } from 'typeorm';

import type { RaceRegistration } from '@core/racing/domain/entities/RaceRegistration';
import type { RaceRegistrationRepository } from '@core/racing/domain/repositories/RaceRegistrationRepository';

import { RaceRegistrationOrmEntity } from '../entities/RaceRegistrationOrmEntity';
import { RaceRegistrationOrmMapper } from '../mappers/RaceRegistrationOrmMapper';

export class TypeOrmRaceRegistrationRepository implements RaceRegistrationRepository {
  constructor(
    private readonly dataSource: DataSource,
    private readonly mapper: RaceRegistrationOrmMapper,
  ) {}

  async isRegistered(raceId: string, driverId: string): Promise<boolean> {
    const repo = this.dataSource.getRepository(RaceRegistrationOrmEntity);
    const count = await repo.count({ where: { raceId, driverId } });
    return count > 0;
  }

  async getRegisteredDrivers(raceId: string): Promise<string[]> {
    const repo = this.dataSource.getRepository(RaceRegistrationOrmEntity);
    const entities = await repo.find({ where: { raceId } });
    return entities.map((e) => e.driverId);
  }

  async findByRaceId(raceId: string): Promise<RaceRegistration[]> {
    const repo = this.dataSource.getRepository(RaceRegistrationOrmEntity);
    const entities = await repo.find({ where: { raceId } });
    return entities.map((e) => this.mapper.toDomain(e));
  }

  async getRegistrationCount(raceId: string): Promise<number> {
    const repo = this.dataSource.getRepository(RaceRegistrationOrmEntity);
    return repo.count({ where: { raceId } });
  }

  async register(registration: RaceRegistration): Promise<void> {
    const repo = this.dataSource.getRepository(RaceRegistrationOrmEntity);
    await repo.save(this.mapper.toOrmEntity(registration));
  }

  async withdraw(raceId: string, driverId: string): Promise<void> {
    const repo = this.dataSource.getRepository(RaceRegistrationOrmEntity);
    await repo.delete({ raceId, driverId });
  }

  async getDriverRegistrations(driverId: string): Promise<string[]> {
    const repo = this.dataSource.getRepository(RaceRegistrationOrmEntity);
    const entities = await repo.find({ where: { driverId } });
    return entities.map((e) => e.raceId);
  }

  async clearRaceRegistrations(raceId: string): Promise<void> {
    const repo = this.dataSource.getRepository(RaceRegistrationOrmEntity);
    await repo.delete({ raceId });
  }
}