import type { DataSource } from 'typeorm';

import type { Transaction, Wallet } from '@core/payments/domain/entities/Wallet';
import type { WalletRepository, TransactionRepository } from '@core/payments/domain/repositories/WalletRepository';

import { PaymentsTransactionOrmEntity } from '../entities/PaymentsTransactionOrmEntity';
import { PaymentsWalletOrmEntity } from '../entities/PaymentsWalletOrmEntity';
import { PaymentsWalletOrmMapper } from '../mappers/PaymentsWalletOrmMapper';

export class TypeOrmWalletRepository implements WalletRepository {
  constructor(
    private readonly dataSource: DataSource,
    private readonly mapper: PaymentsWalletOrmMapper,
  ) {}

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

  async findByLeagueId(leagueId: string): Promise<Wallet | null> {
    const repo = this.dataSource.getRepository(PaymentsWalletOrmEntity);
    const entity = await repo.findOne({ where: { leagueId } });
    return entity ? this.mapper.toDomain(entity) : null;
  }

  async create(wallet: Wallet): Promise<Wallet> {
    const repo = this.dataSource.getRepository(PaymentsWalletOrmEntity);
    await repo.save(this.mapper.toOrmEntity(wallet));
    return wallet;
  }

  async update(wallet: Wallet): Promise<Wallet> {
    const repo = this.dataSource.getRepository(PaymentsWalletOrmEntity);
    await repo.save(this.mapper.toOrmEntity(wallet));
    return wallet;
  }
}

export class TypeOrmTransactionRepository implements TransactionRepository {
  constructor(
    private readonly dataSource: DataSource,
    private readonly mapper: PaymentsWalletOrmMapper,
  ) {}

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

  async findByWalletId(walletId: string): Promise<Transaction[]> {
    const repo = this.dataSource.getRepository(PaymentsTransactionOrmEntity);
    const entities = await repo.find({ where: { walletId } });
    return entities.map((e) => this.mapper.toDomainTransaction(e));
  }

  async create(transaction: Transaction): Promise<Transaction> {
    const repo = this.dataSource.getRepository(PaymentsTransactionOrmEntity);
    await repo.save(this.mapper.toOrmTransaction(transaction));
    return transaction;
  }
}
