import { gameEventSystem, GameEvent } from './gameEventSystem';
import { milestoneDetectionSystem } from './milestoneDetectionSystem';
import { achievementUnlockSystem } from './achievementUnlockSystem';
import { EventEmitter } from 'events';

export interface MilestoneUnlockResult {
  achieved: boolean;
  milestone?: {
    type: string;
    value: number;
    reward: { coins?: number; xp?: number };
  };
  achievement?: {
    id: string;
    name: string;
    icon: string;
  };
}

class GameEngineHooks extends EventEmitter {
  private userLevelMap: Map<string, number> = new Map();
  private userWinMap: Map<string, number> = new Map();
  private userScoreMap: Map<string, number> = new Map();
  private userStreakMap: Map<string, number> = new Map();

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

  /**
   * Setup listeners for game events
   */
  private setupGameEventListeners(): void {
    // Listen for spin completion
    gameEventSystem.onGameEvent('spin-completed', (event: GameEvent) => {
      this.handleSpinCompleted(event);
    });

    // Listen for win detection
    gameEventSystem.onGameEvent('win-detected', (event: GameEvent) => {
      this.handleWinDetected(event);
    });

    // Listen for score updates
    gameEventSystem.onGameEvent('score-updated', (event: GameEvent) => {
      this.handleScoreUpdated(event);
    });

    // Listen for level gains
    gameEventSystem.onGameEvent('level-gained', (event: GameEvent) => {
      this.handleLevelGained(event);
    });

    // Listen for streak updates
    gameEventSystem.onGameEvent('streak-updated', (event: GameEvent) => {
      this.handleStreakUpdated(event);
    });
  }

  /**
   * Handle spin completion - check win milestones
   */
  private handleSpinCompleted(event: GameEvent): void {
    const { userId } = event;

    // Increment win count if there was a win
    if (event.data.winAmount && event.data.winAmount > 0) {
      const currentWins = this.userWinMap.get(userId) || 0;
      const newWins = currentWins + 1;
      this.userWinMap.set(userId, newWins);

      // Check for win milestone
      const milestone = milestoneDetectionSystem.checkWinMilestone(userId, newWins, currentWins);
      if (milestone) {
        this.handleMilestoneUnlock(userId, milestone);
      }
    }

    this.emit('spin-completed', { userId, event });
  }

  /**
   * Handle win detection - check score milestones
   */
  private handleWinDetected(event: GameEvent): void {
    const { userId, data } = event;

    if (data.scoreGained) {
      const currentScore = this.userScoreMap.get(userId) || 0;
      const newScore = currentScore + data.scoreGained;
      this.userScoreMap.set(userId, newScore);

      // Check for score milestone
      const milestone = milestoneDetectionSystem.checkScoreMilestone(userId, newScore, currentScore);
      if (milestone) {
        this.handleMilestoneUnlock(userId, milestone);
      }
    }

    this.emit('win-detected', { userId, event });
  }

  /**
   * Handle score update
   */
  private handleScoreUpdated(event: GameEvent): void {
    const { userId, data } = event;

    if (data.newScore !== undefined) {
      const previousScore = data.previousScore || 0;
      this.userScoreMap.set(userId, data.newScore);

      // Check for score milestone
      const milestone = milestoneDetectionSystem.checkScoreMilestone(userId, data.newScore, previousScore);
      if (milestone) {
        this.handleMilestoneUnlock(userId, milestone);
      }
    }

    this.emit('score-updated', { userId, event });
  }

  /**
   * Handle level gained - check level milestones
   */
  private handleLevelGained(event: GameEvent): void {
    const { userId, data } = event;

    if (data.newLevel !== undefined) {
      const previousLevel = data.previousLevel || 0;
      this.userLevelMap.set(userId, data.newLevel);

      // Check for level milestone
      const milestone = milestoneDetectionSystem.checkLevelMilestone(userId, data.newLevel, previousLevel);
      if (milestone) {
        this.handleMilestoneUnlock(userId, milestone);
      }
    }

    this.emit('level-gained', { userId, event });
  }

  /**
   * Handle streak update - check streak milestones
   */
  private handleStreakUpdated(event: GameEvent): void {
    const { userId, data } = event;

    if (data.newStreak !== undefined) {
      const previousStreak = data.previousStreak || 0;
      this.userStreakMap.set(userId, data.newStreak);

      // Check for streak milestone
      const milestone = milestoneDetectionSystem.checkStreakMilestone(userId, data.newStreak, previousStreak);
      if (milestone) {
        this.handleMilestoneUnlock(userId, milestone);
      }
    }

    this.emit('streak-updated', { userId, event });
  }

  /**
   * Handle milestone unlock
   */
  private handleMilestoneUnlock(userId: string, milestone: any): MilestoneUnlockResult {
    const result: MilestoneUnlockResult = {
      achieved: true,
      milestone: {
        type: milestone.milestone.type,
        value: milestone.milestone.value,
        reward: milestone.milestone.reward || {},
      },
    };

    // Record achievement if mapped
    if (milestone.milestone.achievementId) {
      const achievement = achievementUnlockSystem.recordUnlock(userId, {
        id: milestone.milestone.achievementId,
        name: `${milestone.milestone.type.charAt(0).toUpperCase() + milestone.milestone.type.slice(1)} ${milestone.milestone.value}`,
        description: `Reached ${milestone.milestone.type} ${milestone.milestone.value}`,
        icon: this.getAchievementIcon(milestone.milestone.type),
        rarity: this.getAchievementRarity(milestone.milestone.value),
        reward: milestone.milestone.reward,
      });

      result.achievement = {
        id: achievement.achievement.id,
        name: achievement.achievement.name,
        icon: achievement.achievement.icon,
      };
    }

    this.emit('milestone-unlocked', {
      userId,
      milestone: result.milestone,
      achievement: result.achievement,
      timestamp: new Date(),
    });

    return result;
  }

  /**
   * Get achievement icon based on milestone type
   */
  private getAchievementIcon(type: string): string {
    const icons: Record<string, string> = {
      level: '📈',
      wins: '🏆',
      score: '⭐',
      streak: '🔥',
    };
    return icons[type] || '🎖️';
  }

  /**
   * Get achievement rarity based on milestone value
   */
  private getAchievementRarity(value: number): 'common' | 'rare' | 'epic' | 'legendary' {
    if (value >= 100) return 'legendary';
    if (value >= 50) return 'epic';
    if (value >= 25) return 'rare';
    return 'common';
  }

  /**
   * Set user level
   */
  setUserLevel(userId: string, level: number): void {
    this.userLevelMap.set(userId, level);
  }

  /**
   * Set user wins
   */
  setUserWins(userId: string, wins: number): void {
    this.userWinMap.set(userId, wins);
  }

  /**
   * Set user score
   */
  setUserScore(userId: string, score: number): void {
    this.userScoreMap.set(userId, score);
  }

  /**
   * Set user streak
   */
  setUserStreak(userId: string, streak: number): void {
    this.userStreakMap.set(userId, streak);
  }

  /**
   * Get user level
   */
  getUserLevel(userId: string): number {
    return this.userLevelMap.get(userId) || 0;
  }

  /**
   * Get user wins
   */
  getUserWins(userId: string): number {
    return this.userWinMap.get(userId) || 0;
  }

  /**
   * Get user score
   */
  getUserScore(userId: string): number {
    return this.userScoreMap.get(userId) || 0;
  }

  /**
   * Get user streak
   */
  getUserStreak(userId: string): number {
    return this.userStreakMap.get(userId) || 0;
  }

  /**
   * Get all user stats
   */
  getUserStats(userId: string): {
    level: number;
    wins: number;
    score: number;
    streak: number;
  } {
    return {
      level: this.getUserLevel(userId),
      wins: this.getUserWins(userId),
      score: this.getUserScore(userId),
      streak: this.getUserStreak(userId),
    };
  }

  /**
   * Clear all data (for testing)
   */
  clear(): void {
    this.userLevelMap.clear();
    this.userWinMap.clear();
    this.userScoreMap.clear();
    this.userStreakMap.clear();
  }
}

export const gameEngineHooks = new GameEngineHooks();
