import { EventEmitter } from 'events';

export interface GameTemplate {
  id: string;
  name: string;
  genre: 'slot' | 'table' | 'card' | 'arcade' | 'puzzle' | 'skill';
  description: string;
  baseCode: string;
  baseConfig: Record<string, any>;
  mechanics: string[];
  features: string[];
  theme: {
    colors: Record<string, string>;
    fonts: string[];
    assets: string[];
  };
  documentation: string;
  exampleGames: string[];
  version: string;
  createdAt: Date;
  updatedAt: Date;
  downloads: number;
  rating: number;
  reviews: number;
}

export interface TemplateVariant {
  id: string;
  templateId: string;
  name: string;
  description: string;
  config: Record<string, any>;
  theme: Record<string, any>;
  createdAt: Date;
  updatedAt: Date;
}

export interface TemplatePerformance {
  templateId: string;
  totalGamesCreated: number;
  totalPlays: number;
  totalWagers: number;
  totalPayouts: number;
  averageRTP: number;
  averageEngagementScore: number;
  playerRetention: number;
  revenue: number;
}

class GameTemplateLibraryService extends EventEmitter {
  private templates: Map<string, GameTemplate> = new Map();
  private variants: Map<string, TemplateVariant[]> = new Map();
  private performance: Map<string, TemplatePerformance> = new Map();

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

  /**
   * Initialize default templates
   */
  private initializeDefaultTemplates(): void {
    // Slot Game Template
    const slotTemplate: GameTemplate = {
      id: 'template-slot-001',
      name: 'Classic Slot Machine',
      genre: 'slot',
      description: 'Traditional 3-reel slot machine with classic mechanics',
      baseCode: `
        class SlotGame {
          constructor(config) {
            this.reels = config.reels || 3;
            this.symbols = config.symbols || [];
            this.paylines = config.paylines || 1;
            this.rtp = config.rtp || 95;
          }
          
          spin() {
            // Spin logic
            return this.generateResult();
          }
          
          generateResult() {
            // RNG logic
          }
        }
      `,
      baseConfig: {
        reels: 3,
        rows: 3,
        paylines: 5,
        minBet: 0.1,
        maxBet: 100,
        rtp: 95,
        volatility: 'medium',
      },
      mechanics: ['spinning reels', 'paylines', 'wild symbols', 'scatter symbols'],
      features: ['free spins', 'multipliers', 'bonus rounds'],
      theme: {
        colors: {
          primary: '#FF6B6B',
          secondary: '#4ECDC4',
          background: '#1A1A2E',
        },
        fonts: ['Arial', 'Helvetica'],
        assets: ['reel-symbols', 'animations', 'sounds'],
      },
      documentation: 'Classic slot machine template with 3 reels and 5 paylines',
      exampleGames: ['Crystal Cascade', 'Neon Nights'],
      version: '1.0.0',
      createdAt: new Date(),
      updatedAt: new Date(),
      downloads: 0,
      rating: 4.8,
      reviews: 125,
    };

    // Table Game Template
    const tableTemplate: GameTemplate = {
      id: 'template-table-001',
      name: 'Blackjack',
      genre: 'table',
      description: 'Classic blackjack card game',
      baseCode: `
        class BlackjackGame {
          constructor(config) {
            this.deck = [];
            this.playerHand = [];
            this.dealerHand = [];
          }
          
          deal() {
            // Deal cards
          }
          
          calculateScore(hand) {
            // Calculate hand value
          }
        }
      `,
      baseConfig: {
        decks: 6,
        minBet: 1,
        maxBet: 500,
        rtp: 99.5,
      },
      mechanics: ['card dealing', 'hand evaluation', 'betting'],
      features: ['insurance', 'split', 'double down'],
      theme: {
        colors: {
          primary: '#2ECC71',
          secondary: '#FFFFFF',
          background: '#27AE60',
        },
        fonts: ['Arial'],
        assets: ['card-deck', 'chips', 'table'],
      },
      documentation: 'Professional blackjack game template',
      exampleGames: [],
      version: '1.0.0',
      createdAt: new Date(),
      updatedAt: new Date(),
      downloads: 0,
      rating: 4.9,
      reviews: 89,
    };

    // Arcade Game Template
    const arcadeTemplate: GameTemplate = {
      id: 'template-arcade-001',
      name: 'Arcade Action',
      genre: 'arcade',
      description: 'Fast-paced arcade action game',
      baseCode: `
        class ArcadeGame {
          constructor(config) {
            this.score = 0;
            this.level = 1;
            this.lives = config.lives || 3;
          }
          
          update() {
            // Game loop
          }
          
          render() {
            // Render game
          }
        }
      `,
      baseConfig: {
        lives: 3,
        difficulty: 'medium',
        scoreMultiplier: 1,
      },
      mechanics: ['scoring', 'levels', 'power-ups'],
      features: ['high scores', 'achievements', 'leaderboards'],
      theme: {
        colors: {
          primary: '#FF00FF',
          secondary: '#00FFFF',
          background: '#000000',
        },
        fonts: ['Arial', 'Courier'],
        assets: ['sprites', 'effects', 'music'],
      },
      documentation: 'Retro-style arcade game template',
      exampleGames: [],
      version: '1.0.0',
      createdAt: new Date(),
      updatedAt: new Date(),
      downloads: 0,
      rating: 4.6,
      reviews: 56,
    };

    this.templates.set(slotTemplate.id, slotTemplate);
    this.templates.set(tableTemplate.id, tableTemplate);
    this.templates.set(arcadeTemplate.id, arcadeTemplate);
  }

  /**
   * Get template
   */
  getTemplate(templateId: string): GameTemplate | null {
    return this.templates.get(templateId) || null;
  }

  /**
   * Get all templates
   */
  getAllTemplates(): GameTemplate[] {
    return Array.from(this.templates.values());
  }

  /**
   * Get templates by genre
   */
  getTemplatesByGenre(genre: string): GameTemplate[] {
    return Array.from(this.templates.values()).filter((t) => t.genre === genre);
  }

  /**
   * Create template variant
   */
  createVariant(
    templateId: string,
    name: string,
    description: string,
    config: Record<string, any>,
    theme: Record<string, any>
  ): TemplateVariant {
    const variant: TemplateVariant = {
      id: `variant-${Date.now()}`,
      templateId,
      name,
      description,
      config,
      theme,
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    const variants = this.variants.get(templateId) || [];
    variants.push(variant);
    this.variants.set(templateId, variants);

    this.emit('variant_created', variant);

    return variant;
  }

  /**
   * Get template variants
   */
  getTemplateVariants(templateId: string): TemplateVariant[] {
    return this.variants.get(templateId) || [];
  }

  /**
   * Get variant
   */
  getVariant(variantId: string): TemplateVariant | null {
    for (const variants of this.variants.values()) {
      const variant = variants.find((v) => v.id === variantId);
      if (variant) {
        return variant;
      }
    }
    return null;
  }

  /**
   * Update template performance
   */
  updateTemplatePerformance(
    templateId: string,
    metrics: {
      gamesCreated?: number;
      plays?: number;
      wagers?: number;
      payouts?: number;
      engagementScore?: number;
      retention?: number;
      revenue?: number;
    }
  ): TemplatePerformance {
    let performance = this.performance.get(templateId) || {
      templateId,
      totalGamesCreated: 0,
      totalPlays: 0,
      totalWagers: 0,
      totalPayouts: 0,
      averageRTP: 95,
      averageEngagementScore: 0,
      playerRetention: 0,
      revenue: 0,
    };

    if (metrics.gamesCreated) performance.totalGamesCreated += metrics.gamesCreated;
    if (metrics.plays) performance.totalPlays += metrics.plays;
    if (metrics.wagers) performance.totalWagers += metrics.wagers;
    if (metrics.payouts) performance.totalPayouts += metrics.payouts;
    if (metrics.engagementScore) performance.averageEngagementScore = metrics.engagementScore;
    if (metrics.retention) performance.playerRetention = metrics.retention;
    if (metrics.revenue) performance.revenue += metrics.revenue;

    this.performance.set(templateId, performance);
    this.emit('performance_updated', performance);

    return performance;
  }

  /**
   * Get template performance
   */
  getTemplatePerformance(templateId: string): TemplatePerformance | null {
    return this.performance.get(templateId) || null;
  }

  /**
   * Get top templates
   */
  getTopTemplates(limit: number = 10): GameTemplate[] {
    return Array.from(this.templates.values())
      .sort((a, b) => b.rating - a.rating)
      .slice(0, limit);
  }

  /**
   * Get trending templates
   */
  getTrendingTemplates(limit: number = 5): GameTemplate[] {
    return Array.from(this.templates.values())
      .sort((a, b) => b.downloads - a.downloads)
      .slice(0, limit);
  }

  /**
   * Update template rating
   */
  updateTemplateRating(templateId: string, rating: number, review: string): GameTemplate | null {
    const template = this.templates.get(templateId);
    if (!template) {
      return null;
    }

    // Update rating (weighted average)
    const totalRating = template.rating * template.reviews + rating;
    template.reviews++;
    template.rating = totalRating / template.reviews;
    template.updatedAt = new Date();

    this.emit('template_rated', { templateId, rating, review });

    return template;
  }

  /**
   * Increment template downloads
   */
  incrementTemplateDownloads(templateId: string): GameTemplate | null {
    const template = this.templates.get(templateId);
    if (!template) {
      return null;
    }

    template.downloads++;
    template.updatedAt = new Date();

    this.emit('template_downloaded', template);

    return template;
  }

  /**
   * Search templates
   */
  searchTemplates(query: string): GameTemplate[] {
    const lowerQuery = query.toLowerCase();
    return Array.from(this.templates.values()).filter(
      (t) =>
        t.name.toLowerCase().includes(lowerQuery) ||
        t.description.toLowerCase().includes(lowerQuery) ||
        t.mechanics.some((m) => m.toLowerCase().includes(lowerQuery))
    );
  }

  /**
   * Get template statistics
   */
  getTemplateStatistics(templateId: string): {
    downloads: number;
    rating: number;
    reviews: number;
    gamesCreated: number;
    totalEngagement: number;
  } | null {
    const template = this.templates.get(templateId);
    const performance = this.performance.get(templateId);

    if (!template) {
      return null;
    }

    return {
      downloads: template.downloads,
      rating: template.rating,
      reviews: template.reviews,
      gamesCreated: performance?.totalGamesCreated || 0,
      totalEngagement: performance?.totalPlays || 0,
    };
  }

  /**
   * Get all template performance
   */
  getAllTemplatePerformance(): TemplatePerformance[] {
    return Array.from(this.performance.values());
  }

  /**
   * Get best performing templates
   */
  getBestPerformingTemplates(limit: number = 5): TemplatePerformance[] {
    return Array.from(this.performance.values())
      .sort((a, b) => b.totalPlays - a.totalPlays)
      .slice(0, limit);
  }
}

// Export singleton instance
export const gameTemplateLibraryService = new GameTemplateLibraryService();

export default GameTemplateLibraryService;
