import { Injectable, Logger } from '@nestjs/common';
import { EvmProviderAdapter } from '@/infrastructure/blockchain/evm-provider.adapter';
import { ChainConfigService } from '@/domain/services/chain-config.service';
import { ChainType } from '@/domain/value-objects';
import { ChainTypeEnum } from '@/domain/enums';

export interface BalanceResult {
  chainType: string;
  address: string;
  usdtBalance: string;
  usdtRawBalance: string;
  usdtDecimals: number;
  nativeBalance: string;
  nativeSymbol: string;
}

/**
 * 余额查询服务
 */
@Injectable()
export class BalanceQueryService {
  private readonly logger = new Logger(BalanceQueryService.name);

  constructor(
    private readonly evmProvider: EvmProviderAdapter,
    private readonly chainConfig: ChainConfigService,
  ) {}

  /**
   * 查询单个地址的余额
   */
  async getBalance(chainType: ChainType, address: string): Promise<BalanceResult> {
    const config = this.chainConfig.getConfig(chainType);

    const [usdtBalance, nativeBalance] = await Promise.all([
      this.evmProvider.getTokenBalance(chainType, config.usdtContract, address),
      this.evmProvider.getNativeBalance(chainType, address),
    ]);

    return {
      chainType: chainType.toString(),
      address,
      usdtBalance: usdtBalance.formatted,
      usdtRawBalance: usdtBalance.raw.toString(),
      usdtDecimals: usdtBalance.decimals,
      nativeBalance: nativeBalance.formatted,
      nativeSymbol: config.nativeSymbol,
    };
  }

  /**
   * 查询多条链的余额
   */
  async getBalances(address: string, chainTypes?: ChainTypeEnum[]): Promise<BalanceResult[]> {
    const chains = chainTypes || this.chainConfig.getSupportedChains();
    const results: BalanceResult[] = [];

    for (const chainTypeEnum of chains) {
      try {
        const chainType = ChainType.fromEnum(chainTypeEnum);
        const balance = await this.getBalance(chainType, address);
        results.push(balance);
      } catch (error) {
        this.logger.error(`Error querying balance for ${chainTypeEnum}:`, error);
      }
    }

    return results;
  }

  /**
   * 批量查询地址余额
   */
  async getBatchBalances(
    chainType: ChainType,
    addresses: string[],
  ): Promise<Map<string, BalanceResult>> {
    const results = new Map<string, BalanceResult>();

    await Promise.all(
      addresses.map(async (address) => {
        try {
          const balance = await this.getBalance(chainType, address);
          results.set(address.toLowerCase(), balance);
        } catch (error) {
          this.logger.error(`Error querying balance for ${address}:`, error);
        }
      }),
    );

    return results;
  }
}
