<?php

namespace GriffinForms\Includes\Ai;

/**
 * ButlerModelRouter
 *
 * Maps high-level task intents (e.g., 'form_drafting') to the correct
 * transport provider ID and configuration pulled from the native Settings store.
 *
 * This is intentionally thin for 3.0.1.0. Additional intents and providers
 * can be registered in future releases without touching the Broker.
 *
 * @since 3.0.1.0
 */
class ButlerModelRouter
{
    protected $settings;

    /**
     * Maps intent slugs to provider IDs.
     * Extend this map in future releases as new intents are added.
     */
    protected $intent_map = [
        'form_drafting'     => 'openai',
        'field_suggestion'  => 'openai',
        'default'           => 'openai',
    ];

    public function __construct()
    {
        $this->settings = \GriffinForms\Settings::getInstance();
    }

    /**
     * Resolve the provider ID and transport config for a given intent.
     *
     * @param string $intent A task intent slug (e.g., 'form_drafting').
     * @return array ['provider' => string, 'config' => array]
     */
    public function route(string $intent): array
    {
        $provider = sanitize_key((string) $this->settings->getOption('butler_active_provider', ''));
        if ($provider === '') {
            $provider = sanitize_key((string) $this->settings->getOption('ai_provider', ''));
        }

        $config = $this->buildConfig($provider);

        return [
            'provider' => $provider,
            'config'   => $config,
        ];
    }

    /**
     * Build the transport config array for the resolved provider.
     *
     * @param string $provider Provider ID.
     * @return array
     */
    protected function buildConfig(string $provider): array
    {
        $timeout = $this->resolveGenerationTimeout();

        switch ($provider) {
            case 'openai':
                return [
                    'api_key'    => $this->resolveKey('gf_assist_openai_key', 'openai'),
                    'model'      => (string) ($this->settings->getOption('gf_assist_default_model') ?? 'gpt-4o-mini'),
                    'timeout'    => $timeout,
                    'max_tokens' => $this->resolveMaxTokens(),
                ];
            case 'anthropic':
                return [
                    'api_key'    => $this->resolveKey('gf_assist_anthropic_key', 'anthropic'),
                    'model'      => (string) ($this->settings->getOption('gf_assist_anthropic_model') ?? 'claude-haiku-4-5'),
                    'timeout'    => $timeout,
                    'max_tokens' => $this->resolveMaxTokens(),
                ];
            case 'gemini':
                return [
                    'api_key'    => $this->resolveKey('gf_assist_gemini_key', 'google'),
                    'model'      => (string) ($this->settings->getOption('gf_assist_gemini_model') ?? 'gemini-2.0-flash'),
                    'timeout'    => $timeout,
                    'max_tokens' => $this->resolveMaxTokens(),
                ];
            case 'xai':
                wp_cache_delete('gf_assist_xai_key', 'griffinforms-form-builder');

                return [
                    'api_key'    => (string) ($this->settings->getOption('gf_assist_xai_key') ?? ''),
                    'model'      => (string) ($this->settings->getOption('gf_assist_xai_model') ?? 'grok-3-mini'),
                    'timeout'    => $timeout,
                    'max_tokens' => $this->resolveMaxTokens(),
                ];
            case 'mistral':
                wp_cache_delete('gf_assist_mistral_key', 'griffinforms-form-builder');

                return [
                    'api_key'    => (string) ($this->settings->getOption('gf_assist_mistral_key') ?? ''),
                    'model'      => (string) ($this->settings->getOption('gf_assist_mistral_model') ?? 'mistral-small-latest'),
                    'timeout'    => $timeout,
                    'max_tokens' => $this->resolveMaxTokens(),
                ];
            default:
                return [
                    'timeout' => $timeout,
                    'max_tokens' => $this->resolveMaxTokens(),
                ];
        }
    }

    /**
     * Resolve an AI provider API key: GriffinForms own key takes precedence,
     * then falls back to the WP7 Connectors API key for the matching provider.
     */
    private function resolveKey(string $gf_option_key, string $connector_id): string
    {
        wp_cache_delete($gf_option_key, 'griffinforms-form-builder');
        $own_key = trim((string) ($this->settings->getOption($gf_option_key) ?? ''));
        if ($own_key !== '') {
            return $own_key;
        }

        if (!function_exists('wp_get_connector')) {
            return '';
        }

        $connector = wp_get_connector($connector_id);
        if (!$connector || empty($connector['authentication']['setting_name'])) {
            return '';
        }

        $auth = $connector['authentication'];

        if (!empty($auth['env_var_name'])) {
            $env_value = getenv($auth['env_var_name']);
            if (false !== $env_value && '' !== $env_value) {
                return trim($env_value);
            }
        }

        if (!empty($auth['constant_name']) && defined($auth['constant_name'])) {
            $const_value = constant($auth['constant_name']);
            if (is_string($const_value) && '' !== $const_value) {
                return trim($const_value);
            }
        }

        return trim((string) get_option($auth['setting_name'], ''));
    }

    /**
     * Resolve the configured AI generation timeout with strict fallback.
     */
    protected function resolveGenerationTimeout(): int
    {
        $timeout = (int) $this->settings->getOption('butler_generation_timeout', 20);
        if ($timeout < 1) {
            $timeout = (int) $this->settings->getOption('ai_timeout', 20);
        }

        if (!in_array($timeout, [10, 20, 30], true)) {
            $timeout = 20;
        }

        return $timeout;
    }

    /**
     * Resolve the configured AI completion token budget with a conservative fallback.
     */
    protected function resolveMaxTokens(): int
    {
        $max_tokens = (int) $this->settings->getOption('butler_generation_max_tokens', 4096);
        if ($max_tokens < 256) {
            $max_tokens = 4096;
        }

        return $max_tokens;
    }

    /**
     * Returns all registered intent slugs.
     *
     * @return array
     */
    public function getRegisteredIntents(): array
    {
        return array_keys($this->intent_map);
    }
}
