import { EventEmitter } from 'events';

export type BadgeType = 'achievement' | 'tournament' | 'engagement' | 'milestone' | 'social' | 'special';
export type BadgeRarity = 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary';

export interface Badge {
  id: string;
  name: string;
  description: string;
  type: BadgeType;
  rarity: BadgeRarity;
  icon: string;
  requirement: string;
  unlockedAt?: Date;
  progress?: number; // 0-100
}

export interface PlayerBadges {
  playerId: string;
  badges: Badge[];
  totalBadges: number;
  unlockedBadges: number;
  showcase: string[]; // Top 5 badge IDs to display
}

/**
 * Player Badges System
 * Manages player achievement badges and progression
 */
export class PlayerBadgesSystem extends EventEmitter {
  private playerBadges: Map<string, PlayerBadges> = new Map();
  private badgeDefinitions: Map<string, Badge> = new Map();
  private badgeUnlockHistory: Array<{ playerId: string; badgeId: string; timestamp: Date }> = [];

  constructor() {
    super();
    this.initializeBadgeDefinitions();
    console.log('[PlayerBadges] System initialized');
  }

  /**
   * Initialize badge definitions
   */
  private initializeBadgeDefinitions(): void {
    const badges: Badge[] = [
      // Achievement Badges
      {
        id: 'badge-first-win',
        name: 'First Victory',
        description: 'Win your first game',
        type: 'achievement',
        rarity: 'common',
        icon: '🏆',
        requirement: 'Win 1 game',
      },
      {
        id: 'badge-win-streak-10',
        name: 'On Fire',
        description: 'Win 10 games in a row',
        type: 'achievement',
        rarity: 'rare',
        icon: '🔥',
        requirement: 'Win 10 consecutive games',
      },
      {
        id: 'badge-win-100',
        name: 'Centennial',
        description: 'Achieve 100 wins',
        type: 'achievement',
        rarity: 'epic',
        icon: '💯',
        requirement: 'Win 100 games',
      },
      {
        id: 'badge-win-1000',
        name: 'Legendary Winner',
        description: 'Achieve 1000 wins',
        type: 'achievement',
        rarity: 'legendary',
        icon: '👑',
        requirement: 'Win 1000 games',
      },

      // Milestone Badges
      {
        id: 'badge-level-10',
        name: 'Rising Star',
        description: 'Reach level 10',
        type: 'milestone',
        rarity: 'common',
        icon: '⭐',
        requirement: 'Reach level 10',
      },
      {
        id: 'badge-level-50',
        name: 'Master Player',
        description: 'Reach level 50',
        type: 'milestone',
        rarity: 'epic',
        icon: '🎓',
        requirement: 'Reach level 50',
      },
      {
        id: 'badge-level-100',
        name: 'Grandmaster',
        description: 'Reach level 100',
        type: 'milestone',
        rarity: 'legendary',
        icon: '🧙',
        requirement: 'Reach level 100',
      },

      // Tournament Badges
      {
        id: 'badge-tournament-first',
        name: 'Tournament Debut',
        description: 'Participate in your first tournament',
        type: 'tournament',
        rarity: 'common',
        icon: '🎯',
        requirement: 'Join 1 tournament',
      },
      {
        id: 'badge-tournament-winner',
        name: 'Tournament Champion',
        description: 'Win a tournament',
        type: 'tournament',
        rarity: 'epic',
        icon: '🥇',
        requirement: 'Win 1 tournament',
      },
      {
        id: 'badge-tournament-top-10',
        name: 'Top Competitor',
        description: 'Finish in top 10 of 5 tournaments',
        type: 'tournament',
        rarity: 'rare',
        icon: '🏅',
        requirement: 'Top 10 finishes: 5',
      },

      // Engagement Badges
      {
        id: 'badge-daily-login-7',
        name: 'Dedicated Player',
        description: 'Login 7 days in a row',
        type: 'engagement',
        rarity: 'uncommon',
        icon: '📅',
        requirement: 'Consecutive logins: 7',
      },
      {
        id: 'badge-daily-login-30',
        name: 'Loyal Fan',
        description: 'Login 30 days in a row',
        type: 'engagement',
        rarity: 'rare',
        icon: '💚',
        requirement: 'Consecutive logins: 30',
      },
      {
        id: 'badge-social-share-5',
        name: 'Social Butterfly',
        description: 'Share 5 achievements',
        type: 'social',
        rarity: 'uncommon',
        icon: '🦋',
        requirement: 'Shares: 5',
      },

      // Special Badges
      {
        id: 'badge-early-adopter',
        name: 'Early Adopter',
        description: 'Join before launch',
        type: 'special',
        rarity: 'legendary',
        icon: '🚀',
        requirement: 'Joined before launch',
      },
    ];

    badges.forEach((badge) => {
      this.badgeDefinitions.set(badge.id, badge);
    });

    console.log(`[PlayerBadges] Initialized ${badges.length} badge definitions`);
  }

  /**
   * Initialize player badges
   */
  initializePlayerBadges(playerId: string): PlayerBadges {
    if (!this.playerBadges.has(playerId)) {
      const badges = Array.from(this.badgeDefinitions.values()).map((badge) => ({
        ...badge,
        progress: 0,
      }));

      const playerBadges: PlayerBadges = {
        playerId,
        badges,
        totalBadges: badges.length,
        unlockedBadges: 0,
        showcase: [],
      };

      this.playerBadges.set(playerId, playerBadges);

      this.emit('playerBadgesInitialized', { playerId, totalBadges: badges.length });
      console.log(`[PlayerBadges] Player ${playerId} badges initialized`);
    }

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

  /**
   * Unlock badge
   */
  unlockBadge(playerId: string, badgeId: string): Badge | null {
    const playerBadges = this.playerBadges.get(playerId);
    if (!playerBadges) {
      this.initializePlayerBadges(playerId);
      return this.unlockBadge(playerId, badgeId);
    }

    const badge = playerBadges.badges.find((b) => b.id === badgeId);
    if (!badge || badge.unlockedAt) {
      return null; // Already unlocked or not found
    }

    badge.unlockedAt = new Date();
    badge.progress = 100;
    playerBadges.unlockedBadges++;

    // Add to unlock history
    this.badgeUnlockHistory.push({
      playerId,
      badgeId,
      timestamp: new Date(),
    });

    // Keep only last 1000 unlocks
    if (this.badgeUnlockHistory.length > 1000) {
      this.badgeUnlockHistory.shift();
    }

    this.emit('badgeUnlocked', { playerId, badgeId, badge });
    console.log(`[PlayerBadges] Player ${playerId} unlocked badge: ${badgeId}`);

    return badge;
  }

  /**
   * Update badge progress
   */
  updateBadgeProgress(playerId: string, badgeId: string, progress: number): Badge | null {
    const playerBadges = this.playerBadges.get(playerId);
    if (!playerBadges) return null;

    const badge = playerBadges.badges.find((b) => b.id === badgeId);
    if (!badge || badge.unlockedAt) return null;

    const oldProgress = badge.progress || 0;
    badge.progress = Math.min(100, progress);

    // Auto-unlock if progress reaches 100
    if (badge.progress === 100 && oldProgress < 100) {
      return this.unlockBadge(playerId, badgeId);
    }

    this.emit('badgeProgressUpdated', { playerId, badgeId, progress: badge.progress });

    return badge;
  }

  /**
   * Get player badges
   */
  getPlayerBadges(playerId: string): PlayerBadges {
    if (!this.playerBadges.has(playerId)) {
      this.initializePlayerBadges(playerId);
    }

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

  /**
   * Get unlocked badges
   */
  getUnlockedBadges(playerId: string): Badge[] {
    const playerBadges = this.getPlayerBadges(playerId);
    return playerBadges.badges.filter((b) => b.unlockedAt);
  }

  /**
   * Get locked badges
   */
  getLockedBadges(playerId: string): Badge[] {
    const playerBadges = this.getPlayerBadges(playerId);
    return playerBadges.badges.filter((b) => !b.unlockedAt);
  }

  /**
   * Set showcase badges
   */
  setShowcaseBadges(playerId: string, badgeIds: string[]): void {
    const playerBadges = this.playerBadges.get(playerId);
    if (!playerBadges) return;

    // Only allow unlocked badges in showcase
    const validBadges = badgeIds.filter((id) => playerBadges.badges.find((b) => b.id === id && b.unlockedAt));

    playerBadges.showcase = validBadges.slice(0, 5); // Max 5 badges

    this.emit('showcaseBadgesUpdated', { playerId, badges: playerBadges.showcase });
  }

  /**
   * Get showcase badges
   */
  getShowcaseBadges(playerId: string): Badge[] {
    const playerBadges = this.getPlayerBadges(playerId);
    return playerBadges.showcase
      .map((id) => playerBadges.badges.find((b) => b.id === id))
      .filter((b) => b !== undefined) as Badge[];
  }

  /**
   * Get badge statistics
   */
  getBadgeStats(playerId: string) {
    const playerBadges = this.getPlayerBadges(playerId);
    const unlockedByType = playerBadges.badges
      .filter((b) => b.unlockedAt)
      .reduce(
        (acc, b) => {
          acc[b.type] = (acc[b.type] || 0) + 1;
          return acc;
        },
        {} as Record<BadgeType, number>
      );

    const unlockedByRarity = playerBadges.badges
      .filter((b) => b.unlockedAt)
      .reduce(
        (acc, b) => {
          acc[b.rarity] = (acc[b.rarity] || 0) + 1;
          return acc;
        },
        {} as Record<BadgeRarity, number>
      );

    return {
      playerId,
      totalBadges: playerBadges.totalBadges,
      unlockedBadges: playerBadges.unlockedBadges,
      completionPercentage: (playerBadges.unlockedBadges / playerBadges.totalBadges) * 100,
      unlockedByType,
      unlockedByRarity,
    };
  }

  /**
   * Get leaderboard by badges
   */
  getBadgeLeaderboard(limit: number = 100): Array<{ playerId: string; unlockedBadges: number; completionPercentage: number }> {
    const leaderboard = Array.from(this.playerBadges.values())
      .map((pb) => ({
        playerId: pb.playerId,
        unlockedBadges: pb.unlockedBadges,
        completionPercentage: (pb.unlockedBadges / pb.totalBadges) * 100,
      }))
      .sort((a, b) => b.unlockedBadges - a.unlockedBadges)
      .slice(0, limit);

    return leaderboard;
  }

  /**
   * Get recent unlocks
   */
  getRecentUnlocks(limit: number = 50) {
    return this.badgeUnlockHistory.slice(-limit).reverse();
  }

  /**
   * Clear all data
   */
  clear(): void {
    this.playerBadges.clear();
    this.badgeUnlockHistory = [];
    console.log('[PlayerBadges] System cleared');
  }
}

export const playerBadgesSystem = new PlayerBadgesSystem();
