<?php
/**
 * AI Agent Context Management
 * Manages conversation context, task history, and state for the AI agent
 * 
 * @package AI_Auto_Tool
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Context Management Class
 * Handles conversation context, history, and state management for AI agent
 */
class AIAutotool_Agent_Context {
    
    /**
     * Conversation messages
     * @var array
     */
    private $messages = array();
    
    /**
     * Task history
     * @var array
     */
    private $task_history = array();
    
    /**
     * Tool execution results
     * @var array
     */
    private $tool_results = array();
    
    /**
     * Model switching history
     * @var array
     */
    private $model_history = array();
    
    /**
     * Error tracking
     * @var array
     */
    private $errors = array();
    
    /**
     * User preferences
     * @var array
     */
    private $preferences = array();
    
    /**
     * Max context window size (in messages)
     * @var int
     */
    private $max_context_size = 50;
    
    /**
     * Context metadata
     * @var array
     */
    private $metadata = array();
    
    /**
     * Constructor
     * 
     * @param array $options Optional configuration
     */
    public function __construct($options = array()) {
        if (isset($options['max_context_size'])) {
            $this->max_context_size = intval($options['max_context_size']);
        }
        
        if (isset($options['preferences'])) {
            $this->preferences = $options['preferences'];
        }
        
        $this->metadata = array(
            'created_at' => current_time('mysql'),
            'session_id' => $this->generate_session_id()
        );
    }
    
    /**
     * Generate unique session ID
     * 
     * @return string
     */
    private function generate_session_id() {
        // Use WordPress function if available
        if (function_exists('wp_generate_password')) {
            return 'session_' . wp_generate_password(12, false);
        }
        
        // Fallback for when WordPress is not fully loaded
        return 'session_' . substr(md5(uniqid(mt_rand(), true)), 0, 12);
    }
    
    /**
     * Add message to context
     * 
     * @param string $role Role (user, assistant, system)
     * @param string $content Message content
     * @param array $metadata Optional metadata
     * @return void
     */
    public function add_message($role, $content, $metadata = array()) {
        $message = array(
            'role' => $role,
            'content' => $content,
            'timestamp' => current_time('mysql'),
            'metadata' => $metadata
        );
        
        $this->messages[] = $message;
        
        // Auto-prune if exceeds max size
        if (count($this->messages) > $this->max_context_size) {
            $this->prune_context();
        }
    }
    
    /**
     * Get messages for model consumption
     * 
     * @param int $limit Optional limit
     * @param bool $include_system Include system messages
     * @return array
     */
    public function get_messages($limit = null, $include_system = true) {
        $messages = $this->messages;
        
        if (!$include_system) {
            $messages = array_filter($messages, function($msg) {
                return $msg['role'] !== 'system';
            });
        }
        
        if ($limit) {
            $messages = array_slice($messages, -$limit);
        }
        
        // Format for model consumption (remove metadata)
        return array_map(function($msg) {
            return array(
                'role' => $msg['role'],
                'content' => $msg['content']
            );
        }, $messages);
    }
    
    /**
     * Get full context with metadata
     * 
     * @return array
     */
    public function get_full_context() {
        return array(
            'messages' => $this->messages,
            'task_history' => $this->task_history,
            'tool_results' => $this->tool_results,
            'model_history' => $this->model_history,
            'errors' => $this->errors,
            'preferences' => $this->preferences,
            'metadata' => $this->metadata
        );
    }
    
    /**
     * Add task to history
     * 
     * @param string $task_name Task name
     * @param string $status Status (planning, executing, completed, failed)
     * @param array $details Task details
     * @return void
     */
    public function add_task($task_name, $status, $details = array()) {
        $this->task_history[] = array(
            'name' => $task_name,
            'status' => $status,
            'details' => $details,
            'timestamp' => current_time('mysql')
        );
    }
    
    /**
     * Update last task status
     * 
     * @param string $status New status
     * @param array $details Additional details
     * @return void
     */
    public function update_task_status($status, $details = array()) {
        if (!empty($this->task_history)) {
            $last_index = count($this->task_history) - 1;
            $this->task_history[$last_index]['status'] = $status;
            $this->task_history[$last_index]['updated_at'] = current_time('mysql');
            
            if (!empty($details)) {
                $this->task_history[$last_index]['details'] = array_merge(
                    $this->task_history[$last_index]['details'],
                    $details
                );
            }
        }
    }
    
    /**
     * Add tool execution result
     * 
     * @param string $tool_name Tool name
     * @param array $result Execution result
     * @return void
     */
    public function add_tool_result($tool_name, $result) {
        $this->tool_results[] = array(
            'tool' => $tool_name,
            'result' => $result,
            'timestamp' => current_time('mysql')
        );
    }
    
    /**
     * Get tool results
     * 
     * @param string $tool_name Optional filter by tool name
     * @return array
     */
    public function get_tool_results($tool_name = null) {
        if ($tool_name) {
            return array_filter($this->tool_results, function($result) use ($tool_name) {
                return $result['tool'] === $tool_name;
            });
        }
        
        return $this->tool_results;
    }
    
    /**
     * Log model switch
     * 
     * @param string $from_provider Previous provider
     * @param string $from_model Previous model
     * @param string $to_provider New provider
     * @param string $to_model New model
     * @param string $reason Reason for switch
     * @return void
     */
    public function log_model_switch($from_provider, $from_model, $to_provider, $to_model, $reason) {
        $this->model_history[] = array(
            'from' => array('provider' => $from_provider, 'model' => $from_model),
            'to' => array('provider' => $to_provider, 'model' => $to_model),
            'reason' => $reason,
            'timestamp' => current_time('mysql')
        );
    }
    
    /**
     * Add error
     * 
     * @param string $error_type Error type
     * @param string $message Error message
     * @param array $context Error context
     * @return void
     */
    public function add_error($error_type, $message, $context = array()) {
        $this->errors[] = array(
            'type' => $error_type,
            'message' => $message,
            'context' => $context,
            'timestamp' => current_time('mysql')
        );
    }
    
    /**
     * Get errors
     * 
     * @param string $type Optional filter by error type
     * @return array
     */
    public function get_errors($type = null) {
        if ($type) {
            return array_filter($this->errors, function($error) use ($type) {
                return $error['type'] === $type;
            });
        }
        
        return $this->errors;
    }
    
    /**
     * Prune context to fit within limits
     * Keeps important messages and removes less important ones
     * 
     * @return void
     */
    public function prune_context() {
        if (count($this->messages) <= $this->max_context_size) {
            return;
        }
        
        // Keep first message (often contains important context)
        $first_message = $this->messages[0];
        
        // Keep last N-1 messages
        $keep_count = $this->max_context_size - 1;
        $recent_messages = array_slice($this->messages, -$keep_count);
        
        // Combine
        $this->messages = array_merge(array($first_message), $recent_messages);
        
        // Log pruning
        $this->metadata['last_pruned'] = current_time('mysql');
        $this->metadata['prune_count'] = isset($this->metadata['prune_count']) 
            ? $this->metadata['prune_count'] + 1 
            : 1;
    }
    
    /**
     * Summarize context for long conversations
     * 
     * @return string Summary
     */
    public function summarize_context() {
        $summary = array();
        
        $summary[] = sprintf(
            'Session: %s, Started: %s', 
            $this->metadata['session_id'],
            $this->metadata['created_at']
        );
        
        $summary[] = sprintf('Total messages: %d', count($this->messages));
        $summary[] = sprintf('Tasks: %d', count($this->task_history));
        $summary[] = sprintf('Tool executions: %d', count($this->tool_results));
        $summary[] = sprintf('Model switches: %d', count($this->model_history));
        $summary[] = sprintf('Errors: %d', count($this->errors));
        
        return implode("\n", $summary);
    }
    
    /**
     * Save state to persistent storage
     * 
     * @param string $key Storage key
     * @return bool Success
     */
    public function save_state($key = null) {
        $key = $key ?: 'agent_context_' . $this->metadata['session_id'];
        
        $state = array(
            'messages' => $this->messages,
            'task_history' => $this->task_history,
            'tool_results' => $this->tool_results,
            'model_history' => $this->model_history,
            'errors' => $this->errors,
            'preferences' => $this->preferences,
            'metadata' => $this->metadata
        );
        
        return update_option($key, $state, false);
    }
    
    /**
     * Restore state from persistent storage
     * 
     * @param string $key Storage key
     * @return bool Success
     */
    public function restore_state($key) {
        $state = get_option($key);
        
        if (!$state) {
            return false;
        }
        
        $this->messages = $state['messages'] ?? array();
        $this->task_history = $state['task_history'] ?? array();
        $this->tool_results = $state['tool_results'] ?? array();
        $this->model_history = $state['model_history'] ?? array();
        $this->errors = $state['errors'] ?? array();
        $this->preferences = $state['preferences'] ?? array();
        $this->metadata = $state['metadata'] ?? array();
        
        return true;
    }
    
    /**
     * Clear context
     * 
     * @param bool $keep_preferences Keep user preferences
     * @return void
     */
    public function clear($keep_preferences = true) {
        $this->messages = array();
        $this->task_history = array();
        $this->tool_results = array();
        $this->model_history = array();
        $this->errors = array();
        
        if (!$keep_preferences) {
            $this->preferences = array();
        }
        
        $this->metadata = array(
            'created_at' => current_time('mysql'),
            'session_id' => $this->generate_session_id()
        );
    }
    
    /**
     * Set preference
     * 
     * @param string $key Preference key
     * @param mixed $value Preference value
     * @return void
     */
    public function set_preference($key, $value) {
        $this->preferences[$key] = $value;
    }
    
    /**
     * Get preference
     * 
     * @param string $key Preference key
     * @param mixed $default Default value
     * @return mixed
     */
    public function get_preference($key, $default = null) {
        return $this->preferences[$key] ?? $default;
    }
    
    /**
     * Get session ID
     * 
     * @return string
     */
    public function get_session_id() {
        return $this->metadata['session_id'];
    }
}
