import type { DataSource } from 'typeorm';

import { League } from '@core/racing/domain/entities/League';
import type { LeagueRepository } from '@core/racing/domain/repositories/LeagueRepository';

import { LeagueOrmEntity } from '../entities/LeagueOrmEntity';
import { LeagueOrmMapper } from '../mappers/LeagueOrmMapper';

export class TypeOrmLeagueRepository implements LeagueRepository {
  constructor(
    private readonly dataSource: DataSource,
    private readonly mapper: LeagueOrmMapper,
  ) {}

  async findById(id: string): Promise<League | null> {
    const repo = this.dataSource.getRepository(LeagueOrmEntity);
    const entity = await repo.findOne({ where: { id } });
    return entity ? this.mapper.toDomain(entity) : null;
  }

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

  async countAll(): Promise<number> {
    const repo = this.dataSource.getRepository(LeagueOrmEntity);
    return repo.count();
  }

  async findByOwnerId(ownerId: string): Promise<League[]> {
    const repo = this.dataSource.getRepository(LeagueOrmEntity);
    const entities = await repo.find({ where: { ownerId } });
    return entities.map((e) => this.mapper.toDomain(e));
  }

  async create(league: League): Promise<League> {
    const repo = this.dataSource.getRepository(LeagueOrmEntity);
    const entity = this.mapper.toOrmEntity(league);
    await repo.save(entity);
    return league;
  }

  async update(league: League): Promise<League> {
    const repo = this.dataSource.getRepository(LeagueOrmEntity);
    const entity = this.mapper.toOrmEntity(league);
    await repo.save(entity);
    return league;
  }

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

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

  async searchByName(query: string): Promise<League[]> {
    const repo = this.dataSource.getRepository(LeagueOrmEntity);
    const entities = await repo
      .createQueryBuilder('league')
      .where('league.name ILIKE :q', { q: `%${query}%` })
      .getMany();

    return entities.map((e) => this.mapper.toDomain(e));
  }
}