import { Injectable, Logger, OnModuleDestroy } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Redis from 'ioredis';
import Decimal from 'decimal.js';

/**
 * 热钱包 dUSDT (绿积分) 余额缓存服务
 *
 * 从 Redis DB 0 读取 blockchain-service 写入的热钱包 dUSDT 余额缓存。
 * 用于在用户发起转账前预检查热钱包余额是否足够。
 *
 * Redis Key 格式: hot_wallet:dusdt_balance:{chainType}
 *
 * 策略：如果无法获取余额（Redis 故障、缓存过期等），返回 null，
 * 调用方应拒绝转账并提示用户稍后重试。
 */
@Injectable()
export class HotWalletCacheService implements OnModuleDestroy {
  private readonly logger = new Logger(HotWalletCacheService.name);

  // Redis key 前缀（与 blockchain-service 保持一致）
  private readonly REDIS_KEY_PREFIX = 'hot_wallet:dusdt_balance:';

  // 使用独立的 Redis 连接，连接到 DB 0（公共数据库）
  private readonly sharedRedis: Redis;

  constructor(private readonly configService: ConfigService) {
    // 创建连接到 DB 0 的 Redis 客户端（公共数据库）
    this.sharedRedis = new Redis({
      host: this.configService.get<string>('REDIS_HOST') || 'localhost',
      port: this.configService.get<number>('REDIS_PORT') || 6379,
      password: this.configService.get<string>('REDIS_PASSWORD') || undefined,
      db: 0, // 使用 DB 0 作为公共数据库
    });

    this.sharedRedis.on('connect', () => {
      this.logger.log('[REDIS] Connected to shared Redis DB 0 for hot wallet balance cache');
    });

    this.sharedRedis.on('error', (err) => {
      this.logger.error('[REDIS] Shared Redis connection error', err);
    });
  }

  onModuleDestroy() {
    this.sharedRedis.disconnect();
  }

  /**
   * 获取指定链的热钱包余额
   *
   * @param chainType 链类型 (KAVA, BSC)
   * @returns 余额（Decimal），如果无法获取则返回 null
   */
  async getHotWalletBalance(chainType: string): Promise<Decimal | null> {
    try {
      const redisKey = `${this.REDIS_KEY_PREFIX}${chainType.toUpperCase()}`;
      const balance = await this.sharedRedis.get(redisKey);

      if (balance === null) {
        this.logger.warn(`[CACHE] Hot wallet balance not found for ${chainType}`);
        return null;
      }

      const balanceDecimal = new Decimal(balance);
      this.logger.debug(`[CACHE] Hot wallet dUSDT balance for ${chainType}: ${balanceDecimal.toString()}`);
      return balanceDecimal;
    } catch (error) {
      this.logger.error(`[CACHE] Failed to get hot wallet balance for ${chainType}`, error);
      return null;
    }
  }

  /**
   * 检查热钱包余额是否足够支付转账
   *
   * @param chainType 链类型
   * @param requiredAmount 所需金额
   * @returns { sufficient: boolean, balance: Decimal | null, error?: string }
   */
  async checkSufficientBalance(
    chainType: string,
    requiredAmount: Decimal,
  ): Promise<{ sufficient: boolean; balance: Decimal | null; error?: string }> {
    const balance = await this.getHotWalletBalance(chainType);

    if (balance === null) {
      return {
        sufficient: false,
        balance: null,
        error: '财务系统审计中，请稍后再试',
      };
    }

    if (balance.lessThan(requiredAmount)) {
      this.logger.warn(
        `[CHECK] Insufficient hot wallet balance for ${chainType}: need ${requiredAmount.toString()}, have ${balance.toString()}`,
      );
      return {
        sufficient: false,
        balance,
        error: '财务系统审计中，请稍后再试',
      };
    }

    return { sufficient: true, balance };
  }
}
