import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository'; import type { ILeagueWalletRepository } from '../../domain/repositories/ILeagueWalletRepository'; import type { ITransactionRepository } from '../../domain/repositories/ITransactionRepository'; import type { Transaction } from '../../domain/entities/league-wallet/Transaction'; import type { LeagueWallet } from '../../domain/entities/league-wallet/LeagueWallet'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import { Money } from '../../domain/value-objects/Money'; export type GetLeagueWalletErrorCode = | 'LEAGUE_NOT_FOUND' | 'WALLET_NOT_FOUND' | 'REPOSITORY_ERROR'; export interface GetLeagueWalletInput { leagueId: string; } export interface GetLeagueWalletAggregates { balance: Money; totalRevenue: Money; totalFees: Money; totalWithdrawals: Money; pendingPayouts: Money; } export interface GetLeagueWalletResult { wallet: LeagueWallet; transactions: Transaction[]; aggregates: GetLeagueWalletAggregates; } /** * Use Case for retrieving league wallet information. */ export class GetLeagueWalletUseCase { constructor( private readonly leagueRepository: ILeagueRepository, private readonly leagueWalletRepository: ILeagueWalletRepository, private readonly transactionRepository: ITransactionRepository, ) {} async execute( input: GetLeagueWalletInput, ): Promise< Result> > { try { const leagueExists = await this.leagueRepository.exists(input.leagueId); if (!leagueExists) { return Result.err({ code: 'LEAGUE_NOT_FOUND', details: { message: 'League not found' }, }); } const wallet = await this.leagueWalletRepository.findByLeagueId(input.leagueId); if (!wallet) { return Result.err({ code: 'WALLET_NOT_FOUND', details: { message: 'League wallet not found' }, }); } const transactions = await this.transactionRepository.findByWalletId( wallet.id.toString(), ); const { aggregates } = this.computeAggregates(wallet.balance, transactions); const result: GetLeagueWalletResult = { wallet, transactions: transactions .slice() .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()), aggregates, }; return Result.ok(result); } catch (error) { return Result.err({ code: 'REPOSITORY_ERROR', details: { message: error instanceof Error ? error.message : 'Failed to fetch league wallet', }, }); } } private computeAggregates( balance: Money, transactions: Transaction[], ): { aggregates: GetLeagueWalletAggregates } { let totalRevenue = Money.create(0, balance.currency); let totalFees = Money.create(0, balance.currency); let totalWithdrawals = Money.create(0, balance.currency); let pendingPayouts = Money.create(0, balance.currency); for (const transaction of transactions) { if ( transaction.type === 'sponsorship_payment' || transaction.type === 'membership_payment' || transaction.type === 'prize_payout' ) { totalRevenue = totalRevenue.add(transaction.amount); totalFees = totalFees.add(transaction.platformFee); } if (transaction.type === 'withdrawal' && transaction.status === 'completed') { totalWithdrawals = totalWithdrawals.add(transaction.netAmount); } if (transaction.type === 'prize_payout' && transaction.status === 'pending') { pendingPayouts = pendingPayouts.add(transaction.netAmount); } } return { aggregates: { balance, totalRevenue, totalFees, totalWithdrawals, pendingPayouts, }, }; } }