import { Injectable, Logger } from '@nestjs/common';
import { RedisService } from './redis.service';

/**
 * 钱包缓存数据结构
 */
export interface CachedWalletDTO {
  walletId: string;
  userId: string;
  balances: {
    usdt: { available: number; frozen: number };
    dst: { available: number; frozen: number };
    bnb: { available: number; frozen: number };
    og: { available: number; frozen: number };
    rwad: { available: number; frozen: number };
  };
  hashpower: number;
  rewards: {
    pendingUsdt: number;
    pendingHashpower: number;
    pendingExpireAt: string | null;
    settleableUsdt: number;
    settleableHashpower: number;
    settledTotalUsdt: number;
    settledTotalHashpower: number;
    expiredTotalUsdt: number;
    expiredTotalHashpower: number;
  };
  status: string;
  cachedAt: string;
}

@Injectable()
export class WalletCacheService {
  private readonly logger = new Logger(WalletCacheService.name);

  // 缓存前缀
  private readonly CACHE_PREFIX = 'wallet:user:';

  // 默认缓存时间：60秒（钱包数据变动时会主动失效）
  private readonly DEFAULT_TTL_SECONDS = 60;

  constructor(private readonly redisService: RedisService) {}

  /**
   * 生成缓存 key
   */
  private getCacheKey(userId: string | bigint): string {
    return `${this.CACHE_PREFIX}${userId.toString()}`;
  }

  /**
   * 获取缓存的钱包数据
   */
  async getWallet(userId: string | bigint): Promise<CachedWalletDTO | null> {
    const key = this.getCacheKey(userId);
    const cached = await this.redisService.getJson<CachedWalletDTO>(key);

    if (cached) {
      this.logger.debug(`Cache HIT for wallet: ${userId}`);
    } else {
      this.logger.debug(`Cache MISS for wallet: ${userId}`);
    }

    return cached;
  }

  /**
   * 缓存钱包数据
   */
  async setWallet(
    userId: string | bigint,
    wallet: Omit<CachedWalletDTO, 'cachedAt'>,
    ttlSeconds: number = this.DEFAULT_TTL_SECONDS,
  ): Promise<void> {
    const key = this.getCacheKey(userId);
    const cachedData: CachedWalletDTO = {
      ...wallet,
      cachedAt: new Date().toISOString(),
    };

    await this.redisService.setJson(key, cachedData, ttlSeconds);
    this.logger.debug(`Cached wallet for user: ${userId}, TTL: ${ttlSeconds}s`);
  }

  /**
   * 使钱包缓存失效（数据变更时调用）
   */
  async invalidateWallet(userId: string | bigint): Promise<void> {
    const key = this.getCacheKey(userId);
    await this.redisService.del(key);
    this.logger.debug(`Invalidated wallet cache for user: ${userId}`);
  }

  /**
   * 批量使钱包缓存失效
   */
  async invalidateWallets(userIds: (string | bigint)[]): Promise<void> {
    for (const userId of userIds) {
      await this.invalidateWallet(userId);
    }
  }

  /**
   * 清除所有钱包缓存（谨慎使用）
   */
  async invalidateAllWallets(): Promise<number> {
    const pattern = `${this.CACHE_PREFIX}*`;
    const count = await this.redisService.delByPattern(pattern);
    this.logger.warn(`Invalidated all wallet caches, count: ${count}`);
    return count;
  }

  /**
   * 检查缓存是否存在
   */
  async hasCache(userId: string | bigint): Promise<boolean> {
    const key = this.getCacheKey(userId);
    return this.redisService.exists(key);
  }

  /**
   * 获取缓存剩余 TTL
   */
  async getCacheTTL(userId: string | bigint): Promise<number> {
    const key = this.getCacheKey(userId);
    return this.redisService.ttl(key);
  }
}
