import { EventEmitter } from 'events';

export enum VIPTier {
  BRONZE = 'bronze',
  SILVER = 'silver',
  GOLD = 'gold',
  PLATINUM = 'platinum',
}

interface VIPTierConfig {
  tier: VIPTier;
  minScore: number;
  entryFee: number;
  prizeMultiplier: number;
  maxTournaments: number;
  bonusPercentage: number;
  perks: string[];
}

interface VIPTournament {
  tournamentId: string;
  tier: VIPTier;
  name: string;
  entryFee: number;
  prizePool: number;
  maxPlayers: number;
  currentPlayers: number;
  status: 'upcoming' | 'active' | 'completed';
  startTime: Date;
  endTime?: Date;
  rewards: Record<number, number>; // rank -> prize amount
}

interface PlayerVIPStatus {
  playerId: string;
  currentTier: VIPTier;
  totalScore: number;
  tournamentsPlayed: number;
  winnings: number;
  nextTierProgress: number; // 0-100
}

export class VIPTournamentTiersService extends EventEmitter {
  private tierConfigs: Map<VIPTier, VIPTierConfig> = new Map();
  private vipTournaments: Map<string, VIPTournament> = new Map();
  private playerVIPStatus: Map<string, PlayerVIPStatus> = new Map();

  constructor() {
    super();
    this.initializeTierConfigs();
  }

  /**
   * Initialize VIP tier configurations
   */
  private initializeTierConfigs() {
    const configs: VIPTierConfig[] = [
      {
        tier: VIPTier.BRONZE,
        minScore: 0,
        entryFee: 10,
        prizeMultiplier: 1.0,
        maxTournaments: 5,
        bonusPercentage: 5,
        perks: ['Bronze badge', '5% bonus on wins', 'Access to bronze tournaments'],
      },
      {
        tier: VIPTier.SILVER,
        minScore: 5000,
        entryFee: 25,
        prizeMultiplier: 1.5,
        maxTournaments: 10,
        bonusPercentage: 10,
        perks: [
          'Silver badge',
          '10% bonus on wins',
          'Access to silver tournaments',
          'Weekly bonus SC',
        ],
      },
      {
        tier: VIPTier.GOLD,
        minScore: 15000,
        entryFee: 50,
        prizeMultiplier: 2.0,
        maxTournaments: 20,
        bonusPercentage: 15,
        perks: [
          'Gold badge',
          '15% bonus on wins',
          'Access to gold tournaments',
          'Weekly bonus SC',
          'Priority support',
        ],
      },
      {
        tier: VIPTier.PLATINUM,
        minScore: 50000,
        entryFee: 100,
        prizeMultiplier: 3.0,
        maxTournaments: 50,
        bonusPercentage: 25,
        perks: [
          'Platinum badge',
          '25% bonus on wins',
          'Access to platinum tournaments',
          'Weekly bonus SC',
          'Priority support',
          'Exclusive events',
          'Personal account manager',
        ],
      },
    ];

    configs.forEach((config) => {
      this.tierConfigs.set(config.tier, config);
    });
  }

  /**
   * Get player VIP status
   */
  getPlayerVIPStatus(playerId: string): PlayerVIPStatus {
    if (!this.playerVIPStatus.has(playerId)) {
      this.playerVIPStatus.set(playerId, {
        playerId,
        currentTier: VIPTier.BRONZE,
        totalScore: 0,
        tournamentsPlayed: 0,
        winnings: 0,
        nextTierProgress: 0,
      });
    }

    return this.playerVIPStatus.get(playerId)!;
  }

  /**
   * Update player score and check for tier promotion
   */
  updatePlayerScore(playerId: string, scoreIncrease: number, winnings: number = 0) {
    const status = this.getPlayerVIPStatus(playerId);
    const previousTier = status.currentTier;

    status.totalScore += scoreIncrease;
    status.winnings += winnings;
    status.tournamentsPlayed += 1;

    // Check for tier promotion
    const newTier = this.determineTier(status.totalScore);
    if (newTier !== previousTier) {
      status.currentTier = newTier;
      this.emit('tier_promoted', {
        playerId,
        previousTier,
        newTier,
        totalScore: status.totalScore,
      });
    }

    // Calculate progress to next tier
    status.nextTierProgress = this.calculateTierProgress(status.totalScore, newTier);

    return status;
  }

  /**
   * Determine tier based on score
   */
  private determineTier(score: number): VIPTier {
    if (score >= 50000) return VIPTier.PLATINUM;
    if (score >= 15000) return VIPTier.GOLD;
    if (score >= 5000) return VIPTier.SILVER;
    return VIPTier.BRONZE;
  }

  /**
   * Calculate progress to next tier (0-100)
   */
  private calculateTierProgress(score: number, currentTier: VIPTier): number {
    const tierThresholds = [0, 5000, 15000, 50000];
    const tierIndex = Object.values(VIPTier).indexOf(currentTier);

    if (tierIndex === 3) return 100; // Platinum is max tier

    const currentThreshold = tierThresholds[tierIndex];
    const nextThreshold = tierThresholds[tierIndex + 1];
    const progress = ((score - currentThreshold) / (nextThreshold - currentThreshold)) * 100;

    return Math.min(100, Math.max(0, progress));
  }

  /**
   * Create a VIP tournament
   */
  createVIPTournament(
    tournamentId: string,
    tier: VIPTier,
    name: string,
    maxPlayers: number,
    startTime: Date,
    endTime: Date
  ): VIPTournament {
    const config = this.tierConfigs.get(tier)!;
    const basePrizePool = config.entryFee * maxPlayers * config.prizeMultiplier;

    const tournament: VIPTournament = {
      tournamentId,
      tier,
      name,
      entryFee: config.entryFee,
      prizePool: basePrizePool,
      maxPlayers,
      currentPlayers: 0,
      status: 'upcoming',
      startTime,
      endTime,
      rewards: this.generateRewardStructure(basePrizePool, maxPlayers),
    };

    this.vipTournaments.set(tournamentId, tournament);
    this.emit('tournament_created', tournament);

    return tournament;
  }

  /**
   * Generate reward structure for tournament
   */
  private generateRewardStructure(prizePool: number, maxPlayers: number): Record<number, number> {
    const rewards: Record<number, number> = {};

    // Top 10% get rewards
    const rewardPlaces = Math.max(1, Math.floor(maxPlayers * 0.1));
    const rewardPercentages = [0.4, 0.25, 0.15, 0.1, 0.05, 0.03, 0.01, 0.005, 0.003, 0.001];

    for (let i = 0; i < rewardPlaces && i < rewardPercentages.length; i++) {
      rewards[i + 1] = Math.floor(prizePool * rewardPercentages[i]);
    }

    return rewards;
  }

  /**
   * Register player for VIP tournament
   */
  registerForTournament(playerId: string, tournamentId: string): boolean {
    const tournament = this.vipTournaments.get(tournamentId);
    if (!tournament) return false;

    const playerStatus = this.getPlayerVIPStatus(playerId);

    // Check if player tier matches tournament tier
    if (playerStatus.currentTier !== tournament.tier) {
      this.emit('registration_failed', {
        playerId,
        tournamentId,
        reason: 'Tier mismatch',
      });
      return false;
    }

    // Check if tournament is full
    if (tournament.currentPlayers >= tournament.maxPlayers) {
      this.emit('registration_failed', {
        playerId,
        tournamentId,
        reason: 'Tournament full',
      });
      return false;
    }

    tournament.currentPlayers += 1;
    this.emit('player_registered', { playerId, tournamentId });

    return true;
  }

  /**
   * Get VIP tournaments for a tier
   */
  getVIPTournaments(tier: VIPTier): VIPTournament[] {
    return Array.from(this.vipTournaments.values()).filter((t) => t.tier === tier);
  }

  /**
   * Get tier configuration
   */
  getTierConfig(tier: VIPTier): VIPTierConfig | undefined {
    return this.tierConfigs.get(tier);
  }

  /**
   * Get all tier configurations
   */
  getAllTierConfigs(): VIPTierConfig[] {
    return Array.from(this.tierConfigs.values());
  }

  /**
   * Calculate bonus for player
   */
  calculateBonus(playerId: string, baseAmount: number): number {
    const status = this.getPlayerVIPStatus(playerId);
    const config = this.tierConfigs.get(status.currentTier)!;
    const bonusAmount = baseAmount * (config.bonusPercentage / 100);

    return Math.floor(bonusAmount);
  }

  /**
   * Get leaderboard for VIP tier
   */
  getVIPLeaderboard(tier: VIPTier, limit: number = 100) {
    return Array.from(this.playerVIPStatus.values())
      .filter((status) => status.currentTier === tier)
      .sort((a, b) => b.totalScore - a.totalScore)
      .slice(0, limit);
  }
}

export default VIPTournamentTiersService;
