import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { RedisService } from './redis.service';
import { LeaderboardType } from '../../domain/value-objects/leaderboard-type.enum';

/**
 * 榜单缓存服务
 *
 * 缓存键格式:
 * - leaderboard:{type}:{periodKey} - 榜单数据
 * - leaderboard:{type}:{periodKey}:user:{userId} - 用户排名
 */
@Injectable()
export class LeaderboardCacheService {
  private readonly logger = new Logger(LeaderboardCacheService.name);
  private readonly cacheTTL: number;
  private readonly keyPrefix = 'leaderboard';

  constructor(
    private readonly redisService: RedisService,
    private readonly configService: ConfigService,
  ) {
    this.cacheTTL = this.configService.get<number>('LEADERBOARD_CACHE_TTL', 300);
  }

  /**
   * 获取榜单缓存键
   */
  private getLeaderboardKey(type: LeaderboardType, periodKey: string): string {
    return `${this.keyPrefix}:${type}:${periodKey}`;
  }

  /**
   * 获取用户排名缓存键
   */
  private getUserRankingKey(type: LeaderboardType, periodKey: string, userId: bigint): string {
    return `${this.keyPrefix}:${type}:${periodKey}:user:${userId}`;
  }

  /**
   * 缓存榜单数据
   */
  async cacheLeaderboard(
    type: LeaderboardType,
    periodKey: string,
    rankings: any[],
  ): Promise<void> {
    const key = this.getLeaderboardKey(type, periodKey);
    try {
      await this.redisService.set(
        key,
        JSON.stringify(rankings),
        this.cacheTTL,
      );
      this.logger.debug(`缓存榜单数据: ${key}`);
    } catch (error) {
      this.logger.error(`缓存榜单数据失败: ${key}`, error);
    }
  }

  /**
   * 获取缓存的榜单数据
   */
  async getCachedLeaderboard(
    type: LeaderboardType,
    periodKey: string,
  ): Promise<any[] | null> {
    const key = this.getLeaderboardKey(type, periodKey);
    try {
      const cached = await this.redisService.get(key);
      if (cached) {
        return JSON.parse(cached);
      }
      return null;
    } catch (error) {
      this.logger.error(`获取缓存榜单数据失败: ${key}`, error);
      return null;
    }
  }

  /**
   * 缓存用户排名
   */
  async cacheUserRanking(
    type: LeaderboardType,
    periodKey: string,
    userId: bigint,
    ranking: any,
  ): Promise<void> {
    const key = this.getUserRankingKey(type, periodKey, userId);
    try {
      await this.redisService.set(
        key,
        JSON.stringify(ranking),
        this.cacheTTL,
      );
    } catch (error) {
      this.logger.error(`缓存用户排名失败: ${key}`, error);
    }
  }

  /**
   * 获取缓存的用户排名
   */
  async getCachedUserRanking(
    type: LeaderboardType,
    periodKey: string,
    userId: bigint,
  ): Promise<any | null> {
    const key = this.getUserRankingKey(type, periodKey, userId);
    try {
      const cached = await this.redisService.get(key);
      if (cached) {
        return JSON.parse(cached);
      }
      return null;
    } catch (error) {
      this.logger.error(`获取缓存用户排名失败: ${key}`, error);
      return null;
    }
  }

  /**
   * 清除榜单缓存
   */
  async invalidateLeaderboard(type: LeaderboardType, periodKey: string): Promise<void> {
    const pattern = `${this.keyPrefix}:${type}:${periodKey}*`;
    try {
      const keys = await this.redisService.keys(pattern);
      if (keys.length > 0) {
        for (const key of keys) {
          await this.redisService.del(key);
        }
        this.logger.debug(`清除榜单缓存: ${pattern}, 共 ${keys.length} 个键`);
      }
    } catch (error) {
      this.logger.error(`清除榜单缓存失败: ${pattern}`, error);
    }
  }

  /**
   * 清除所有榜单缓存
   */
  async invalidateAllLeaderboards(): Promise<void> {
    const pattern = `${this.keyPrefix}:*`;
    try {
      const keys = await this.redisService.keys(pattern);
      if (keys.length > 0) {
        for (const key of keys) {
          await this.redisService.del(key);
        }
        this.logger.log(`清除所有榜单缓存, 共 ${keys.length} 个键`);
      }
    } catch (error) {
      this.logger.error('清除所有榜单缓存失败', error);
    }
  }
}
