import { gameEventSystem, GameEvent } from './gameEventSystem';
import { gameEngineHooks } from './gameEngineHooks';
import { db } from './db.ts';

export interface SpinResult {
  spinId: string;
  userId: string;
  gameId: string;
  betAmount: number;
  winAmount: number;
  multiplier: number;
  lineWins: number;
  bonusTriggered: boolean;
  finalScore: number;
  previousScore: number;
}

export interface GameSessionData {
  userId: string;
  gameId: string;
  sessionId: string;
  startTime: Date;
}

/**
 * Adapter for integrating slot game events into the engagement system
 */
export class SlotGameEventAdapter {
  private activeSessions: Map<string, GameSessionData> = new Map();

  /**
   * Start a game session
   */
  startGameSession(userId: string, gameId: string): GameSessionData {
    const session = gameEventSystem.startSession(userId, gameId);

    const sessionData: GameSessionData = {
      userId,
      gameId,
      sessionId: session.sessionId,
      startTime: session.startTime,
    };

    this.activeSessions.set(session.sessionId, sessionData);

    console.log(`[GameEventAdapter] Session started: ${session.sessionId} for user ${userId} in game ${gameId}`);

    return sessionData;
  }

  /**
   * End a game session
   */
  endGameSession(sessionId: string): void {
    const session = gameEventSystem.endSession(sessionId);
    if (session) {
      this.activeSessions.delete(sessionId);
      console.log(`[GameEventAdapter] Session ended: ${sessionId}`);
    }
  }

  /**
   * Record a spin completion event
   */
  recordSpinCompletion(result: SpinResult): void {
    try {
      const event: GameEvent = {
        userId: result.userId,
        gameId: result.gameId,
        eventType: 'spin-completed',
        timestamp: new Date(),
        data: {
          spinId: result.spinId,
          winAmount: result.winAmount,
          betAmount: result.betAmount,
          multiplier: result.multiplier,
          lineWins: result.lineWins,
          bonusTriggered: result.bonusTriggered,
          metadata: {
            spinResult: 'completed',
            timestamp: Date.now(),
          },
        },
      };

      gameEventSystem.recordEvent(event);

      // If there was a win, record win event
      if (result.winAmount > 0) {
        this.recordWinDetected(result);
      }

      console.log(`[GameEventAdapter] Spin recorded: ${result.spinId} for user ${result.userId}`);
    } catch (err) {
      console.error(`[GameEventAdapter] Error recording spin:`, err);
    }
  }

  /**
   * Record a win detection event
   */
  private recordWinDetected(result: SpinResult): void {
    try {
      const event: GameEvent = {
        userId: result.userId,
        gameId: result.gameId,
        eventType: 'win-detected',
        timestamp: new Date(),
        data: {
          winAmount: result.winAmount,
          scoreGained: result.winAmount,
          newScore: result.finalScore,
          previousScore: result.previousScore,
          multiplier: result.multiplier,
          lineWins: result.lineWins,
          bonusTriggered: result.bonusTriggered,
        },
      };

      gameEventSystem.recordEvent(event);

      console.log(`[GameEventAdapter] Win detected: ${result.winAmount} for user ${result.userId}`);
    } catch (err) {
      console.error(`[GameEventAdapter] Error recording win:`, err);
    }
  }

  /**
   * Record a score update event
   */
  recordScoreUpdate(userId: string, gameId: string, newScore: number, previousScore: number): void {
    try {
      const event: GameEvent = {
        userId,
        gameId,
        eventType: 'score-updated',
        timestamp: new Date(),
        data: {
          newScore,
          previousScore,
          scoreGained: newScore - previousScore,
        },
      };

      gameEventSystem.recordEvent(event);

      console.log(`[GameEventAdapter] Score updated: ${previousScore} -> ${newScore} for user ${userId}`);
    } catch (err) {
      console.error(`[GameEventAdapter] Error recording score update:`, err);
    }
  }

  /**
   * Record a level gain event
   */
  recordLevelGain(userId: string, gameId: string, newLevel: number, previousLevel: number): void {
    try {
      const event: GameEvent = {
        userId,
        gameId,
        eventType: 'level-gained',
        timestamp: new Date(),
        data: {
          newLevel,
          previousLevel,
        },
      };

      gameEventSystem.recordEvent(event);

      // Update game engine hooks
      gameEngineHooks.setUserLevel(userId, newLevel);

      console.log(`[GameEventAdapter] Level gained: ${previousLevel} -> ${newLevel} for user ${userId}`);
    } catch (err) {
      console.error(`[GameEventAdapter] Error recording level gain:`, err);
    }
  }

  /**
   * Record a streak update event
   */
  recordStreakUpdate(userId: string, gameId: string, newStreak: number, previousStreak: number): void {
    try {
      const event: GameEvent = {
        userId,
        gameId,
        eventType: 'streak-updated',
        timestamp: new Date(),
        data: {
          newStreak,
          previousStreak,
        },
      };

      gameEventSystem.recordEvent(event);

      // Update game engine hooks
      gameEngineHooks.setUserStreak(userId, newStreak);

      console.log(`[GameEventAdapter] Streak updated: ${previousStreak} -> ${newStreak} for user ${userId}`);
    } catch (err) {
      console.error(`[GameEventAdapter] Error recording streak update:`, err);
    }
  }

  /**
   * Get session stats
   */
  getSessionStats(sessionId: string) {
    const session = gameEventSystem.getSession(sessionId);
    if (!session) return null;

    return gameEventSystem.getSessionStats(sessionId);
  }

  /**
   * Get user game stats
   */
  getUserGameStats(userId: string) {
    return gameEventSystem.getUserStats(userId);
  }

  /**
   * Get recent user events
   */
  getRecentUserEvents(userId: string, limit: number = 50) {
    return gameEventSystem.getRecentEvents(userId, limit);
  }

  /**
   * Get game-specific events
   */
  getGameEvents(userId: string, gameId: string, limit: number = 50) {
    return gameEventSystem.getGameEvents(userId, gameId, limit);
  }

  /**
   * Get global game stats
   */
  getGlobalGameStats() {
    return gameEventSystem.getGlobalStats();
  }

  /**
   * Get game-specific stats
   */
  getGameStats(gameId: string) {
    return gameEventSystem.getGameStats(gameId);
  }

  /**
   * Batch record multiple spin results
   */
  recordSpinBatch(results: SpinResult[]): void {
    for (const result of results) {
      this.recordSpinCompletion(result);
    }
  }

  /**
   * Clear all sessions (for testing)
   */
  clearSessions(): void {
    this.activeSessions.clear();
    gameEventSystem.clear();
  }
}

export const slotGameEventAdapter = new SlotGameEventAdapter();
