import { NotFoundError } from '../../../domain/errors/not-found-error';
import { INetworkRepository } from '../../../domain/repositories/network-repository';
import { INetworkRpcClient } from '../../ports/network-rpc-client';

const DEFAULT_GAS_PRICE = '20000000000'; // 20 gwei
const SWAP_GAS_LIMIT = 200000;

export interface NetworkGasInfoOutput {
  readonly networkId: string;
  readonly blockNumber: number;
  readonly gasPrice: string;
  readonly gasLimit: number;
  readonly fee: string;
}

export class GetNetworkGasInfoUseCase {
  constructor(
    private readonly networkRepository: INetworkRepository,
    private readonly rpcClient: INetworkRpcClient,
  ) {}

  async execute(networkId: string): Promise<NetworkGasInfoOutput> {
    const network = await this.networkRepository.findById(networkId);
    if (!network) {
      throw new NotFoundError('Network', networkId);
    }

    const estimate = network.chainId
      ? await this.rpcClient.getGasEstimate(network.chainId)
      : null;

    const blockNumber = estimate?.blockNumber
      ? estimate.blockNumber
      : this.fallbackBlockNumber();
    const gasPrice = estimate?.gasPrice ?? DEFAULT_GAS_PRICE;
    const gasLimit = estimate?.gasLimit ?? SWAP_GAS_LIMIT;
    const fee = (BigInt(gasPrice) * BigInt(gasLimit)).toString();

    return {
      networkId: network.id,
      blockNumber,
      gasPrice,
      gasLimit,
      fee,
    };
  }

  private fallbackBlockNumber(): number {
    return Math.floor(Date.now() / 1000);
  }
}
