<?php

namespace Autopilot\Helper;

/**
 * Agent Helper for AI-powered interactions with Cockpit CMS
 * Provides tool registration and execution for OpenAI function calling
 */
class Agent extends \Lime\Helper {

    protected array $tools = [];
    protected array $toolExecutions = [];
    protected int $maxToolCalls = 10; // Prevent infinite loops

    protected function initialize() {

        $this->loadToolsFromDirectory('autopilot:agent-tools');
        $this->loadToolsFromDirectory('#config:agent-tools');

        $this->app->trigger('autopilot:agent:register', [$this]);
    }

    /**
     * Get all registered tools
     *
     * @return array
     */
    public function tools(): array {
        return $this->tools;
    }

    /**
     * Register a tool that the AI agent can use
     *
     * @param string $name Tool identifier
     * @param string $description What the tool does
     * @param array $parameters JSON Schema for parameters
     * @param callable $handler Function to execute the tool
     * @param array $options Additional options (permissions, etc.)
     */
    public function registerTool(string $name, string $description, array $parameters, callable $handler, array $options = []): void {

        $this->tools[$name] = [
            'type' => 'function',
            'function' => [
                'name' => $name,
                'description' => $description,
                'parameters' => $parameters
            ],
            'handler' => $handler,
            'options' => \array_merge([
                'permission' => "autopilot/tools/{$name}",
                'requires_confirmation' => false,
                'log_execution' => true
            ], $options)
        ];
    }

    /**
     * Get all registered tools in OpenAI format
     *
     * @return array Tool definitions for OpenAI API
     */
    public function getToolDefinitions(): array {

        $definitions = [];

        foreach ($this->tools as $name => $tool) {

            // Check if user has permission for this tool
            if (isset($tool['options']['permission']) && $tool['options']['permission'] && !$this->app->helper('acl')->isAllowed($tool['options']['permission'])) {
                continue;
            }

            // Ensure properties is an object, not an array
            $function = $tool['function'];
            if (isset($function['parameters']['properties']) && empty($function['parameters']['properties'])) {
                $function['parameters']['properties'] = new \stdClass();
            }

            $definitions[] = [
                'type' => $tool['type'],
                'function' => $function
            ];
        }

        return $definitions;
    }

    /**
     * Execute a tool call from the AI
     *
     * @param string $name Tool name
     * @param array $arguments Tool arguments
     * @return array Result with success status and data/error
     */
    public function executeToolCall(string $name, array $arguments): array {

        // Check if tool exists
        if (!isset($this->tools[$name])) {
            return [
                'success' => false,
                'error' => "Unknown tool: {$name}"
            ];
        }

        $tool = $this->tools[$name];

        // Check permissions
        if (!$this->app->helper('acl')->isAllowed($tool['options']['permission'])) {
            return [
                'success' => false,
                'error' => "Permission denied for tool: {$name}"
            ];
        }

        // Check execution limit
        if (\count($this->toolExecutions) >= $this->maxToolCalls) {
            return [
                'success' => false,
                'error' => "Maximum tool calls ({$this->maxToolCalls}) exceeded"
            ];
        }

        // Log execution if enabled (disabled for now - datastore not available)
        // if ($tool['options']['log_execution']) {
        //     $this->logExecution($name, $arguments);
        // }

        try {
            // Execute the tool handler
            $result = \call_user_func($tool['handler'], $arguments, $this->app);

            // Track execution
            $this->toolExecutions[] = [
                'tool' => $name,
                'arguments' => $arguments,
                'result' => $result,
                'timestamp' => \time()
            ];

            return [
                'success' => true,
                'data' => $result
            ];

        } catch (\Exception $e) {

            // Log error if logger is available
            if (isset($this->app->logger) && $this->app->logger) {
                $this->app->logger->error("Agent tool execution failed: {$name}", [
                    'error' => $e->getMessage(),
                    'arguments' => $arguments
                ]);
            }

            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Process tool calls from OpenAI streaming response
     *
     * @param array $toolCalls Array of tool calls from OpenAI
     * @return array Results formatted for OpenAI
     */
    public function processToolCalls(array $toolCalls): array {

        $results = [];

        foreach ($toolCalls as $toolCall) {
            $name = $toolCall['function']['name'] ?? '';
            $arguments = \json_decode($toolCall['function']['arguments'] ?? '{}', true);

            $result = $this->executeToolCall($name, $arguments);

            $results[] = [
                'tool_call_id' => $toolCall['id'],
                'role' => 'tool',
                'name' => $name,
                'content' => \json_encode($result)
            ];
        }

        return $results;
    }

    /**
     * Load tools from the tools directory
     */
    public function loadToolsFromDirectory(string $directory): void {

        $directory = $this->app->path($directory);
        $app = $this->app;

        if (!$directory || !\is_dir($directory)) {
            return;
        }

        $toolFiles = \glob($directory . '/*.php');

        foreach ($toolFiles as $file) {
            $tool = include $file;

            if (!\is_array($tool) || !isset($tool['name'], $tool['description'], $tool['parameters'], $tool['handler'])) {
                continue;
            }

            $this->registerTool(
                $tool['name'],
                $tool['description'],
                $tool['parameters'],
                $tool['handler'],
                $tool['options'] ?? []
            );
        }
    }

    /**
     * Register default Cockpit tools (deprecated - use loadToolsFromDirectory)
     */
    public function registerDefaultTools(): void {
        // This method is kept for backward compatibility
        // Tools are now loaded from the tools directory
    }

    /**
     * Log tool execution for auditing (disabled - datastore not available)
     * @param string $tool Tool name (unused until logging implemented)
     * @param array $arguments Tool arguments (unused until logging implemented)
     */
    protected function logExecution(string $tool, array $arguments): void {
        // Disabled for now - would need a proper datastore implementation
        // Parameters intentionally unused until logging is implemented
        // Could log to file or database in the future
    }

    /**
     * Get execution history (disabled - datastore not available)
     * @param int $limit Maximum entries to return (unused until history tracking implemented)
     */
    public function getExecutionHistory(int $limit = 100): array {
        // Disabled for now - would need a proper datastore implementation
        // Parameter intentionally unused until history tracking is implemented
        return [];
    }

    /**
     * Clear execution tracking for current session
     */
    public function clearExecutions(): void {
        $this->toolExecutions = [];
    }
}
