import { Injectable, Logger, Inject, forwardRef } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {
  JsonRpcProvider,
  Contract,
  parseUnits,
  formatUnits,
  Transaction,
  Signature,
  recoverAddress,
} from 'ethers';
import { ChainConfigService } from './chain-config.service';
import { RpcProviderManager } from './rpc-provider-manager.service';
import { ChainType } from '@/domain/value-objects';
import { ChainTypeEnum } from '@/domain/enums';

// ERC20 ABI for transfer
const ERC20_TRANSFER_ABI = [
  'function transfer(address to, uint256 amount) returns (bool)',
  'function balanceOf(address owner) view returns (uint256)',
  'function decimals() view returns (uint8)',
  'function symbol() view returns (string)',
];

export interface TransferResult {
  success: boolean;
  txHash?: string;
  error?: string;
  gasUsed?: string;
  blockNumber?: number;
}

// MPC 签名客户端接口（避免循环依赖）
export interface IMpcSigningClient {
  isConfigured(): boolean;
  getHotWalletAddress(): string;
  signMessage(messageHash: string): Promise<string>;
}

export const MPC_SIGNING_CLIENT = Symbol('MPC_SIGNING_CLIENT');

/**
 * ERC20 转账服务
 *
 * 用于从系统热钱包发送 ERC20 代币到用户指定地址
 * 使用 MPC 签名替代私钥签名，提高安全性
 */
@Injectable()
export class Erc20TransferService {
  private readonly logger = new Logger(Erc20TransferService.name);
  private readonly hotWalletAddress: string;
  private mpcSigningClient: IMpcSigningClient | null = null;

  constructor(
    private readonly configService: ConfigService,
    private readonly chainConfig: ChainConfigService,
    private readonly rpcProviderManager: RpcProviderManager,
  ) {
    this.hotWalletAddress = this.configService.get<string>('HOT_WALLET_ADDRESS', '');
    this.initializeWalletConfig();
  }

  /**
   * 设置 MPC 签名客户端（用于延迟注入，避免循环依赖）
   */
  setMpcSigningClient(client: IMpcSigningClient): void {
    this.mpcSigningClient = client;
    this.logger.log(`[INIT] MPC Signing Client injected`);
  }

  /**
   * 获取某条链当前活跃的 provider（由 RpcProviderManager 统一管理，支持故障转移）
   */
  private getProvider(chainType: ChainTypeEnum): JsonRpcProvider {
    return this.rpcProviderManager.getProvider(chainType);
  }

  /**
   * 判断错误是否为 RPC 连接类错误（需要触发故障转移）
   * 区分 RPC 网络错误（503、超时等）和合约执行错误（revert、余额不足等）
   */
  private isRpcConnectionError(error: any): boolean {
    const message = (error?.message || '').toLowerCase();
    return (
      message.includes('could not detect network') ||
      message.includes('connection refused') ||
      message.includes('timeout') ||
      message.includes('econnrefused') ||
      message.includes('enotfound') ||
      message.includes('503') ||
      message.includes('502') ||
      message.includes('server error') ||
      message.includes('missing response') ||
      message.includes('request failed') ||
      error?.code === 'NETWORK_ERROR' ||
      error?.code === 'SERVER_ERROR' ||
      error?.code === 'TIMEOUT'
    );
  }

  /**
   * 初始化钱包配置检查（provider 由 RpcProviderManager 统一管理）
   */
  private initializeWalletConfig(): void {
    // 检查热钱包地址配置
    if (this.hotWalletAddress) {
      this.logger.log(`[INIT] Hot wallet address configured: ${this.hotWalletAddress}`);
    } else {
      this.logger.warn('[INIT] HOT_WALLET_ADDRESS not configured, transfers will fail');
    }
  }

  /**
   * 获取热钱包地址
   */
  getHotWalletAddress(chainType: ChainTypeEnum): string | null {
    // MPC 钱包地址在所有 EVM 链上相同
    return this.hotWalletAddress || null;
  }

  /**
   * 获取热钱包 USDT 余额
   */
  async getHotWalletBalance(chainType: ChainTypeEnum): Promise<string> {
    const provider = this.getProvider(chainType);

    if (!this.hotWalletAddress) {
      throw new Error('Hot wallet address not configured');
    }

    const config = this.chainConfig.getConfig(ChainType.fromEnum(chainType));
    const contract = new Contract(config.usdtContract, ERC20_TRANSFER_ABI, provider);

    const balance = await contract.balanceOf(this.hotWalletAddress);
    const decimals = await contract.decimals();

    return formatUnits(balance, decimals);
  }

  /**
   * 执行 ERC20 转账（使用 MPC 签名）
   *
   * @param chainType 链类型 (KAVA, BSC)
   * @param toAddress 接收地址
   * @param amount 转账金额 (人类可读格式，如 "100.5")
   * @returns 转账结果
   */
  async transferUsdt(
    chainType: ChainTypeEnum,
    toAddress: string,
    amount: string,
  ): Promise<TransferResult> {
    this.logger.log(`[TRANSFER] Starting USDT transfer with MPC signing`);
    this.logger.log(`[TRANSFER] Chain: ${chainType}`);
    this.logger.log(`[TRANSFER] To: ${toAddress}`);
    this.logger.log(`[TRANSFER] Amount: ${amount} USDT`);

    const provider = this.getProvider(chainType);

    if (!this.mpcSigningClient || !this.mpcSigningClient.isConfigured()) {
      const error = 'MPC signing client not configured';
      this.logger.error(`[TRANSFER] ${error}`);
      return { success: false, error };
    }

    if (!this.hotWalletAddress) {
      const error = 'Hot wallet address not configured';
      this.logger.error(`[TRANSFER] ${error}`);
      return { success: false, error };
    }

    try {
      const config = this.chainConfig.getConfig(ChainType.fromEnum(chainType));
      const contract = new Contract(config.usdtContract, ERC20_TRANSFER_ABI, provider);

      // 获取代币精度
      const decimals = await contract.decimals();
      this.logger.log(`[TRANSFER] Token decimals: ${decimals}`);

      // 转换金额
      const amountInWei = parseUnits(amount, decimals);
      this.logger.log(`[TRANSFER] Amount in wei: ${amountInWei.toString()}`);

      // 检查余额
      const balance = await contract.balanceOf(this.hotWalletAddress);
      this.logger.log(`[TRANSFER] Hot wallet balance: ${formatUnits(balance, decimals)} USDT`);

      if (balance < amountInWei) {
        const error = 'Insufficient USDT balance in hot wallet';
        this.logger.error(`[TRANSFER] ${error}`);
        return { success: false, error };
      }

      // 构建交易
      this.logger.log(`[TRANSFER] Building transaction...`);
      const nonce = await provider.getTransactionCount(this.hotWalletAddress);
      const feeData = await provider.getFeeData();

      // ERC20 transfer 的 calldata
      const transferData = contract.interface.encodeFunctionData('transfer', [toAddress, amountInWei]);

      // 估算 gas
      const gasEstimate = await provider.estimateGas({
        from: this.hotWalletAddress,
        to: config.usdtContract,
        data: transferData,
      });

      const gasLimit = gasEstimate * BigInt(120) / BigInt(100); // 增加 20% buffer

      // 检测链是否支持 EIP-1559
      // 如果 maxFeePerGas 为 null 或 0，则使用 legacy 交易
      const supportsEip1559 = feeData.maxFeePerGas && feeData.maxFeePerGas > BigInt(0);
      this.logger.log(`[TRANSFER] Chain supports EIP-1559: ${supportsEip1559}`);
      this.logger.log(`[TRANSFER] Fee data: gasPrice=${feeData.gasPrice}, maxFeePerGas=${feeData.maxFeePerGas}`);

      let tx: Transaction;
      if (supportsEip1559) {
        // EIP-1559 交易 (type 2)
        tx = Transaction.from({
          type: 2,
          chainId: config.chainId,
          nonce,
          to: config.usdtContract,
          data: transferData,
          gasLimit,
          maxFeePerGas: feeData.maxFeePerGas,
          maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,
        });
        this.logger.log(`[TRANSFER] Built EIP-1559 transaction`);
      } else {
        // Legacy 交易 (type 0)
        const gasPrice = feeData.gasPrice || BigInt(1000000000); // 默认 1 gwei
        tx = Transaction.from({
          type: 0,
          chainId: config.chainId,
          nonce,
          to: config.usdtContract,
          data: transferData,
          gasLimit,
          gasPrice,
        });
        this.logger.log(`[TRANSFER] Built legacy transaction with gasPrice=${gasPrice}`);
      }

      this.logger.log(`[TRANSFER] Transaction built: nonce=${nonce}, gasLimit=${tx.gasLimit}`);

      // 获取交易哈希用于签名
      const unsignedTxHash = tx.unsignedHash;
      this.logger.log(`[TRANSFER] Unsigned tx hash: ${unsignedTxHash}`);

      // 使用 MPC 签名
      this.logger.log(`[TRANSFER] Requesting MPC signature...`);
      const signatureHex = await this.mpcSigningClient.signMessage(unsignedTxHash);
      this.logger.log(`[TRANSFER] MPC signature obtained: ${signatureHex.slice(0, 20)}...`);

      // 解析签名 - MPC 返回 64 字节 (r+s)，需要转换为 ethers.js 格式
      // 确保有 0x 前缀
      const normalizedSig = signatureHex.startsWith('0x') ? signatureHex : `0x${signatureHex}`;
      this.logger.log(`[TRANSFER] Normalized signature: ${normalizedSig.slice(0, 22)}...`);

      // MPC 签名是 64 字节 (r: 32 bytes + s: 32 bytes)，需要添加 v (recovery id)
      // 对于 EIP-1559 交易，v = 0 或 1 (yParity)
      // 我们需要尝试两个值来恢复正确的地址
      const sigBytes = normalizedSig.slice(2); // 去掉 0x
      const r = `0x${sigBytes.slice(0, 64)}`;
      const s = `0x${sigBytes.slice(64, 128)}`;

      this.logger.log(`[TRANSFER] Signature r: ${r.slice(0, 20)}...`);
      this.logger.log(`[TRANSFER] Signature s: ${s.slice(0, 20)}...`);

      // 尝试 yParity 0 和 1 来找到正确的 recovery id
      let signature: Signature | null = null;
      for (const yParity of [0, 1] as const) {
        try {
          const testSig = Signature.from({ r, s, yParity });
          // 使用 recoverAddress 验证签名
          const recoveredAddress = recoverAddress(unsignedTxHash, testSig);
          this.logger.log(`[TRANSFER] Recovered address with yParity=${yParity}: ${recoveredAddress}`);

          if (recoveredAddress.toLowerCase() === this.hotWalletAddress.toLowerCase()) {
            this.logger.log(`[TRANSFER] Found correct yParity: ${yParity}`);
            signature = testSig;
            break;
          }
        } catch (e) {
          this.logger.debug(`[TRANSFER] yParity=${yParity} failed: ${e}`);
        }
      }

      if (!signature) {
        throw new Error('Failed to recover correct signature - address mismatch');
      }

      // 创建已签名交易
      const signedTx = tx.clone();
      signedTx.signature = signature;

      // 广播交易
      this.logger.log(`[TRANSFER] Broadcasting transaction...`);
      const txResponse = await provider.broadcastTransaction(signedTx.serialized);
      this.logger.log(`[TRANSFER] Transaction sent: ${txResponse.hash}`);

      // 等待确认
      this.logger.log(`[TRANSFER] Waiting for confirmation...`);
      const receipt = await txResponse.wait();

      if (receipt && receipt.status === 1) {
        this.logger.log(`[TRANSFER] Transaction confirmed!`);
        this.logger.log(`[TRANSFER] Block: ${receipt.blockNumber}`);
        this.logger.log(`[TRANSFER] Gas used: ${receipt.gasUsed.toString()}`);

        this.rpcProviderManager.reportSuccess(chainType);
        return {
          success: true,
          txHash: txResponse.hash,
          gasUsed: receipt.gasUsed.toString(),
          blockNumber: receipt.blockNumber,
        };
      } else {
        const error = 'Transaction failed (reverted)';
        this.logger.error(`[TRANSFER] ${error}`);
        return { success: false, txHash: txResponse.hash, error };
      }
    } catch (error: any) {
      if (this.isRpcConnectionError(error)) {
        this.rpcProviderManager.reportFailure(chainType, error);
      }
      this.logger.error(`[TRANSFER] Transfer failed:`, error);
      return {
        success: false,
        error: error.message || 'Unknown error during transfer',
      };
    }
  }

  /**
   * 检查热钱包是否已配置
   */
  isConfigured(chainType: ChainTypeEnum): boolean {
    try {
      this.rpcProviderManager.getProvider(chainType);
      return !!this.hotWalletAddress && !!this.mpcSigningClient?.isConfigured();
    } catch {
      return false;
    }
  }
}
