/**
 * AI Agent System
 * Create, train, and manage AI agents for game behavior and player interactions
 */

import { EventEmitter } from 'events';
import { invokeLLM } from './server/_core/llm.ts';

export interface AIAgent {
  id: string;
  name: string;
  description: string;
  type: 'game_logic' | 'player_interaction' | 'difficulty_adjuster' | 'reward_optimizer';
  personality: 'aggressive' | 'balanced' | 'conservative';
  trainingData: {
    gamesAnalyzed: number;
    playersStudied: number;
    decisionsLogged: number;
  };
  performance: {
    accuracy: number;
    responseTime: number;
    playerSatisfaction: number;
  };
  behaviors: {
    rtp: number;
    volatility: number;
    bonusFrequency: number;
    winCelebration: string;
  };
  createdAt: Date;
  updatedAt: Date;
  status: 'training' | 'active' | 'archived';
}

export interface AgentTrainingConfig {
  agentId: string;
  trainingDataset: string;
  epochs: number;
  learningRate: number;
  targetMetrics: {
    minAccuracy: number;
    maxResponseTime: number;
    minPlayerSatisfaction: number;
  };
}

export class AIAgentSystem extends EventEmitter {
  private agents: Map<string, AIAgent> = new Map();

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

  /**
   * Initialize default AI agents
   */
  private initializeDefaultAgents(): void {
    const defaultAgents: AIAgent[] = [
      {
        id: 'agent-balanced-game',
        name: 'Balanced Game Logic',
        description: 'Provides fair and balanced game mechanics',
        type: 'game_logic',
        personality: 'balanced',
        trainingData: {
          gamesAnalyzed: 10000,
          playersStudied: 5000,
          decisionsLogged: 50000,
        },
        performance: {
          accuracy: 0.98,
          responseTime: 50,
          playerSatisfaction: 0.92,
        },
        behaviors: {
          rtp: 96.0,
          volatility: 0.5,
          bonusFrequency: 0.15,
          winCelebration: 'moderate',
        },
        createdAt: new Date(),
        updatedAt: new Date(),
        status: 'active',
      },
      {
        id: 'agent-aggressive-game',
        name: 'Aggressive Game Logic',
        description: 'High volatility, high reward gameplay',
        type: 'game_logic',
        personality: 'aggressive',
        trainingData: {
          gamesAnalyzed: 8000,
          playersStudied: 4000,
          decisionsLogged: 40000,
        },
        performance: {
          accuracy: 0.96,
          responseTime: 45,
          playerSatisfaction: 0.88,
        },
        behaviors: {
          rtp: 94.5,
          volatility: 0.8,
          bonusFrequency: 0.25,
          winCelebration: 'intense',
        },
        createdAt: new Date(),
        updatedAt: new Date(),
        status: 'active',
      },
      {
        id: 'agent-conservative-game',
        name: 'Conservative Game Logic',
        description: 'Low volatility, steady gameplay',
        type: 'game_logic',
        personality: 'conservative',
        trainingData: {
          gamesAnalyzed: 9000,
          playersStudied: 4500,
          decisionsLogged: 45000,
        },
        performance: {
          accuracy: 0.99,
          responseTime: 55,
          playerSatisfaction: 0.95,
        },
        behaviors: {
          rtp: 97.0,
          volatility: 0.3,
          bonusFrequency: 0.1,
          winCelebration: 'subtle',
        },
        createdAt: new Date(),
        updatedAt: new Date(),
        status: 'active',
      },
      {
        id: 'agent-player-interaction',
        name: 'Player Interaction Agent',
        description: 'Handles player engagement and feedback',
        type: 'player_interaction',
        personality: 'balanced',
        trainingData: {
          gamesAnalyzed: 5000,
          playersStudied: 8000,
          decisionsLogged: 30000,
        },
        performance: {
          accuracy: 0.94,
          responseTime: 100,
          playerSatisfaction: 0.91,
        },
        behaviors: {
          rtp: 96.0,
          volatility: 0.5,
          bonusFrequency: 0.15,
          winCelebration: 'engaging',
        },
        createdAt: new Date(),
        updatedAt: new Date(),
        status: 'active',
      },
    ];

    defaultAgents.forEach((agent) => {
      this.agents.set(agent.id, agent);
    });

    this.emit('agents_initialized', defaultAgents.length);
  }

  /**
   * Create new AI agent
   */
  async createAgent(config: {
    name: string;
    description: string;
    type: AIAgent['type'];
    personality: AIAgent['personality'];
  }): Promise<AIAgent> {
    const agentId = `agent-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

    this.emit('agent_creation_started', { agentId, name: config.name });

    try {
      // Use LLM to generate agent configuration
      const prompt = `
        Create an AI agent with the following specifications:
        - Name: ${config.name}
        - Description: ${config.description}
        - Type: ${config.type}
        - Personality: ${config.personality}
        
        Generate appropriate behaviors for this agent including:
        1. RTP (Return to Player) percentage (90-99%)
        2. Volatility level (0.1-1.0)
        3. Bonus frequency (0.05-0.5)
        4. Win celebration style
        
        Return as JSON with keys: rtp, volatility, bonusFrequency, winCelebration
      `;

      const response = await invokeLLM({
        messages: [
          {
            role: 'system',
            content: 'You are an expert game designer. Generate appropriate game behavior parameters.',
          },
          {
            role: 'user',
            content: prompt,
          },
        ],
        response_format: {
          type: 'json_schema',
          json_schema: {
            name: 'agent_config',
            strict: true,
            schema: {
              type: 'object',
              properties: {
                rtp: { type: 'number' },
                volatility: { type: 'number' },
                bonusFrequency: { type: 'number' },
                winCelebration: { type: 'string' },
              },
              required: ['rtp', 'volatility', 'bonusFrequency', 'winCelebration'],
            },
          },
        },
      });

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

      const newAgent: AIAgent = {
        id: agentId,
        name: config.name,
        description: config.description,
        type: config.type,
        personality: config.personality,
        trainingData: {
          gamesAnalyzed: 0,
          playersStudied: 0,
          decisionsLogged: 0,
        },
        performance: {
          accuracy: 0.85,
          responseTime: 100,
          playerSatisfaction: 0.8,
        },
        behaviors,
        createdAt: new Date(),
        updatedAt: new Date(),
        status: 'training',
      };

      this.agents.set(agentId, newAgent);
      this.emit('agent_created', newAgent);

      return newAgent;
    } catch (error) {
      this.emit('agent_creation_error', { error, config });
      throw error;
    }
  }

  /**
   * Train AI agent
   */
  async trainAgent(config: AgentTrainingConfig): Promise<AIAgent> {
    const agent = this.agents.get(config.agentId);
    if (!agent) {
      throw new Error(`Agent ${config.agentId} not found`);
    }

    this.emit('training_started', { agentId: config.agentId, epochs: config.epochs });

    try {
      // Simulate training process
      for (let epoch = 0; epoch < config.epochs; epoch++) {
        // Update performance metrics
        agent.performance.accuracy = Math.min(
          0.99,
          agent.performance.accuracy + 0.001 * (1 - agent.performance.accuracy)
        );
        agent.performance.responseTime = Math.max(
          30,
          agent.performance.responseTime - 0.5
        );
        agent.performance.playerSatisfaction = Math.min(
          0.99,
          agent.performance.playerSatisfaction + 0.002 * (1 - agent.performance.playerSatisfaction)
        );

        agent.trainingData.decisionsLogged += Math.floor(Math.random() * 1000) + 500;

        this.emit('training_progress', {
          agentId: config.agentId,
          epoch: epoch + 1,
          totalEpochs: config.epochs,
          accuracy: agent.performance.accuracy,
        });

        // Simulate training delay
        await new Promise((resolve) => setTimeout(resolve, 100));
      }

      agent.status = 'active';
      agent.updatedAt = new Date();

      this.emit('training_complete', { agentId: config.agentId, agent });

      return agent;
    } catch (error) {
      this.emit('training_error', { error, agentId: config.agentId });
      throw error;
    }
  }

  /**
   * Get agent by ID
   */
  getAgent(agentId: string): AIAgent | undefined {
    return this.agents.get(agentId);
  }

  /**
   * Get all agents
   */
  getAllAgents(): AIAgent[] {
    return Array.from(this.agents.values());
  }

  /**
   * Get agents by type
   */
  getAgentsByType(type: AIAgent['type']): AIAgent[] {
    return Array.from(this.agents.values()).filter((agent) => agent.type === type);
  }

  /**
   * Get agents by personality
   */
  getAgentsByPersonality(personality: AIAgent['personality']): AIAgent[] {
    return Array.from(this.agents.values()).filter((agent) => agent.personality === personality);
  }

  /**
   * Update agent
   */
  updateAgent(agentId: string, updates: Partial<AIAgent>): AIAgent {
    const agent = this.agents.get(agentId);
    if (!agent) {
      throw new Error(`Agent ${agentId} not found`);
    }

    const updated = { ...agent, ...updates, updatedAt: new Date() };
    this.agents.set(agentId, updated);
    this.emit('agent_updated', updated);

    return updated;
  }

  /**
   * Delete agent
   */
  deleteAgent(agentId: string): void {
    this.agents.delete(agentId);
    this.emit('agent_deleted', { agentId });
  }

  /**
   * Get best agent for game type
   */
  getBestAgentForGameType(gameType: string): AIAgent | undefined {
    const candidates = this.getAgentsByType('game_logic' as any);
    return candidates.reduce((best, current) =>
      current.performance.accuracy > (best?.performance.accuracy || 0) ? current : best
    );
  }
}

export const aiAgentSystem = new AIAgentSystem();
