import { Injectable } from '@nestjs/common';
import { ContributionAccountRepository } from '../../infrastructure/persistence/repositories/contribution-account.repository';
import { RedisService } from '../../infrastructure/redis/redis.service';

export interface ContributionRankingDto {
  rank: number;
  accountSequence: string;
  effectiveContribution: string;
  personalContribution: string;
  totalPending: string;
  totalUnlocked: string;
}

@Injectable()
export class GetContributionRankingQuery {
  private readonly RANKING_CACHE_KEY = 'contribution:ranking';
  private readonly CACHE_TTL = 300; // 5分钟缓存

  constructor(
    private readonly accountRepository: ContributionAccountRepository,
    private readonly redis: RedisService,
  ) {}

  /**
   * 获取算力排行榜
   */
  async execute(limit: number = 100): Promise<ContributionRankingDto[]> {
    // 尝试从缓存获取
    const cached = await this.redis.getJson<ContributionRankingDto[]>(`${this.RANKING_CACHE_KEY}:${limit}`);
    if (cached) {
      return cached;
    }

    // 从数据库获取
    const topContributors = await this.accountRepository.findTopContributors(limit);

    const ranking: ContributionRankingDto[] = topContributors.map((account, index) => ({
      rank: index + 1,
      accountSequence: account.accountSequence,
      effectiveContribution: account.effectiveContribution.value.toString(),
      personalContribution: account.personalContribution.value.toString(),
      totalPending: account.totalPending.value.toString(),
      totalUnlocked: account.totalUnlocked.value.toString(),
    }));

    // 缓存结果
    await this.redis.setJson(`${this.RANKING_CACHE_KEY}:${limit}`, ranking, this.CACHE_TTL);

    return ranking;
  }

  /**
   * 获取指定用户的排名
   */
  async getUserRank(accountSequence: string): Promise<{
    rank: number | null;
    effectiveContribution: string;
    percentile: number | null;
  } | null> {
    const account = await this.accountRepository.findByAccountSequence(accountSequence);
    if (!account) {
      return null;
    }

    // 使用 Redis 有序集合来快速获取排名
    // 这需要在算力变化时同步更新 Redis
    const rank = await this.redis.zrevrank('contribution:leaderboard', accountSequence);
    const totalAccounts = await this.accountRepository.countAccountsWithContribution();

    return {
      rank: rank !== null ? rank + 1 : null,
      effectiveContribution: account.effectiveContribution.value.toString(),
      percentile: rank !== null && totalAccounts > 0 ? ((totalAccounts - rank) / totalAccounts) * 100 : null,
    };
  }

  /**
   * 刷新排行榜缓存
   */
  async refreshRankingCache(): Promise<void> {
    // 清除旧缓存
    await this.redis.del(`${this.RANKING_CACHE_KEY}:100`);
    await this.redis.del(`${this.RANKING_CACHE_KEY}:50`);
    await this.redis.del(`${this.RANKING_CACHE_KEY}:10`);

    // 重新生成缓存
    await this.execute(100);
  }
}
