<?php

namespace GriffinForms\Includes\Integrations\OpenAI;

/**
 * OpenAI Integration
 *
 * Manages BYO API key configuration for Griffin Assist AI features.
 * Global-only integration; no per-form configuration surface.
 *
 * @since 3.0.1.0
 */
class Main extends \GriffinForms\Includes\Integrations\Format
{
    /**
     * Set integration identifiers.
     */
    protected function setMeta()
    {
        $this->meta = 'openai';
        $this->id   = 'openai';
    }

    /**
     * Build integration metadata.
     *
     * @return array
     */
    protected function buildInfo(): array
    {
        return [
            'id'          => 'openai',
            'name'        => 'OpenAI',
            'category'    => 'AI',
            'description' => __('Connect your OpenAI API key to power Griffin Assist features across your forms.', 'griffinforms-form-builder'),
            'scope'       => [
                'is_global'      => true,
                'allow_override' => false,
            ],
            'coming_soon' => false,
        ];
    }

    /**
     * Current integration status.
     *
     * @return array
     */
    public function getStatus(): array
    {
        $configured = $this->isConfigured();

        return [
            'configured'  => $configured,
            'active'      => $configured,
            'message'     => $configured
                ? __('Connected', 'griffinforms-form-builder')
                : __('API key required', 'griffinforms-form-builder'),
        ];
    }

    /**
     * No field schema used (HTML-driven configure view).
     *
     * @return array
     */
    public function getConfigFields(): array
    {
        return [];
    }

    /**
     * Per-instance cache for the decrypted API key.
     *
     * Prevents a WP object cache collision: Settings::getOption() caches the
     * raw encrypted DB value, so a second call within the same request (e.g.
     * testConnection() → isConfigured() then → validateConnection()) would
     * return ciphertext instead of the plaintext key.
     *
     * @var string|null  null = not yet read, '' = confirmed empty
     */
    private $decrypted_api_key = null;

    /**
     * Read and cache the decrypted API key for this request.
     *
     * Forces a WP cache eviction before reading so that the Settings layer
     * always returns the freshly-decrypted value regardless of call order.
     *
     * @return string
     */
    private function getApiKey(): string
    {
        if ($this->decrypted_api_key === null) {
            wp_cache_delete('gf_assist_openai_key', 'griffinforms-form-builder');
            $own_key = trim((string) $this->settings->getOption('gf_assist_openai_key'));
            $this->decrypted_api_key = $own_key !== '' ? $own_key : $this->resolveConnectorApiKey('openai');
        }

        return $this->decrypted_api_key;
    }

    /**
     * Check if the integration is configured.
     *
     * @return bool
     */
    public function isConfigured(): bool
    {
        return !empty($this->getApiKey());
    }

    /**
     * Save configuration — persists the API key and model preference.
     *
     * @param array $config
     * @return bool
     */
    protected function saveConfiguration(array $config): bool
    {
        try {
            $api_key = isset($config['gf_assist_openai_key'])
                ? sanitize_text_field($config['gf_assist_openai_key'])
                : '';

            $model = isset($config['gf_assist_default_model'])
                ? sanitize_text_field($config['gf_assist_default_model'])
                : 'gpt-4o-mini';

            $allowed_models = array_keys($this->getSupportedModels());
            if (!in_array($model, $allowed_models, true)) {
                $model = 'gpt-4o-mini';
            }

            // api_key may be intentionally cleared — allow empty to delete
            $this->settings->updateOption('gf_assist_openai_key', $api_key, 'ai');
            $this->settings->updateOption('gf_assist_default_model', $model, 'ai');

            return true;
        } catch (\Exception $e) {
            $this->log->add(
                'error',
                'integration',
                0,
                get_current_user_id(),
                'Failed to save OpenAI configuration: ' . $e->getMessage(),
                'integration (openai)'
            );
            return false;
        }
    }

    /**
     * Validate connection by making a lightweight models list request.
     *
     * @return array
     */
    protected function validateConnection(): array
    {
        $api_key = $this->getApiKey();

        if (empty($api_key)) {
            return [
                'success' => false,
                'message' => __('No API key is saved. Please enter your key and save first.', 'griffinforms-form-builder'),
            ];
        }

        $response = wp_remote_get('https://api.openai.com/v1/models', [
            'headers' => [
                'Authorization' => 'Bearer ' . $api_key,
                'Content-Type'  => 'application/json',
            ],
            'timeout' => 15,
        ]);

        if (is_wp_error($response)) {
            $message = 'OpenAI connection test failed (network error): ' . $response->get_error_message();
            $this->log->add('error', 'integration', 0, get_current_user_id(), $message, 'integration (openai)');
            return [
                'success' => false,
                'message' => $response->get_error_message(),
            ];
        }

        $code = (int) wp_remote_retrieve_response_code($response);

        if ($code === 200) {
            $message = 'OpenAI connection test successful (HTTP 200).';
            $this->log->add('success', 'integration', 0, get_current_user_id(), $message, 'integration (openai)');
            return [
                'success' => true,
                'message' => __('Connection verified successfully.', 'griffinforms-form-builder'),
            ];
        }

        $body    = wp_remote_retrieve_body($response);
        $message = 'OpenAI connection test failed: HTTP ' . $code . ' — ' . $body;
        $this->log->add('error', 'integration', 0, get_current_user_id(), $message, 'integration (openai)');

        return [
            'success' => false,
            'message' => sprintf(
                /* translators: %d: HTTP response code */
                __('OpenAI returned HTTP %d. Please check your API key.', 'griffinforms-form-builder'),
                $code
            ),
        ];
    }

    /**
     * No external library required.
     *
     * @return bool
     */
    public function isLibraryInstalled(): bool
    {
        return true;
    }

    /**
     * No library instructions required.
     *
     * @return string
     */
    public function getLibraryInstructions(): string
    {
        return '';
    }

    /**
     * Supported OpenAI model options.
     *
     * @return array slug => label
     */
    protected function getSupportedModels(): array
    {
        return [
            'gpt-4o-mini' => 'GPT-4o mini (Recommended)',
            'gpt-4o'      => 'GPT-4o',
        ];
    }

    /**
     * Render the configuration form HTML for the integrations modal.
     *
     * @return string
     */
    public function getConfigurationFormHtml(): string
    {
        $api_key       = $this->settings->getOption('gf_assist_openai_key', '');
        $saved_model   = $this->settings->getOption('gf_assist_default_model', 'gpt-4o-mini');
        $models        = $this->getSupportedModels();

        $factory = new \GriffinForms\Includes\Integrations\FormControls\Factory();

        $fields_html = '';

        // If no GriffinForms key is set but a WP Connector key is available, show a notice instead of the key input.
        $connector_key = trim($api_key) === '' ? $this->resolveConnectorApiKey('openai') : '';
        if ($connector_key !== '') {
            $fields_html .= '<div class="gf-notice gf-notice-info mb-3">' .
                wp_kses_post(__('Using API key from <strong>WordPress Settings → Connectors</strong>. Enter a key below to override it for GriffinForms specifically.', 'griffinforms-form-builder')) .
                '</div>';
        }

        // API Key field — masked password control
        $fields_html .= $factory->create(
            'password',
            'gf_assist_openai_key',
            $api_key,
            'openai',
            [
                'label'       => __('API Key', 'griffinforms-form-builder'),
                'type'        => 'password',
                'required'    => $connector_key === '',
                'description' => __('Your secret key from platform.openai.com. It is encrypted before storage.', 'griffinforms-form-builder'),
            ]
        )->render();

        // Model selector — flat slug => label map as required by Select control
        $fields_html .= $factory->create(
            'select',
            'gf_assist_default_model',
            $saved_model,
            'openai',
            [
                'label'       => __('Default Model', 'griffinforms-form-builder'),
                'required'    => false,
                'options'     => $this->getSupportedModels(),
                'description' => __('The model used for all Griffin Assist features unless overridden.', 'griffinforms-form-builder'),
            ]
        )->render();

        return $this->renderConfigurationFormTemplate('gf-openai-config-form', 'openai', $fields_html, [
            'show_remove' => trim($api_key) !== '',
        ]);
    }

    /**
     * JavaScript handler for the configuration form.
     *
     * @return string
     */
    public function getConfigurationJs(): string
    {
        return "
        (function() {
            const form = document.getElementById('gf-openai-config-form');
            if (!form) return;

            const cancelBtn = form.querySelector('.gf-integration-btn-cancel');
            if (cancelBtn) {
                cancelBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    window.loadIntegrationInfo('openai');
                });
            }

            const removeBtn = form.querySelector('.gf-integration-btn-remove');
            if (removeBtn) {
                removeBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    jQuery.ajax({
                        url: ajaxurl,
                        type: 'POST',
                        data: {
                            action: 'saveIntegrationConfiguration',
                            integration_id: 'openai',
                            nonce: window.griffinformsIntegrationsNonce || '',
                            gf_assist_openai_key: '',
                            gf_assist_default_model: 'gpt-4o-mini',
                        },
                        success: function(response) {
                            if (response.success) {
                                window.showIntegrationsMessage('success', 'OpenAI key removed.');
                                setTimeout(() => window.loadIntegrationInfo('openai'), 1000);
                            } else {
                                const msg = (response.data && response.data.msg) ? response.data.msg : 'Failed to remove key.';
                                window.showIntegrationsMessage('danger', msg);
                            }
                        },
                        error: function() {
                            window.showIntegrationsMessage('danger', 'Error removing OpenAI key.');
                        }
                    });
                });
            }

            form.addEventListener('submit', function(e) {
                e.preventDefault();

                const keyField  = form.querySelector('#gf-openai-gf_assist_openai_key');
                const modelField = form.querySelector('#gf-openai-gf_assist_default_model');

                if (keyField && keyField.required && !keyField.value.trim()) {
                    window.showIntegrationsMessage('danger', 'Please enter your OpenAI API key.');
                    return;
                }

                const data = {
                    action: 'saveIntegrationConfiguration',
                    integration_id: 'openai',
                    nonce: window.griffinformsIntegrationsNonce || '',
                    gf_assist_openai_key: keyField.value.trim(),
                    gf_assist_default_model: modelField ? modelField.value : 'gpt-4o-mini',
                };

                jQuery.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: data,
                    success: function(response) {
                        if (response.success) {
                            window.showIntegrationsMessage('success', 'OpenAI configuration saved.');
                            setTimeout(() => window.loadIntegrationInfo('openai'), 1000);
                        } else {
                            const msg = (response.data && response.data.msg) ? response.data.msg : 'Failed to save configuration.';
                            window.showIntegrationsMessage('danger', msg);
                        }
                    },
                    error: function() {
                        window.showIntegrationsMessage('danger', 'Error saving OpenAI configuration.');
                    }
                });
            });
        })();
        ";
    }
}
