import type { DataSource } from 'typeorm';

import type { IPaymentRepository } from '@core/payments/domain/repositories/IPaymentRepository';
import type { Payment, PaymentType } from '@core/payments/domain/entities/Payment';

import { PaymentsPaymentOrmEntity } from '../entities/PaymentsPaymentOrmEntity';
import { PaymentsPaymentOrmMapper } from '../mappers/PaymentsPaymentOrmMapper';

export class TypeOrmPaymentRepository implements IPaymentRepository {
  constructor(
    private readonly dataSource: DataSource,
    private readonly mapper: PaymentsPaymentOrmMapper,
  ) {}

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

  async findByLeagueId(leagueId: string): Promise<Payment[]> {
    const repo = this.dataSource.getRepository(PaymentsPaymentOrmEntity);
    const entities = await repo.find({ where: { leagueId } });
    return entities.map((e) => this.mapper.toDomain(e));
  }

  async findByPayerId(payerId: string): Promise<Payment[]> {
    const repo = this.dataSource.getRepository(PaymentsPaymentOrmEntity);
    const entities = await repo.find({ where: { payerId } });
    return entities.map((e) => this.mapper.toDomain(e));
  }

  async findByType(type: PaymentType): Promise<Payment[]> {
    const repo = this.dataSource.getRepository(PaymentsPaymentOrmEntity);
    const entities = await repo.find({ where: { type } });
    return entities.map((e) => this.mapper.toDomain(e));
  }

  async findByFilters(filters: { leagueId?: string; payerId?: string; type?: PaymentType }): Promise<Payment[]> {
    const repo = this.dataSource.getRepository(PaymentsPaymentOrmEntity);

    const where: {
      leagueId?: string;
      payerId?: string;
      type?: PaymentType;
    } = {};

    if (filters.leagueId !== undefined) where.leagueId = filters.leagueId;
    if (filters.payerId !== undefined) where.payerId = filters.payerId;
    if (filters.type !== undefined) where.type = filters.type;

    const entities = await repo.find({ where });
    return entities.map((e) => this.mapper.toDomain(e));
  }

  async create(payment: Payment): Promise<Payment> {
    const repo = this.dataSource.getRepository(PaymentsPaymentOrmEntity);
    await repo.save(this.mapper.toOrmEntity(payment));
    return payment;
  }

  async update(payment: Payment): Promise<Payment> {
    const repo = this.dataSource.getRepository(PaymentsPaymentOrmEntity);
    await repo.save(this.mapper.toOrmEntity(payment));
    return payment;
  }
}
