import { EventEmitter } from 'events';
import { invokeLLM } from './_core/llm.ts';
import { generateImage } from './_core/imageGeneration.ts';
import { storagePut } from './storage.ts';

export interface GameConcept {
  id: string;
  title: string;
  description: string;
  genre: 'slot' | 'puzzle' | 'action' | 'strategy' | 'arcade' | 'card';
  targetAudience: 'casual' | 'hardcore' | 'all';
  theme: string;
  mechanics: string[];
  estimatedPlaytime: number; // minutes
  createdAt: Date;
  createdBy: string;
}

export interface GeneratedGame {
  id: string;
  conceptId: string;
  title: string;
  description: string;
  htmlCode: string;
  cssCode: string;
  jsCode: string;
  thumbnailUrl: string;
  previewUrl: string;
  status: 'draft' | 'testing' | 'approved' | 'published' | 'archived';
  performance?: {
    avgPlaytime: number;
    playerCount: number;
    engagementScore: number;
    retentionRate: number;
  };
  createdAt: Date;
  publishedAt?: Date;
}

export interface GameCustomization {
  gameId: string;
  theme: {
    primaryColor: string;
    secondaryColor: string;
    accentColor: string;
    fontFamily: string;
  };
  difficulty: 'easy' | 'medium' | 'hard' | 'extreme';
  rewards: {
    minWin: number;
    maxWin: number;
    multiplier: number;
    bonusChance: number;
  };
  mechanics: {
    speed: number;
    complexity: number;
    interactivity: number;
  };
}

export interface BatchGenerationJob {
  id: string;
  conceptId: string;
  variantCount: number;
  status: 'queued' | 'processing' | 'completed' | 'failed';
  generatedGames: string[]; // game IDs
  progress: number; // 0-100
  startedAt: Date;
  completedAt?: Date;
  error?: string;
}

/**
 * AI Game Builder Service
 * Generates playable HTML5 games from text descriptions using LLM
 */
export class AIGameBuilderService extends EventEmitter {
  private gamePrompts = {
    slot: `Create an HTML5 slot machine game with:
- 3 reels with 5 symbols each
- Spin animation with sound effects
- Payline detection (3 matching symbols = win)
- Bet multiplier system (1x to 10x)
- Win animation with particle effects
- Balance display and spin counter
- Responsive design for mobile
- Professional styling with gradients
Return ONLY the complete HTML code with inline CSS and JavaScript.`,

    puzzle: `Create an HTML5 puzzle game with:
- 4x4 grid of tiles
- Match 3+ tiles of same color to clear
- Gravity physics (tiles fall down)
- Combo multiplier for consecutive matches
- Power-ups (bombs, lightning, color changers)
- Score tracking and level progression
- Time-based or move-based challenges
- Particle effects for matches
Return ONLY the complete HTML code with inline CSS and JavaScript.`,

    action: `Create an HTML5 action game with:
- Player character (spaceship or character)
- Keyboard/touch controls
- Enemy waves with increasing difficulty
- Projectile system with collision detection
- Health/shield system
- Score multiplier for consecutive hits
- Power-up drops (shield, rapid fire, slow-mo)
- Wave progression system
Return ONLY the complete HTML code with inline CSS and JavaScript.`,

    strategy: `Create an HTML5 strategy game with:
- Turn-based gameplay
- Resource management (coins, energy, gems)
- Unit placement and movement
- Tower defense or similar mechanics
- AI opponent with difficulty levels
- Upgrade system for units/towers
- Victory/defeat conditions
- Leaderboard integration points
Return ONLY the complete HTML code with inline CSS and JavaScript.`,

    arcade: `Create an HTML5 arcade game with:
- Simple, addictive gameplay loop
- Progressive difficulty scaling
- High score tracking
- Combo/multiplier system
- Sound effects and visual feedback
- Mobile-optimized controls
- Retro or modern aesthetic
- Quick play sessions (2-5 minutes)
Return ONLY the complete HTML code with inline CSS and JavaScript.`,

    card: `Create an HTML5 card game with:
- Deck of 52 cards or custom deck
- Card dealing and hand management
- Turn-based gameplay
- Win conditions (highest card, specific combinations)
- Betting system with multipliers
- Animated card flips and shuffles
- Player vs AI or multiplayer setup
- Score and chip tracking
Return ONLY the complete HTML code with inline CSS and JavaScript.`,
  };

  constructor() {
    super();
    console.log('[AIGameBuilder] Service initialized');
  }

  /**
   * Parse game concept from user input
   */
  async parseGameConcept(description: string): Promise<GameConcept> {
    const response = await invokeLLM({
      messages: [
        {
          role: 'system',
          content: `You are a game design expert. Parse the game concept and extract:
- Title (catchy, 2-4 words)
- Genre (slot/puzzle/action/strategy/arcade/card)
- Target audience (casual/hardcore/all)
- Theme (visual style description)
- Mechanics (list 3-5 core mechanics)
- Estimated playtime (in minutes)

Return as JSON object.`,
        },
        {
          role: 'user',
          content: description,
        },
      ],
      response_format: {
        type: 'json_schema',
        json_schema: {
          name: 'game_concept',
          strict: true,
          schema: {
            type: 'object',
            properties: {
              title: { type: 'string' },
              genre: { type: 'string', enum: ['slot', 'puzzle', 'action', 'strategy', 'arcade', 'card'] },
              targetAudience: { type: 'string', enum: ['casual', 'hardcore', 'all'] },
              theme: { type: 'string' },
              mechanics: { type: 'array', items: { type: 'string' } },
              estimatedPlaytime: { type: 'number' },
            },
            required: ['title', 'genre', 'targetAudience', 'theme', 'mechanics', 'estimatedPlaytime'],
            additionalProperties: false,
          },
        },
      },
    });

    const parsed = JSON.parse(response.choices[0].message.content);

    return {
      id: `concept-${Date.now()}`,
      title: parsed.title,
      description,
      genre: parsed.genre,
      targetAudience: parsed.targetAudience,
      theme: parsed.theme,
      mechanics: parsed.mechanics,
      estimatedPlaytime: parsed.estimatedPlaytime,
      createdAt: new Date(),
      createdBy: 'admin',
    };
  }

  /**
   * Generate game code from concept
   */
  async generateGameCode(concept: GameConcept): Promise<GeneratedGame> {
    const prompt = this.gamePrompts[concept.genre] || this.gamePrompts.arcade;

    const enhancedPrompt = `${prompt}

Theme: ${concept.theme}
Mechanics: ${concept.mechanics.join(', ')}
Target: ${concept.targetAudience}
Title: ${concept.title}`;

    console.log(`[AIGameBuilder] Generating ${concept.genre} game: ${concept.title}`);

    const response = await invokeLLM({
      messages: [
        {
          role: 'system',
          content: `You are an expert HTML5 game developer. Create a complete, playable game.
IMPORTANT: Return ONLY valid HTML code with inline CSS and JavaScript. No markdown, no explanations.
The code must be production-ready and include:
- Responsive design
- Touch/mobile support
- Sound effects (using Web Audio API)
- Particle effects
- Smooth animations
- Professional styling
- Error handling`,
        },
        {
          role: 'user',
          content: enhancedPrompt,
        },
      ],
    });

    const htmlCode = response.choices[0].message.content;

    // Generate thumbnail
    const thumbnailUrl = await this.generateGameThumbnail(concept.title, concept.theme);

    const game: GeneratedGame = {
      id: `game-${Date.now()}`,
      conceptId: concept.id,
      title: concept.title,
      description: concept.description,
      htmlCode,
      cssCode: '', // Extracted from HTML
      jsCode: '', // Extracted from HTML
      thumbnailUrl,
      previewUrl: '', // Will be set after deployment
      status: 'draft',
      createdAt: new Date(),
    };

    this.emit('gameGenerated', game);
    console.log(`[AIGameBuilder] Game generated: ${game.id}`);

    return game;
  }

  /**
   * Generate game thumbnail image
   */
  private async generateGameThumbnail(title: string, theme: string): Promise<string> {
    try {
      const { url } = await generateImage({
        prompt: `Create a vibrant game thumbnail for "${title}". Style: ${theme}. 
        Professional, eye-catching, 16:9 aspect ratio. Include game title.`,
      });

      return url;
    } catch (error) {
      console.error('[AIGameBuilder] Thumbnail generation failed:', error);
      return ''; // Fallback to placeholder
    }
  }

  /**
   * Customize game with theme and mechanics
   */
  async customizeGame(game: GeneratedGame, customization: Partial<GameCustomization>): Promise<GeneratedGame> {
    const customizationPrompt = `Modify this HTML5 game code with the following customizations:
${customization.theme ? `- Theme colors: primary=${customization.theme.primaryColor}, secondary=${customization.theme.secondaryColor}` : ''}
${customization.difficulty ? `- Difficulty level: ${customization.difficulty}` : ''}
${customization.rewards ? `- Reward range: ${customization.rewards.minWin}-${customization.rewards.maxWin} with ${customization.rewards.multiplier}x multiplier` : ''}
${customization.mechanics ? `- Adjust mechanics: speed=${customization.mechanics.speed}, complexity=${customization.mechanics.complexity}` : ''}

Original code:
${game.htmlCode}

Return ONLY the modified HTML code.`;

    const response = await invokeLLM({
      messages: [
        {
          role: 'system',
          content: 'You are an expert at modifying HTML5 games. Return ONLY valid HTML code with inline CSS and JavaScript.',
        },
        {
          role: 'user',
          content: customizationPrompt,
        },
      ],
    });

    game.htmlCode = response.choices[0].message.content;
    game.status = 'testing';

    this.emit('gameCustomized', game);
    console.log(`[AIGameBuilder] Game customized: ${game.id}`);

    return game;
  }

  /**
   * Create game variants for A/B testing
   */
  async createGameVariants(game: GeneratedGame, variantCount: number = 3): Promise<GeneratedGame[]> {
    const variants: GeneratedGame[] = [];

    const themes = [
      { name: 'Dark', colors: { primary: '#1a1a2e', secondary: '#16213e', accent: '#0f3460' } },
      { name: 'Neon', colors: { primary: '#0a0e27', secondary: '#1a1a2e', accent: '#00ff88' } },
      { name: 'Gold', colors: { primary: '#2d1810', secondary: '#5a3a1a', accent: '#ffd700' } },
    ];

    for (let i = 0; i < Math.min(variantCount, themes.length); i++) {
      const theme = themes[i];
      const customization: Partial<GameCustomization> = {
        theme: {
          primaryColor: theme.colors.primary,
          secondaryColor: theme.colors.secondary,
          accentColor: theme.colors.accent,
          fontFamily: 'Arial, sans-serif',
        },
        difficulty: i === 0 ? 'easy' : i === 1 ? 'medium' : 'hard',
      };

      const variant = await this.customizeGame(game, customization);
      variant.id = `game-${theme.name.toLowerCase()}-${Date.now()}`;
      variants.push(variant);
    }

    this.emit('variantsCreated', { baseGame: game.id, variants: variants.map((v) => v.id) });
    console.log(`[AIGameBuilder] Created ${variants.length} variants for game ${game.id}`);

    return variants;
  }

  /**
   * Deploy game to S3
   */
  async deployGame(game: GeneratedGame): Promise<string> {
    try {
      const { url } = await storagePut(`games/${game.id}/index.html`, game.htmlCode, 'text/html');

      game.previewUrl = url;
      game.status = 'published';

      this.emit('gameDeployed', { gameId: game.id, url });
      console.log(`[AIGameBuilder] Game deployed: ${url}`);

      return url;
    } catch (error) {
      console.error('[AIGameBuilder] Deployment failed:', error);
      throw error;
    }
  }

  /**
   * Validate game code
   */
  async validateGame(game: GeneratedGame): Promise<{ valid: boolean; errors: string[] }> {
    const errors: string[] = [];

    // Check for required elements
    if (!game.htmlCode.includes('<html')) errors.push('Missing HTML tag');
    if (!game.htmlCode.includes('<canvas') && !game.htmlCode.includes('div')) errors.push('Missing game container');
    if (!game.htmlCode.includes('function') && !game.htmlCode.includes('=>')) errors.push('Missing game logic');

    // Check for security issues
    if (game.htmlCode.includes('eval(')) errors.push('Security risk: eval() detected');
    if (game.htmlCode.includes('innerHTML') && game.htmlCode.includes('user')) errors.push('Potential XSS vulnerability');

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

  /**
   * Get game statistics
   */
  getGameStats(game: GeneratedGame) {
    return {
      codeSize: game.htmlCode.length,
      complexity: Math.ceil(game.htmlCode.length / 1000), // Rough estimate
      hasAnimation: game.htmlCode.includes('animation') || game.htmlCode.includes('requestAnimationFrame'),
      hasAudio: game.htmlCode.includes('AudioContext') || game.htmlCode.includes('audio'),
      hasParticles: game.htmlCode.includes('particle'),
      estimatedPlaytime: 3, // Default
    };
  }

  /**
   * Clear all data
   */
  clear(): void {
    console.log('[AIGameBuilder] Service cleared');
  }
}

export const aiGameBuilderService = new AIGameBuilderService();
