import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import {
  WithdrawalEventConsumerService,
  SystemWithdrawalConfirmedPayload,
  SystemWithdrawalFailedPayload,
} from '@/infrastructure/kafka/withdrawal-event-consumer.service';
import { SystemWithdrawalApplicationService } from '@/application/services';

/**
 * System Withdrawal Status Handler
 *
 * Handles system withdrawal status events from blockchain-service.
 * - On CONFIRMED: Updates order status and credits receiver's wallet
 * - On FAILED: Updates order status and refunds sender's wallet
 */
@Injectable()
export class SystemWithdrawalStatusHandler implements OnModuleInit {
  private readonly logger = new Logger(SystemWithdrawalStatusHandler.name);

  constructor(
    private readonly withdrawalEventConsumer: WithdrawalEventConsumerService,
    private readonly systemWithdrawalService: SystemWithdrawalApplicationService,
  ) {}

  onModuleInit() {
    this.withdrawalEventConsumer.onSystemWithdrawalConfirmed(
      this.handleSystemWithdrawalConfirmed.bind(this),
    );
    this.withdrawalEventConsumer.onSystemWithdrawalFailed(
      this.handleSystemWithdrawalFailed.bind(this),
    );
    this.logger.log(`[INIT] SystemWithdrawalStatusHandler registered`);
  }

  /**
   * Handle system withdrawal confirmed event
   * Update order status to CONFIRMED and credit receiver's wallet
   */
  private async handleSystemWithdrawalConfirmed(
    payload: SystemWithdrawalConfirmedPayload,
  ): Promise<void> {
    this.logger.log(`[CONFIRMED] Processing system withdrawal confirmation`);
    this.logger.log(`[CONFIRMED] orderNo: ${payload.orderNo}`);
    this.logger.log(`[CONFIRMED] txHash: ${payload.txHash}`);
    this.logger.log(`[CONFIRMED] toAccountSequence: ${payload.toAccountSequence}`);

    try {
      await this.systemWithdrawalService.handleWithdrawalConfirmed(
        payload.orderNo,
        payload.txHash,
      );
      this.logger.log(`[CONFIRMED] System withdrawal ${payload.orderNo} confirmed successfully`);
    } catch (error) {
      this.logger.error(
        `[CONFIRMED] Failed to process system withdrawal confirmation: ${payload.orderNo}`,
        error,
      );
      throw error;
    }
  }

  /**
   * Handle system withdrawal failed event
   * Update order status to FAILED and refund sender's wallet
   */
  private async handleSystemWithdrawalFailed(
    payload: SystemWithdrawalFailedPayload,
  ): Promise<void> {
    this.logger.log(`[FAILED] Processing system withdrawal failure`);
    this.logger.log(`[FAILED] orderNo: ${payload.orderNo}`);
    this.logger.log(`[FAILED] error: ${payload.error}`);

    try {
      await this.systemWithdrawalService.handleWithdrawalFailed(
        payload.orderNo,
        payload.error,
      );
      this.logger.log(`[FAILED] System withdrawal ${payload.orderNo} failure processed`);
    } catch (error) {
      this.logger.error(
        `[FAILED] Failed to process system withdrawal failure: ${payload.orderNo}`,
        error,
      );
      throw error;
    }
  }
}
