import { db } from './db.ts';
import { games } from '../drizzle/schema.ts';
import { eq } from 'drizzle-orm';

export interface GameDeploymentConfig {
  gameId: string;
  name: string;
  description: string;
  rtp: number;
  volatility: 'low' | 'medium' | 'high';
  maxWin: number;
  minBet: number;
  maxBet: number;
  paylines: number;
  reelCount: number;
  symbolCount: number;
  bonusFeatures: string[];
  thumbnail: string;
  enabled: boolean;
}

/**
 * Slot Game Deployment System
 * Handles game publishing, configuration, and lifecycle management
 */
export class SlotGameDeployment {
  /**
   * Deploy a new game
   */
  static async deployGame(config: GameDeploymentConfig): Promise<void> {
    try {
      // Check if game already exists
      const existing = await db.query.games.findFirst({
        where: eq(games.id, config.gameId),
      });

      if (existing) {
        // Update existing game
        await db
          .update(games)
          .set({
            name: config.name,
            description: config.description,
            enabled: config.enabled,
            metadata: {
              rtp: config.rtp,
              volatility: config.volatility,
              maxWin: config.maxWin,
              minBet: config.minBet,
              maxBet: config.maxBet,
              paylines: config.paylines,
              reelCount: config.reelCount,
              symbolCount: config.symbolCount,
              bonusFeatures: config.bonusFeatures,
              deployedAt: new Date().toISOString(),
            },
          })
          .where(eq(games.id, config.gameId));
      } else {
        // Create new game
        await db.insert(games).values({
          id: config.gameId,
          name: config.name,
          description: config.description,
          enabled: config.enabled,
          thumbnail: config.thumbnail,
          metadata: {
            rtp: config.rtp,
            volatility: config.volatility,
            maxWin: config.maxWin,
            minBet: config.minBet,
            maxBet: config.maxBet,
            paylines: config.paylines,
            reelCount: config.reelCount,
            symbolCount: config.symbolCount,
            bonusFeatures: config.bonusFeatures,
            deployedAt: new Date().toISOString(),
          },
        });
      }

      console.log(`[Game Deployment] Game ${config.gameId} deployed successfully`);
    } catch (error) {
      console.error(`[Game Deployment] Failed to deploy game ${config.gameId}:`, error);
      throw error;
    }
  }

  /**
   * Enable/disable game
   */
  static async setGameStatus(gameId: string, enabled: boolean): Promise<void> {
    await db.update(games).set({ enabled }).where(eq(games.id, gameId));
    console.log(`[Game Deployment] Game ${gameId} ${enabled ? 'enabled' : 'disabled'}`);
  }

  /**
   * Update game configuration
   */
  static async updateGameConfig(gameId: string, config: Partial<GameDeploymentConfig>): Promise<void> {
    const game = await db.query.games.findFirst({
      where: eq(games.id, gameId),
    });

    if (!game) {
      throw new Error(`Game ${gameId} not found`);
    }

    const metadata = game.metadata || {};

    await db
      .update(games)
      .set({
        name: config.name || game.name,
        description: config.description || game.description,
        metadata: {
          ...metadata,
          rtp: config.rtp || metadata.rtp,
          volatility: config.volatility || metadata.volatility,
          maxWin: config.maxWin || metadata.maxWin,
          minBet: config.minBet || metadata.minBet,
          maxBet: config.maxBet || metadata.maxBet,
          paylines: config.paylines || metadata.paylines,
          reelCount: config.reelCount || metadata.reelCount,
          symbolCount: config.symbolCount || metadata.symbolCount,
          bonusFeatures: config.bonusFeatures || metadata.bonusFeatures,
          updatedAt: new Date().toISOString(),
        },
      })
      .where(eq(games.id, gameId));

    console.log(`[Game Deployment] Game ${gameId} configuration updated`);
  }

  /**
   * Get game deployment status
   */
  static async getGameStatus(gameId: string) {
    const game = await db.query.games.findFirst({
      where: eq(games.id, gameId),
    });

    if (!game) {
      return null;
    }

    return {
      gameId: game.id,
      name: game.name,
      enabled: game.enabled,
      deployed: !!game.metadata?.deployedAt,
      deployedAt: game.metadata?.deployedAt,
      rtp: game.metadata?.rtp || 96.5,
      volatility: game.metadata?.volatility || 'medium',
      totalPlays: 0,
      totalRevenue: 0,
      avgBet: 0,
      avgWin: 0,
    };
  }

  /**
   * Deploy preset games
   */
  static async deployPresetGames(): Promise<void> {
    const presetGames: GameDeploymentConfig[] = [
      {
        gameId: 'classic-slots',
        name: 'Classic Slots',
        description: '3-reel classic slot machine with traditional symbols',
        rtp: 96.5,
        volatility: 'low',
        maxWin: 100,
        minBet: 0.1,
        maxBet: 100,
        paylines: 1,
        reelCount: 3,
        symbolCount: 6,
        bonusFeatures: ['wild', 'scatter'],
        thumbnail: '/games/classic-slots.png',
        enabled: true,
      },
      {
        gameId: 'neon-nights',
        name: 'Neon Nights',
        description: 'Cascading reels with multipliers and bonus rounds',
        rtp: 96.5,
        volatility: 'high',
        maxWin: 500,
        minBet: 0.1,
        maxBet: 100,
        paylines: 5,
        reelCount: 5,
        symbolCount: 8,
        bonusFeatures: ['cascading', 'multiplier', 'free_spins'],
        thumbnail: '/games/neon-nights.png',
        enabled: true,
      },
      {
        gameId: 'crystal-dreams',
        name: 'Crystal Dreams',
        description: 'Magical crystals with expanding wilds and bonus features',
        rtp: 95.8,
        volatility: 'medium',
        maxWin: 250,
        minBet: 0.1,
        maxBet: 100,
        paylines: 10,
        reelCount: 5,
        symbolCount: 7,
        bonusFeatures: ['expanding_wild', 'free_spins', 'bonus_game'],
        thumbnail: '/games/crystal-dreams.png',
        enabled: true,
      },
      {
        gameId: 'golden-rush',
        name: 'Golden Rush',
        description: 'Gold rush themed megaways slot with huge win potential',
        rtp: 97.2,
        volatility: 'high',
        maxWin: 1000,
        minBet: 0.1,
        maxBet: 100,
        paylines: 117649,
        reelCount: 6,
        symbolCount: 8,
        bonusFeatures: ['megaways', 'cascading', 'bonus_buy'],
        thumbnail: '/games/golden-rush.png',
        enabled: true,
      },
      {
        gameId: 'cosmic-spin',
        name: 'Cosmic Spin',
        description: 'Space-themed slot with hold & spin mechanics',
        rtp: 95.5,
        volatility: 'medium',
        maxWin: 300,
        minBet: 0.1,
        maxBet: 100,
        paylines: 25,
        reelCount: 5,
        symbolCount: 7,
        bonusFeatures: ['hold_spin', 'sticky_wilds', 'bonus_spins'],
        thumbnail: '/games/cosmic-spin.png',
        enabled: true,
      },
    ];

    for (const gameConfig of presetGames) {
      try {
        await this.deployGame(gameConfig);
      } catch (error) {
        console.error(`Failed to deploy preset game ${gameConfig.gameId}:`, error);
      }
    }

    console.log('[Game Deployment] All preset games deployed');
  }

  /**
   * Get all deployed games
   */
  static async getAllDeployedGames() {
    const allGames = await db.query.games.findMany();
    return allGames.map((game) => ({
      id: game.id,
      name: game.name,
      enabled: game.enabled,
      rtp: game.metadata?.rtp || 96.5,
      volatility: game.metadata?.volatility || 'medium',
      maxWin: game.metadata?.maxWin || 100,
    }));
  }

  /**
   * Validate game configuration
   */
  static validateConfig(config: GameDeploymentConfig): { valid: boolean; errors: string[] } {
    const errors: string[] = [];

    if (!config.gameId) errors.push('Game ID is required');
    if (!config.name) errors.push('Game name is required');
    if (config.rtp < 90 || config.rtp > 99) errors.push('RTP must be between 90 and 99');
    if (config.maxWin < 1) errors.push('Max win must be at least 1');
    if (config.minBet <= 0) errors.push('Min bet must be greater than 0');
    if (config.maxBet <= config.minBet) errors.push('Max bet must be greater than min bet');
    if (config.paylines < 1) errors.push('Paylines must be at least 1');
    if (config.reelCount < 3) errors.push('Reel count must be at least 3');
    if (config.symbolCount < 5) errors.push('Symbol count must be at least 5');

    return {
      valid: errors.length === 0,
      errors,
    };
  }
}

export default SlotGameDeployment;
