import { EventEmitter } from 'events';

export interface GameTemplate {
  id: string;
  name: string;
  description: string;
  category: 'slots' | 'table' | 'arcade' | 'specialty';
  baseRTP: number;
  features: string[];
  paylines?: number;
  reels?: number;
  createdAt: Date;
}

export interface GameCreationRequest {
  id: string;
  name: string;
  description: string;
  category: 'slots' | 'table' | 'arcade' | 'specialty';
  templateId?: string;
  customization: {
    rtp: number;
    volatility: 'low' | 'medium' | 'high';
    minBet: number;
    maxBet: number;
    features: string[];
    bonusRounds: boolean;
    freeSpins: boolean;
    progressiveJackpot: boolean;
    multiplayer: boolean;
    theme?: string;
    colors?: string[];
    symbols?: string[];
  };
  aiSuggestions?: {
    enabled: boolean;
    theme?: string;
    mechanics?: string[];
    artStyle?: string;
  };
  createdBy: string;
  status: 'draft' | 'in_review' | 'approved' | 'published' | 'rejected';
  createdAt: Date;
  updatedAt: Date;
}

export interface GameDesignSuggestion {
  category: string;
  suggestions: string[];
  reasoning: string;
}

class GameCreatorSystem extends EventEmitter {
  private templates = new Map<string, GameTemplate>();
  private creationRequests = new Map<string, GameCreationRequest>();
  private designSuggestions = new Map<string, GameDesignSuggestion[]>();

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

  /**
   * Initialize default game templates
   */
  private initializeDefaultTemplates(): void {
    const defaultTemplates: GameTemplate[] = [
      {
        id: 'tpl_classic_slots',
        name: 'Classic Slots',
        description: 'Traditional 3-reel slot machine',
        category: 'slots',
        baseRTP: 96.5,
        features: ['simple', 'fast-paced', 'nostalgic'],
        reels: 3,
        paylines: 1,
        createdAt: new Date(),
      },
      {
        id: 'tpl_video_slots',
        name: 'Video Slots',
        description: '5-reel video slot with multiple paylines',
        category: 'slots',
        baseRTP: 96.0,
        features: ['bonus-rounds', 'free-spins', 'wild-symbols'],
        reels: 5,
        paylines: 25,
        createdAt: new Date(),
      },
      {
        id: 'tpl_progressive_slots',
        name: 'Progressive Slots',
        description: 'Slots with progressive jackpot',
        category: 'slots',
        baseRTP: 94.0,
        features: ['progressive-jackpot', 'high-volatility', 'big-wins'],
        reels: 5,
        paylines: 50,
        createdAt: new Date(),
      },
      {
        id: 'tpl_blackjack',
        name: 'Blackjack',
        description: 'Classic card game',
        category: 'table',
        baseRTP: 99.5,
        features: ['strategy', 'low-volatility', 'skill-based'],
        createdAt: new Date(),
      },
      {
        id: 'tpl_roulette',
        name: 'Roulette',
        description: 'European roulette game',
        category: 'table',
        baseRTP: 97.3,
        features: ['chance-based', 'simple', 'fast'],
        createdAt: new Date(),
      },
    ];

    defaultTemplates.forEach(t => this.templates.set(t.id, t));
  }

  /**
   * Get available templates
   */
  getTemplates(category?: string): GameTemplate[] {
    const templates = Array.from(this.templates.values());
    return category ? templates.filter(t => t.category === category) : templates;
  }

  /**
   * Create new game from template
   */
  createGameFromTemplate(
    templateId: string,
    gameData: Omit<GameCreationRequest, 'id' | 'status' | 'createdAt' | 'updatedAt' | 'templateId'>
  ): GameCreationRequest | null {
    const template = this.templates.get(templateId);
    if (!template) return null;

    const id = `game_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    const request: GameCreationRequest = {
      ...gameData,
      id,
      templateId,
      status: 'draft',
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    this.creationRequests.set(id, request);
    this.emit('game:created', request);
    return request;
  }

  /**
   * Create custom game
   */
  createCustomGame(
    gameData: Omit<GameCreationRequest, 'id' | 'status' | 'createdAt' | 'updatedAt' | 'templateId'>
  ): GameCreationRequest {
    const id = `game_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    const request: GameCreationRequest = {
      ...gameData,
      id,
      status: 'draft',
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    this.creationRequests.set(id, request);
    this.emit('game:created', request);
    return request;
  }

  /**
   * Update game creation request
   */
  updateGameRequest(gameId: string, updates: Partial<GameCreationRequest>): GameCreationRequest | null {
    const game = this.creationRequests.get(gameId);
    if (!game) return null;

    const updated: GameCreationRequest = {
      ...game,
      ...updates,
      updatedAt: new Date(),
    };

    this.creationRequests.set(gameId, updated);
    this.emit('game:updated', updated);
    return updated;
  }

  /**
   * Get game creation request
   */
  getGameRequest(gameId: string): GameCreationRequest | null {
    return this.creationRequests.get(gameId) || null;
  }

  /**
   * List game creation requests
   */
  listGameRequests(status?: string, createdBy?: string): GameCreationRequest[] {
    const requests = Array.from(this.creationRequests.values());
    return requests.filter(r => {
      if (status && r.status !== status) return false;
      if (createdBy && r.createdBy !== createdBy) return false;
      return true;
    });
  }

  /**
   * Submit game for review
   */
  submitForReview(gameId: string): GameCreationRequest | null {
    const game = this.getGameRequest(gameId);
    if (!game || game.status !== 'draft') return null;

    return this.updateGameRequest(gameId, { status: 'in_review' });
  }

  /**
   * Approve game
   */
  approveGame(gameId: string): GameCreationRequest | null {
    const game = this.getGameRequest(gameId);
    if (!game || game.status !== 'in_review') return null;

    return this.updateGameRequest(gameId, { status: 'approved' });
  }

  /**
   * Reject game
   */
  rejectGame(gameId: string, reason: string): GameCreationRequest | null {
    const game = this.getGameRequest(gameId);
    if (!game || game.status !== 'in_review') return null;

    return this.updateGameRequest(gameId, {
      status: 'rejected',
      customization: {
        ...game.customization,
      },
    });
  }

  /**
   * Publish game
   */
  publishGame(gameId: string): GameCreationRequest | null {
    const game = this.getGameRequest(gameId);
    if (!game || game.status !== 'approved') return null;

    const published = this.updateGameRequest(gameId, { status: 'published' });
    if (published) {
      this.emit('game:published', published);
    }
    return published;
  }

  /**
   * Get AI design suggestions
   */
  getDesignSuggestions(gameType: string): GameDesignSuggestion[] {
    const suggestions: GameDesignSuggestion[] = [
      {
        category: 'theme',
        suggestions: ['Egyptian', 'Asian', 'Retro', 'Fantasy', 'Nature', 'Space', 'Pirates', 'Western'],
        reasoning: 'Popular themes that resonate with players',
      },
      {
        category: 'mechanics',
        suggestions: ['Cascading Reels', 'Expanding Wilds', 'Sticky Symbols', 'Multiplier Trails', 'Bonus Spins'],
        reasoning: 'Proven game mechanics that increase engagement',
      },
      {
        category: 'art_style',
        suggestions: ['3D Cartoon', 'Realistic', 'Minimalist', 'Pixel Art', 'Comic Style'],
        reasoning: 'Visual styles that appeal to different player demographics',
      },
      {
        category: 'features',
        suggestions: ['Bonus Rounds', 'Free Spins', 'Multipliers', 'Scatter Symbols', 'Wild Symbols'],
        reasoning: 'Features that enhance player experience and retention',
      },
    ];

    return suggestions;
  }

  /**
   * Generate game recommendations based on player data
   */
  generateGameRecommendations(playerPreferences: {
    favoriteThemes: string[];
    preferredVolatility: 'low' | 'medium' | 'high';
    avgSessionLength: number;
    preferredFeatures: string[];
  }): GameDesignSuggestion[] {
    const recommendations: GameDesignSuggestion[] = [];

    // Theme recommendation
    recommendations.push({
      category: 'theme',
      suggestions: playerPreferences.favoriteThemes,
      reasoning: 'Based on your play history and preferences',
    });

    // Volatility recommendation
    const volatilityMap = {
      low: ['Classic Slots', 'Blackjack', 'Baccarat'],
      medium: ['Video Slots', 'Poker', 'Roulette'],
      high: ['Progressive Slots', 'Megaways', 'Extreme Volatility'],
    };

    recommendations.push({
      category: 'game_type',
      suggestions: volatilityMap[playerPreferences.preferredVolatility],
      reasoning: 'Matches your volatility preference',
    });

    // Feature recommendation
    recommendations.push({
      category: 'features',
      suggestions: playerPreferences.preferredFeatures,
      reasoning: 'Features you enjoy most',
    });

    return recommendations;
  }

  /**
   * Validate game configuration
   */
  validateGameConfig(config: GameCreationRequest['customization']): {
    valid: boolean;
    errors: string[];
    warnings: string[];
  } {
    const errors: string[] = [];
    const warnings: string[] = [];

    // RTP validation
    if (config.rtp < 85 || config.rtp > 99) {
      errors.push('RTP must be between 85% and 99%');
    }

    // Bet limits validation
    if (config.minBet >= config.maxBet) {
      errors.push('Min bet must be less than max bet');
    }

    if (config.minBet < 0.01) {
      warnings.push('Very low minimum bet may reduce revenue');
    }

    if (config.maxBet > 1000) {
      warnings.push('Very high maximum bet may attract problem gamblers');
    }

    // Feature validation
    if (config.features.length === 0) {
      warnings.push('Game has no special features - consider adding some');
    }

    // Volatility and RTP alignment
    if (config.volatility === 'high' && config.rtp > 97) {
      warnings.push('High volatility games typically have lower RTP');
    }

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

  /**
   * Clone existing game
   */
  cloneGame(gameId: string, newName: string, createdBy: string): GameCreationRequest | null {
    const original = this.getGameRequest(gameId);
    if (!original) return null;

    return this.createCustomGame({
      name: newName,
      description: `Clone of ${original.name}`,
      category: original.category,
      customization: { ...original.customization },
      createdBy,
    });
  }

  /**
   * Get game creation statistics
   */
  getCreationStats(): {
    totalGames: number;
    byStatus: Record<string, number>;
    byCategory: Record<string, number>;
    avgRTP: number;
    mostPopularFeatures: string[];
  } {
    const games = Array.from(this.creationRequests.values());

    const byStatus: Record<string, number> = {};
    const byCategory: Record<string, number> = {};
    const featureCount: Record<string, number> = {};
    let totalRTP = 0;

    games.forEach(g => {
      byStatus[g.status] = (byStatus[g.status] || 0) + 1;
      byCategory[g.category] = (byCategory[g.category] || 0) + 1;
      totalRTP += g.customization.rtp;

      g.customization.features.forEach(f => {
        featureCount[f] = (featureCount[f] || 0) + 1;
      });
    });

    const mostPopularFeatures = Object.entries(featureCount)
      .sort(([, a], [, b]) => b - a)
      .slice(0, 5)
      .map(([f]) => f);

    return {
      totalGames: games.length,
      byStatus,
      byCategory,
      avgRTP: games.length > 0 ? totalRTP / games.length : 0,
      mostPopularFeatures,
    };
  }

  /**
   * Export game configuration
   */
  exportGameConfig(gameId: string): string | null {
    const game = this.getGameRequest(gameId);
    if (!game) return null;

    return JSON.stringify(game, null, 2);
  }

  /**
   * Import game configuration
   */
  importGameConfig(jsonData: string, createdBy: string): GameCreationRequest | null {
    try {
      const config = JSON.parse(jsonData);
      return this.createCustomGame({
        name: config.name,
        description: config.description,
        category: config.category,
        customization: config.customization,
        aiSuggestions: config.aiSuggestions,
        createdBy,
      });
    } catch (error) {
      this.emit('error', { message: 'Failed to import game config', error });
      return null;
    }
  }
}

export const gameCreatorSystem = new GameCreatorSystem();
