import { v4 as uuidv4 } from 'uuid';
import { Address } from '../../../domain/entities/address';
import { NotFoundError } from '../../../domain/errors/not-found-error';
import { IWalletRepository } from '../../../domain/repositories/wallet-repository';
import { INetworkRepository } from '../../../domain/repositories/network-repository';
import { IAddressRepository } from '../../../domain/repositories/address-repository';
import { IAddressGenerator } from '../../ports/address-generator';

export class GetWalletAddressForNetworkUseCase {
  constructor(
    private readonly walletRepository: IWalletRepository,
    private readonly networkRepository: INetworkRepository,
    private readonly addressRepository: IAddressRepository,
    private readonly addressGenerator: IAddressGenerator,
  ) {}

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

    const network = await this.networkRepository.findById(networkId);
    if (!network) {
      throw new NotFoundError('Network', networkId);
    }

    const existing = await this.addressRepository.findByWalletIdAndType(
      walletId,
      network.addressType,
    );
    if (existing.length > 0) {
      return existing[0];
    }

    const generated = this.addressGenerator.generate(network, wallet);
    const address = Address.create(
      uuidv4(),
      generated.address,
      generated.type,
      walletId,
      false,
    );
    return this.addressRepository.save(address);
  }
}
