import type { DataSource } from 'typeorm';

import type { Driver } from '@core/racing/domain/entities/Driver';
import type { DriverRepository } from '@core/racing/domain/repositories/DriverRepository';

import { DriverOrmEntity } from '../entities/DriverOrmEntity';
import { DriverOrmMapper } from '../mappers/DriverOrmMapper';

export class TypeOrmDriverRepository implements DriverRepository {
  constructor(
    private readonly dataSource: DataSource,
    private readonly mapper: DriverOrmMapper,
  ) {}

  async findById(id: string): Promise<Driver | null> {
    // Validate UUID format to prevent database errors
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
    if (!uuidRegex.test(id)) {
      return null;
    }
    
    const repo = this.dataSource.getRepository(DriverOrmEntity);
    const entity = await repo.findOne({ where: { id } });
    return entity ? this.mapper.toDomain(entity) : null;
  }

  async findByIRacingId(iracingId: string): Promise<Driver | null> {
    const repo = this.dataSource.getRepository(DriverOrmEntity);
    const entity = await repo.findOne({ where: { iracingId } });
    return entity ? this.mapper.toDomain(entity) : null;
  }

  async findAll(): Promise<Driver[]> {
    const repo = this.dataSource.getRepository(DriverOrmEntity);
    const entities = await repo.find();
    return entities.map((e) => this.mapper.toDomain(e));
  }

  async create(driver: Driver): Promise<Driver> {
    const repo = this.dataSource.getRepository(DriverOrmEntity);
    await repo.save(this.mapper.toOrmEntity(driver));
    return driver;
  }

  async update(driver: Driver): Promise<Driver> {
    const repo = this.dataSource.getRepository(DriverOrmEntity);
    await repo.save(this.mapper.toOrmEntity(driver));
    return driver;
  }

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

  async exists(id: string): Promise<boolean> {
    const repo = this.dataSource.getRepository(DriverOrmEntity);
    const count = await repo.count({ where: { id } });
    return count > 0;
  }

  async existsByIRacingId(iracingId: string): Promise<boolean> {
    const repo = this.dataSource.getRepository(DriverOrmEntity);
    const count = await repo.count({ where: { iracingId } });
    return count > 0;
  }
}