import { NotFoundError } from '../../../domain/errors/not-found-error';
import { WalletBalanceService } from '../../../domain/services/wallet-balance.service';
import { IWalletRepository } from '../../../domain/repositories/wallet-repository';
import { IAddressRepository } from '../../../domain/repositories/address-repository';
import { ITokenRepository } from '../../../domain/repositories/token-repository';
import { ITransactionRepository } from '../../../domain/repositories/transaction-repository';
import { TokenBalanceOutput } from '../../dto/balance.dto';

const TOKEN_PAGE_LIMIT = 1000;

export class GetAllWalletBalancesUseCase {
  constructor(
    private readonly walletRepository: IWalletRepository,
    private readonly addressRepository: IAddressRepository,
    private readonly tokenRepository: ITokenRepository,
    private readonly transactionRepository: ITransactionRepository,
    private readonly balanceService: WalletBalanceService,
  ) {}

  async execute(walletId: string): Promise<TokenBalanceOutput[]> {
    const wallet = await this.walletRepository.findById(walletId);
    if (!wallet) {
      throw new NotFoundError('Wallet', walletId);
    }

    const addresses = await this.addressRepository.findByWalletId(walletId);
    const addressIds = addresses.map((address) => address.id);
    
    if (addressIds.length === 0) {
      return [];
    }

    const transactions = await this.transactionRepository.findByAddressIds(addressIds);
    const tokens = await this.tokenRepository.findAll({ limit: TOKEN_PAGE_LIMIT });

    return this.balanceService.calculate(addresses, transactions, tokens);
  }
}
