import { TRPCError } from '@trpc/server';
import { slotGameEventAdapter } from './slotGameEventAdapter';
import { gameEngineHooks } from './gameEngineHooks';

/**
 * Middleware for recording game events in tRPC procedures
 */
export const gameEventMiddleware = {
  /**
   * Record a spin completion
   */
  recordSpin: async (userId: string, gameId: string, spinData: any) => {
    try {
      slotGameEventAdapter.recordSpinCompletion({
        spinId: spinData.spinId || `spin-${Date.now()}`,
        userId,
        gameId,
        betAmount: spinData.betAmount || 0,
        winAmount: spinData.winAmount || 0,
        multiplier: spinData.multiplier || 1,
        lineWins: spinData.lineWins || 0,
        bonusTriggered: spinData.bonusTriggered || false,
        finalScore: spinData.finalScore || 0,
        previousScore: spinData.previousScore || 0,
      });

      return { success: true, message: 'Spin recorded' };
    } catch (err) {
      console.error('[GameEventMiddleware] Error recording spin:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to record game event',
      });
    }
  },

  /**
   * Record a level gain
   */
  recordLevelGain: async (userId: string, gameId: string, newLevel: number, previousLevel: number) => {
    try {
      slotGameEventAdapter.recordLevelGain(userId, gameId, newLevel, previousLevel);
      return { success: true, message: 'Level gain recorded' };
    } catch (err) {
      console.error('[GameEventMiddleware] Error recording level gain:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to record level gain',
      });
    }
  },

  /**
   * Record a score update
   */
  recordScoreUpdate: async (userId: string, gameId: string, newScore: number, previousScore: number) => {
    try {
      slotGameEventAdapter.recordScoreUpdate(userId, gameId, newScore, previousScore);
      return { success: true, message: 'Score update recorded' };
    } catch (err) {
      console.error('[GameEventMiddleware] Error recording score update:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to record score update',
      });
    }
  },

  /**
   * Record a streak update
   */
  recordStreakUpdate: async (userId: string, gameId: string, newStreak: number, previousStreak: number) => {
    try {
      slotGameEventAdapter.recordStreakUpdate(userId, gameId, newStreak, previousStreak);
      return { success: true, message: 'Streak update recorded' };
    } catch (err) {
      console.error('[GameEventMiddleware] Error recording streak update:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to record streak update',
      });
    }
  },

  /**
   * Get user game stats
   */
  getUserStats: async (userId: string) => {
    try {
      const stats = slotGameEventAdapter.getUserGameStats(userId);
      return stats || { totalSpins: 0, totalWins: 0, totalScore: 0 };
    } catch (err) {
      console.error('[GameEventMiddleware] Error getting user stats:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to get user stats',
      });
    }
  },

  /**
   * Get recent events
   */
  getRecentEvents: async (userId: string, limit: number = 50) => {
    try {
      return slotGameEventAdapter.getRecentUserEvents(userId, limit);
    } catch (err) {
      console.error('[GameEventMiddleware] Error getting recent events:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to get recent events',
      });
    }
  },

  /**
   * Get game-specific events
   */
  getGameEvents: async (userId: string, gameId: string, limit: number = 50) => {
    try {
      return slotGameEventAdapter.getGameEvents(userId, gameId, limit);
    } catch (err) {
      console.error('[GameEventMiddleware] Error getting game events:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to get game events',
      });
    }
  },

  /**
   * Get global game stats
   */
  getGlobalStats: async () => {
    try {
      return slotGameEventAdapter.getGlobalGameStats();
    } catch (err) {
      console.error('[GameEventMiddleware] Error getting global stats:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to get global stats',
      });
    }
  },

  /**
   * Get game-specific stats
   */
  getGameStats: async (gameId: string) => {
    try {
      return slotGameEventAdapter.getGameStats(gameId);
    } catch (err) {
      console.error('[GameEventMiddleware] Error getting game stats:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to get game stats',
      });
    }
  },

  /**
   * Start a game session
   */
  startSession: async (userId: string, gameId: string) => {
    try {
      const session = slotGameEventAdapter.startGameSession(userId, gameId);
      return {
        sessionId: session.sessionId,
        startTime: session.startTime,
      };
    } catch (err) {
      console.error('[GameEventMiddleware] Error starting session:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to start game session',
      });
    }
  },

  /**
   * End a game session
   */
  endSession: async (sessionId: string) => {
    try {
      slotGameEventAdapter.endGameSession(sessionId);
      return { success: true, message: 'Session ended' };
    } catch (err) {
      console.error('[GameEventMiddleware] Error ending session:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to end game session',
      });
    }
  },

  /**
   * Batch record spins
   */
  recordSpinBatch: async (userId: string, gameId: string, spins: any[]) => {
    try {
      const spinResults = spins.map((spin) => ({
        spinId: spin.spinId || `spin-${Date.now()}-${Math.random()}`,
        userId,
        gameId,
        betAmount: spin.betAmount || 0,
        winAmount: spin.winAmount || 0,
        multiplier: spin.multiplier || 1,
        lineWins: spin.lineWins || 0,
        bonusTriggered: spin.bonusTriggered || false,
        finalScore: spin.finalScore || 0,
        previousScore: spin.previousScore || 0,
      }));

      slotGameEventAdapter.recordSpinBatch(spinResults);

      return {
        success: true,
        message: `Recorded ${spinResults.length} spins`,
        count: spinResults.length,
      };
    } catch (err) {
      console.error('[GameEventMiddleware] Error recording spin batch:', err);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to record spin batch',
      });
    }
  },
};
