import { EventEmitter } from 'events';

interface BattlePassTier {
  tier: number;
  name: string;
  requiredXP: number;
  rewards: {
    coins?: number;
    gems?: number;
    cosmetics?: string[];
    badges?: string[];
  };
}

interface Season {
  id: string;
  name: string;
  number: number;
  theme: string;
  startDate: Date;
  endDate: Date;
  battlePass: BattlePassTier[];
  weeklyChallenge: WeeklyChallenge[];
  seasonalRewards: SeasonalReward[];
  status: 'upcoming' | 'active' | 'ended';
}

interface WeeklyChallenge {
  id: string;
  seasonId: string;
  week: number;
  title: string;
  description: string;
  objective: string;
  targetValue: number;
  rewards: {
    xp: number;
    coins?: number;
    cosmetics?: string[];
  };
  difficulty: 'easy' | 'medium' | 'hard';
}

interface SeasonalReward {
  id: string;
  seasonId: string;
  name: string;
  description: string;
  type: 'cosmetic' | 'badge' | 'title' | 'emote';
  rarity: 'common' | 'rare' | 'epic' | 'legendary';
  unlockedBy: 'tier' | 'challenge' | 'achievement';
  requirement: string;
}

interface PlayerSeasonProgress {
  userId: string;
  seasonId: string;
  currentTier: number;
  currentXP: number;
  completedChallenges: string[];
  unlockedRewards: string[];
  battlePassType: 'free' | 'premium';
  premiumPurchaseDate?: Date;
}

export class SeasonalRewardsSystem extends EventEmitter {
  private seasons = new Map<string, Season>();
  private playerProgress = new Map<string, PlayerSeasonProgress>();
  private challengeProgress = new Map<string, { userId: string; challengeId: string; progress: number }[]>();

  /**
   * Create a new season
   */
  createSeason(config: {
    name: string;
    number: number;
    theme: string;
    startDate: Date;
    endDate: Date;
  }): Season {
    const seasonId = `season_${config.number}_${Date.now()}`;

    const season: Season = {
      id: seasonId,
      name: config.name,
      number: config.number,
      theme: config.theme,
      startDate: config.startDate,
      endDate: config.endDate,
      battlePass: this.generateBattlePassTiers(),
      weeklyChallenge: this.generateWeeklyChallenges(seasonId),
      seasonalRewards: this.generateSeasonalRewards(seasonId),
      status: 'upcoming',
    };

    this.seasons.set(seasonId, season);
    this.emit('season:created', { seasonId, name: config.name });

    return season;
  }

  /**
   * Activate a season
   */
  activateSeason(seasonId: string): Season | null {
    const season = this.seasons.get(seasonId);
    if (!season) return null;

    season.status = 'active';
    this.emit('season:activated', { seasonId });

    return season;
  }

  /**
   * End a season
   */
  endSeason(seasonId: string): Season | null {
    const season = this.seasons.get(seasonId);
    if (!season) return null;

    season.status = 'ended';
    this.emit('season:ended', { seasonId });

    return season;
  }

  /**
   * Get or create player season progress
   */
  getPlayerProgress(userId: string, seasonId: string): PlayerSeasonProgress {
    const key = `${userId}_${seasonId}`;
    let progress = this.playerProgress.get(key);

    if (!progress) {
      progress = {
        userId,
        seasonId,
        currentTier: 1,
        currentXP: 0,
        completedChallenges: [],
        unlockedRewards: [],
        battlePassType: 'free',
      };
      this.playerProgress.set(key, progress);
    }

    return progress;
  }

  /**
   * Add XP to player
   */
  addPlayerXP(userId: string, seasonId: string, xpAmount: number): PlayerSeasonProgress {
    const progress = this.getPlayerProgress(userId, seasonId);
    const season = this.seasons.get(seasonId);
    if (!season) throw new Error('Season not found');

    progress.currentXP += xpAmount;

    // Check for tier ups
    while (progress.currentTier <= season.battlePass.length) {
      const nextTier = season.battlePass[progress.currentTier - 1];
      if (progress.currentXP >= nextTier.requiredXP) {
        progress.currentTier++;
        this.emit('player:tier-up', { userId, seasonId, tier: progress.currentTier });
      } else {
        break;
      }
    }

    return progress;
  }

  /**
   * Complete a weekly challenge
   */
  completeChallenge(userId: string, challengeId: string): boolean {
    const challenge = this.findChallenge(challengeId);
    if (!challenge) return false;

    const progress = this.getPlayerProgress(userId, challenge.seasonId);

    if (progress.completedChallenges.includes(challengeId)) {
      return false; // Already completed
    }

    progress.completedChallenges.push(challengeId);

    // Award XP
    this.addPlayerXP(userId, challenge.seasonId, challenge.rewards.xp);

    this.emit('challenge:completed', { userId, challengeId, rewards: challenge.rewards });

    return true;
  }

  /**
   * Purchase premium battle pass
   */
  purchasePremiumPass(userId: string, seasonId: string): PlayerSeasonProgress {
    const progress = this.getPlayerProgress(userId, seasonId);
    progress.battlePassType = 'premium';
    progress.premiumPurchaseDate = new Date();

    this.emit('battlepass:purchased', { userId, seasonId });

    return progress;
  }

  /**
   * Get season details
   */
  getSeason(seasonId: string): Season | null {
    return this.seasons.get(seasonId) || null;
  }

  /**
   * Get active season
   */
  getActiveSeason(): Season | null {
    for (const season of this.seasons.values()) {
      if (season.status === 'active') {
        return season;
      }
    }
    return null;
  }

  /**
   * Get weekly challenges for a season
   */
  getWeeklyChallenges(seasonId: string, week?: number): WeeklyChallenge[] {
    const season = this.seasons.get(seasonId);
    if (!season) return [];

    if (week !== undefined) {
      return season.weeklyChallenge.filter(c => c.week === week);
    }

    return season.weeklyChallenge;
  }

  /**
   * Get player battle pass progress
   */
  getPlayerBattlePassProgress(userId: string, seasonId: string) {
    const progress = this.getPlayerProgress(userId, seasonId);
    const season = this.seasons.get(seasonId);
    if (!season) return null;

    const currentTierData = season.battlePass[progress.currentTier - 1];
    const nextTierData = season.battlePass[progress.currentTier];

    return {
      currentTier: progress.currentTier,
      totalTiers: season.battlePass.length,
      currentXP: progress.currentXP,
      requiredXP: currentTierData?.requiredXP || 0,
      nextTierXP: nextTierData?.requiredXP || 0,
      xpProgress: nextTierData
        ? ((progress.currentXP - currentTierData.requiredXP) /
            (nextTierData.requiredXP - currentTierData.requiredXP)) *
          100
        : 100,
      battlePassType: progress.battlePassType,
      completedChallenges: progress.completedChallenges.length,
      unlockedRewards: progress.unlockedRewards,
    };
  }

  /**
   * Generate battle pass tiers
   */
  private generateBattlePassTiers(): BattlePassTier[] {
    const tiers: BattlePassTier[] = [];
    for (let i = 1; i <= 50; i++) {
      tiers.push({
        tier: i,
        name: `Tier ${i}`,
        requiredXP: i * 1000,
        rewards: {
          coins: i * 100,
          gems: i % 5 === 0 ? 50 : 0,
          cosmetics: i % 10 === 0 ? [`cosmetic_tier_${i}`] : [],
          badges: i % 25 === 0 ? [`badge_tier_${i}`] : [],
        },
      });
    }
    return tiers;
  }

  /**
   * Generate weekly challenges
   */
  private generateWeeklyChallenges(seasonId: string): WeeklyChallenge[] {
    const challenges: WeeklyChallenge[] = [];
    for (let week = 1; week <= 12; week++) {
      challenges.push(
        {
          id: `challenge_${seasonId}_${week}_1`,
          seasonId,
          week,
          title: `Play ${week * 5} Games`,
          description: `Complete ${week * 5} games this week`,
          objective: 'games_played',
          targetValue: week * 5,
          rewards: { xp: 500, coins: 100 },
          difficulty: 'easy',
        },
        {
          id: `challenge_${seasonId}_${week}_2`,
          seasonId,
          week,
          title: `Win ${week * 3} Games`,
          description: `Win ${week * 3} games this week`,
          objective: 'games_won',
          targetValue: week * 3,
          rewards: { xp: 750, coins: 200 },
          difficulty: 'medium',
        },
        {
          id: `challenge_${seasonId}_${week}_3`,
          seasonId,
          week,
          title: `Earn ${week * 5000} SC`,
          description: `Earn ${week * 5000} SC this week`,
          objective: 'coins_earned',
          targetValue: week * 5000,
          rewards: { xp: 1000, coins: 300, cosmetics: [`cosmetic_week_${week}`] },
          difficulty: 'hard',
        }
      );
    }
    return challenges;
  }

  /**
   * Generate seasonal rewards
   */
  private generateSeasonalRewards(seasonId: string): SeasonalReward[] {
    return [
      {
        id: `reward_${seasonId}_1`,
        seasonId,
        name: 'Season Champion Badge',
        description: 'Awarded for reaching tier 50',
        type: 'badge',
        rarity: 'legendary',
        unlockedBy: 'tier',
        requirement: 'tier_50',
      },
      {
        id: `reward_${seasonId}_2`,
        seasonId,
        name: 'Seasonal Emote Pack',
        description: '5 exclusive emotes for this season',
        type: 'emote',
        rarity: 'epic',
        unlockedBy: 'tier',
        requirement: 'tier_25',
      },
      {
        id: `reward_${seasonId}_3`,
        seasonId,
        name: 'Season Title',
        description: 'Display your seasonal achievement',
        type: 'title',
        rarity: 'rare',
        unlockedBy: 'achievement',
        requirement: 'complete_all_challenges',
      },
    ];
  }

  /**
   * Find challenge by ID
   */
  private findChallenge(challengeId: string): WeeklyChallenge | null {
    for (const season of this.seasons.values()) {
      const challenge = season.weeklyChallenge.find(c => c.id === challengeId);
      if (challenge) return challenge;
    }
    return null;
  }

  /**
   * Get season leaderboard
   */
  getSeasonLeaderboard(seasonId: string, limit: number = 100) {
    const leaderboard: Array<{
      userId: string;
      tier: number;
      xp: number;
      completedChallenges: number;
    }> = [];

    for (const [key, progress] of this.playerProgress.entries()) {
      if (progress.seasonId === seasonId) {
        leaderboard.push({
          userId: progress.userId,
          tier: progress.currentTier,
          xp: progress.currentXP,
          completedChallenges: progress.completedChallenges.length,
        });
      }
    }

    return leaderboard
      .sort((a, b) => {
        if (b.tier !== a.tier) return b.tier - a.tier;
        return b.xp - a.xp;
      })
      .slice(0, limit);
  }
}

export const seasonalRewardsSystem = new SeasonalRewardsSystem();
