import { Injectable } from '@nestjs/common';
import { LeaderboardRanking } from '../aggregates/leaderboard-ranking/leaderboard-ranking.aggregate';

/**
 * 排名合并服务
 *
 * 负责将虚拟排名和真实排名合并
 */
@Injectable()
export class RankingMergerService {
  /**
   * 合并虚拟排名和真实排名
   *
   * 规则：
   * - 虚拟账户占据前面的位置
   * - 真实用户排名从虚拟账户数量+1开始
   *
   * @example
   * // 虚拟账户数量设置为 30
   * // 真实排名第1的用户显示在第31名
   *
   * // 虚拟账户数量设置为 0
   * // 关闭虚拟排名，完全显示真实排名
   */
  mergeRankings(
    virtualRankings: LeaderboardRanking[],
    realRankings: LeaderboardRanking[],
    displayLimit: number,
  ): LeaderboardRanking[] {
    const merged: LeaderboardRanking[] = [];
    const virtualCount = virtualRankings.length;

    // 1. 添加虚拟排名
    for (const virtual of virtualRankings) {
      if (virtual.displayPosition.value <= displayLimit) {
        merged.push(virtual);
      }
    }

    // 2. 调整真实用户的显示排名并添加
    for (const real of realRankings) {
      const newDisplayPosition = real.rankPosition.value + virtualCount;

      if (newDisplayPosition <= displayLimit) {
        real.updateDisplayPosition(newDisplayPosition);
        merged.push(real);
      }
    }

    // 3. 按显示排名排序
    merged.sort((a, b) => a.displayPosition.value - b.displayPosition.value);

    return merged;
  }

  /**
   * 仅获取真实用户排名（不含虚拟）
   *
   * 用于后台管理或内部统计
   */
  getRealRankingsOnly(
    rankings: LeaderboardRanking[],
    displayLimit: number,
  ): LeaderboardRanking[] {
    return rankings
      .filter(r => !r.isVirtual)
      .slice(0, displayLimit);
  }

  /**
   * 仅获取虚拟排名
   *
   * 用于后台管理
   */
  getVirtualRankingsOnly(
    rankings: LeaderboardRanking[],
  ): LeaderboardRanking[] {
    return rankings.filter(r => r.isVirtual);
  }

  /**
   * 计算用户的实际排名（去除虚拟用户后的排名）
   */
  calculateRealRankPosition(
    allRankings: LeaderboardRanking[],
    userId: bigint,
  ): number | null {
    const realRankings = this.getRealRankingsOnly(allRankings, allRankings.length);
    const index = realRankings.findIndex(r => r.userId === userId);
    return index >= 0 ? index + 1 : null;
  }

  /**
   * 验证排名连续性
   */
  validateRankingContinuity(rankings: LeaderboardRanking[]): boolean {
    const sorted = [...rankings].sort((a, b) =>
      a.displayPosition.value - b.displayPosition.value
    );

    for (let i = 0; i < sorted.length; i++) {
      if (sorted[i].displayPosition.value !== i + 1) {
        return false;
      }
    }
    return true;
  }
}
