import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import {
  WithdrawalEventConsumerService,
  WithdrawalRequestedPayload,
} from '@/infrastructure/kafka/withdrawal-event-consumer.service';
import { EventPublisherService } from '@/infrastructure/kafka/event-publisher.service';
import { Erc20TransferService } from '@/domain/services/erc20-transfer.service';
import { ChainTypeEnum } from '@/domain/enums';

/**
 * Withdrawal Requested Event Handler
 *
 * Handles withdrawal requests from wallet-service.
 * Executes ERC20 USDT transfers on the specified chain (KAVA/BSC).
 */
@Injectable()
export class WithdrawalRequestedHandler implements OnModuleInit {
  private readonly logger = new Logger(WithdrawalRequestedHandler.name);

  constructor(
    private readonly withdrawalEventConsumer: WithdrawalEventConsumerService,
    private readonly eventPublisher: EventPublisherService,
    private readonly transferService: Erc20TransferService,
  ) {}

  onModuleInit() {
    this.withdrawalEventConsumer.onWithdrawalRequested(
      this.handleWithdrawalRequested.bind(this),
    );
    this.logger.log(`[INIT] WithdrawalRequestedHandler registered`);
  }

  /**
   * Handle withdrawal requested event from wallet-service
   *
   * Flow:
   * 1. Receive withdrawal request
   * 2. Publish "PROCESSING" status
   * 3. Execute ERC20 transfer
   * 4. Publish final status (CONFIRMED or FAILED)
   */
  private async handleWithdrawalRequested(
    payload: WithdrawalRequestedPayload,
  ): Promise<void> {
    this.logger.log(`[HANDLE] ========== Withdrawal Request ==========`);
    this.logger.log(`[HANDLE] orderNo: ${payload.orderNo}`);
    this.logger.log(`[HANDLE] accountSequence: ${payload.accountSequence}`);
    this.logger.log(`[HANDLE] userId: ${payload.userId}`);
    this.logger.log(`[HANDLE] chainType: ${payload.chainType}`);
    this.logger.log(`[HANDLE] toAddress: ${payload.toAddress}`);
    this.logger.log(`[HANDLE] amount: ${payload.amount}`);
    this.logger.log(`[HANDLE] fee: ${payload.fee}`);
    this.logger.log(`[HANDLE] netAmount: ${payload.netAmount}`);

    try {
      // Step 1: 验证链类型
      const chainType = this.parseChainType(payload.chainType);
      if (!chainType) {
        throw new Error(`Unsupported chain type: ${payload.chainType}`);
      }

      // Step 2: 检查转账服务是否配置
      if (!this.transferService.isConfigured(chainType)) {
        throw new Error(`Hot wallet not configured for chain: ${chainType}`);
      }

      // Step 3: 发布处理中状态
      this.logger.log(`[PROCESS] Starting withdrawal ${payload.orderNo}`);
      await this.publishStatus(payload, 'PROCESSING', 'Withdrawal is being processed');

      // Step 4: 执行 ERC20 转账
      this.logger.log(`[PROCESS] Executing ERC20 transfer...`);
      const result = await this.transferService.transferUsdt(
        chainType,
        payload.toAddress,
        payload.netAmount.toString(),
      );

      if (result.success && result.txHash) {
        // Step 5a: 转账成功，发布确认状态
        this.logger.log(`[SUCCESS] Withdrawal ${payload.orderNo} confirmed!`);
        this.logger.log(`[SUCCESS] TxHash: ${result.txHash}`);
        this.logger.log(`[SUCCESS] Block: ${result.blockNumber}`);

        await this.eventPublisher.publish({
          eventType: 'mining_blockchain.withdrawal.confirmed',
          toPayload: () => ({
            orderNo: payload.orderNo,
            accountSequence: payload.accountSequence,
            userId: payload.userId,
            status: 'CONFIRMED',
            txHash: result.txHash,
            blockNumber: result.blockNumber,
            chainType: payload.chainType,
            toAddress: payload.toAddress,
            netAmount: payload.netAmount,
          }),
          eventId: `wd-confirmed-${payload.orderNo}-${Date.now()}`,
          occurredAt: new Date(),
        });

        this.logger.log(`[COMPLETE] Withdrawal ${payload.orderNo} completed successfully`);
      } else {
        // Step 5b: 转账失败
        throw new Error(result.error || 'Transfer failed');
      }

    } catch (error) {
      this.logger.error(
        `[ERROR] Failed to process withdrawal ${payload.orderNo}`,
        error,
      );

      // 发布失败事件
      await this.eventPublisher.publish({
        eventType: 'mining_blockchain.withdrawal.failed',
        toPayload: () => ({
          orderNo: payload.orderNo,
          accountSequence: payload.accountSequence,
          userId: payload.userId,
          status: 'FAILED',
          error: error instanceof Error ? error.message : 'Unknown error',
          chainType: payload.chainType,
          toAddress: payload.toAddress,
          netAmount: payload.netAmount,
        }),
        eventId: `wd-failed-${payload.orderNo}-${Date.now()}`,
        occurredAt: new Date(),
      });

      throw error;
    }
  }

  /**
   * 发布状态更新
   */
  private async publishStatus(
    payload: WithdrawalRequestedPayload,
    status: string,
    message: string,
  ): Promise<void> {
    await this.eventPublisher.publish({
      eventType: 'mining_blockchain.withdrawal.status',
      toPayload: () => ({
        orderNo: payload.orderNo,
        accountSequence: payload.accountSequence,
        status,
        message,
      }),
      eventId: `wd-status-${payload.orderNo}-${status}-${Date.now()}`,
      occurredAt: new Date(),
    });
  }

  /**
   * 解析链类型字符串
   */
  private parseChainType(chainType: string): ChainTypeEnum | null {
    const normalized = chainType.toUpperCase();
    if (normalized === 'KAVA') return ChainTypeEnum.KAVA;
    if (normalized === 'BSC') return ChainTypeEnum.BSC;
    return null;
  }
}
