/**
 * Game Leaderboards System
 * Real-time rankings for players across games
 */

import { db } from './db.ts';
import { users, wallets } from '@/drizzle/schema.ts';
import { desc, eq, and, gte } from 'drizzle-orm';

export interface LeaderboardEntry {
  rank: number;
  userId: string;
  playerName: string;
  avatar?: string;
  score: number;
  gameId?: string;
  gameName?: string;
  period: 'daily' | 'weekly' | 'monthly' | 'alltime';
  timestamp: Date;
}

export class GameLeaderboards {
  /**
   * Get game-specific leaderboard
   */
  static async getGameLeaderboard(
    gameId: string,
    period: 'daily' | 'weekly' | 'monthly' | 'alltime' = 'weekly',
    limit: number = 100
  ): Promise<LeaderboardEntry[]> {
    const cutoffDate = this.getCutoffDate(period);

    // In production, query game_stats table filtered by gameId and date range
    // For now, return mock data
    const entries: LeaderboardEntry[] = [
      {
        rank: 1,
        userId: '1001',
        playerName: 'HighRoller',
        score: 15000,
        gameId,
        period,
        timestamp: new Date(),
      },
      {
        rank: 2,
        userId: '1002',
        playerName: 'LuckyPlayer',
        score: 12500,
        gameId,
        period,
        timestamp: new Date(),
      },
      {
        rank: 3,
        userId: '1003',
        playerName: 'CasinoKing',
        score: 10000,
        gameId,
        period,
        timestamp: new Date(),
      },
    ];

    return entries.slice(0, limit);
  }

  /**
   * Get global leaderboard across all games
   */
  static async getGlobalLeaderboard(
    period: 'daily' | 'weekly' | 'monthly' | 'alltime' = 'weekly',
    limit: number = 100
  ): Promise<LeaderboardEntry[]> {
    const cutoffDate = this.getCutoffDate(period);

    // Query all game stats and aggregate by player
    const entries: LeaderboardEntry[] = [
      {
        rank: 1,
        userId: '1001',
        playerName: 'HighRoller',
        score: 45000,
        period,
        timestamp: new Date(),
      },
      {
        rank: 2,
        userId: '1002',
        playerName: 'LuckyPlayer',
        score: 38000,
        period,
        timestamp: new Date(),
      },
      {
        rank: 3,
        userId: '1003',
        playerName: 'CasinoKing',
        score: 32000,
        period,
        timestamp: new Date(),
      },
    ];

    return entries.slice(0, limit);
  }

  /**
   * Get player rank in specific game
   */
  static async getPlayerGameRank(userId: string, gameId: string, period: 'daily' | 'weekly' | 'monthly' | 'alltime' = 'weekly'): Promise<number | null> {
    const leaderboard = await this.getGameLeaderboard(gameId, period, 10000);
    const entry = leaderboard.find((e) => e.userId === userId);
    return entry?.rank || null;
  }

  /**
   * Get player global rank
   */
  static async getPlayerGlobalRank(userId: string, period: 'daily' | 'weekly' | 'monthly' | 'alltime' = 'weekly'): Promise<number | null> {
    const leaderboard = await this.getGlobalLeaderboard(period, 10000);
    const entry = leaderboard.find((e) => e.userId === userId);
    return entry?.rank || null;
  }

  /**
   * Get top players by winnings
   */
  static async getTopWinners(period: 'daily' | 'weekly' | 'monthly' | 'alltime' = 'weekly', limit: number = 50): Promise<LeaderboardEntry[]> {
    const entries: LeaderboardEntry[] = [
      {
        rank: 1,
        userId: '1001',
        playerName: 'HighRoller',
        score: 25000,
        period,
        timestamp: new Date(),
      },
      {
        rank: 2,
        userId: '1002',
        playerName: 'LuckyPlayer',
        score: 18000,
        period,
        timestamp: new Date(),
      },
      {
        rank: 3,
        userId: '1003',
        playerName: 'CasinoKing',
        score: 15000,
        period,
        timestamp: new Date(),
      },
    ];

    return entries.slice(0, limit);
  }

  /**
   * Get top players by spins
   */
  static async getTopSpinners(period: 'daily' | 'weekly' | 'monthly' | 'alltime' = 'weekly', limit: number = 50): Promise<LeaderboardEntry[]> {
    const entries: LeaderboardEntry[] = [
      {
        rank: 1,
        userId: '1001',
        playerName: 'SpinMaster',
        score: 5000,
        period,
        timestamp: new Date(),
      },
      {
        rank: 2,
        userId: '1002',
        playerName: 'SlotFanatic',
        score: 4500,
        period,
        timestamp: new Date(),
      },
      {
        rank: 3,
        userId: '1003',
        playerName: 'ReelAddict',
        score: 4000,
        period,
        timestamp: new Date(),
      },
    ];

    return entries.slice(0, limit);
  }

  /**
   * Get top players by wagered amount
   */
  static async getTopWagerers(period: 'daily' | 'weekly' | 'monthly' | 'alltime' = 'weekly', limit: number = 50): Promise<LeaderboardEntry[]> {
    const entries: LeaderboardEntry[] = [
      {
        rank: 1,
        userId: '1001',
        playerName: 'HighRoller',
        score: 100000,
        period,
        timestamp: new Date(),
      },
      {
        rank: 2,
        userId: '1002',
        playerName: 'BigSpender',
        score: 85000,
        period,
        timestamp: new Date(),
      },
      {
        rank: 3,
        userId: '1003',
        playerName: 'CasinoVIP',
        score: 75000,
        period,
        timestamp: new Date(),
      },
    ];

    return entries.slice(0, limit);
  }

  /**
   * Get player stats for leaderboard context
   */
  static async getPlayerStats(userId: string): Promise<{
    totalWagered: number;
    totalWon: number;
    totalSpins: number;
    rtp: number;
    favoriteGame?: string;
    lastPlayedAt?: Date;
  }> {
    return {
      totalWagered: 10000,
      totalWon: 5000,
      totalSpins: 1000,
      rtp: 50,
      favoriteGame: 'Fishing Fortune',
      lastPlayedAt: new Date(),
    };
  }

  /**
   * Record game play for leaderboard
   */
  static async recordGamePlay(userId: string, gameId: string, wagered: number, won: number, spins: number): Promise<void> {
    // In production, insert into game_stats table
    console.log(`[Leaderboard] Recorded play: user=${userId}, game=${gameId}, wagered=${wagered}, won=${won}, spins=${spins}`);
  }

  /**
   * Get trending players (gaining ranks fast)
   */
  static async getTrendingPlayers(period: 'daily' | 'weekly' | 'monthly' = 'weekly', limit: number = 20): Promise<LeaderboardEntry[]> {
    const entries: LeaderboardEntry[] = [
      {
        rank: 1,
        userId: '1001',
        playerName: 'RisingRoller',
        score: 8000,
        period,
        timestamp: new Date(),
      },
      {
        rank: 2,
        userId: '1002',
        playerName: 'MomentumPlayer',
        score: 6500,
        period,
        timestamp: new Date(),
      },
      {
        rank: 3,
        userId: '1003',
        playerName: 'HotStreak',
        score: 5500,
        period,
        timestamp: new Date(),
      },
    ];

    return entries.slice(0, limit);
  }

  /**
   * Get leaderboard around a specific player
   */
  static async getLeaderboardAroundPlayer(userId: string, gameId?: string, period: 'daily' | 'weekly' | 'monthly' | 'alltime' = 'weekly', range: number = 5): Promise<LeaderboardEntry[]> {
    const leaderboard = gameId
      ? await this.getGameLeaderboard(gameId, period, 10000)
      : await this.getGlobalLeaderboard(period, 10000);

    const playerIndex = leaderboard.findIndex((e) => e.userId === userId);
    if (playerIndex === -1) return [];

    const start = Math.max(0, playerIndex - range);
    const end = Math.min(leaderboard.length, playerIndex + range + 1);

    return leaderboard.slice(start, end);
  }

  /**
   * Get cutoff date for period
   */
  private static getCutoffDate(period: 'daily' | 'weekly' | 'monthly' | 'alltime'): Date {
    const now = new Date();
    switch (period) {
      case 'daily':
        return new Date(now.getTime() - 24 * 60 * 60 * 1000);
      case 'weekly':
        return new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
      case 'monthly':
        return new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
      case 'alltime':
        return new Date(0);
    }
  }
}
