<?php

namespace GriffinForms\Includes\Integrations\Googlerecaptcha;

use GriffinForms\Settings;
use GriffinForms\Includes\Integrations\FormSettingsManager;

/**
 * Google reCAPTCHA Integration
 *
 * Handles configuration and management of Google reCAPTCHA v2/v3
 * for form spam protection.
 *
 * @since 1.0.0
 */
class Main extends \GriffinForms\Includes\Integrations\Format
{
    /**
     * Set integration metadata key prefix
     */
    protected function setMeta()
    {
        $this->meta = 'recaptcha';
        $this->id = 'recaptcha';
    }

    /**
     * Build integration metadata/info
     *
     * @return array Integration metadata
     */
    protected function buildInfo(): array
    {
        return [
            'id'       => 'recaptcha',
            'name'     => 'Google reCAPTCHA',
            'category' => 'Security',
        ];
    }

    /**
     * Get current integration status
     *
     * @return array Status array
     */
    public function getStatus(): array
    {
        return [
            'configured' => $this->isConfigured(),
            'active'     => $this->isConfigured(),
            'message'    => $this->isConfigured() ? 'Configured' : 'Not configured',
        ];
    }

    /**
     * Get configuration form fields
     *
     * @return array Form field definitions
     */
    public function getConfigFields(): array
    {
        return [
            ['name' => 'recaptcha_version', 'label' => 'Version', 'type' => 'select'],
            ['name' => 'recaptcha_site_key', 'label' => 'Site Key', 'type' => 'text', 'required' => true],
            ['name' => 'recaptcha_secret_key', 'label' => 'Secret Key', 'type' => 'password', 'required' => true],
        ];
    }

    /**
     * Validate reCAPTCHA connection
     *
     * Makes a test API call to Google's servers to verify the secret key is valid.
     *
     * @return array ['success' => bool, 'message' => string]
     */
    protected function validateConnection(): array
    {
        $secret_key = $this->getOption('secret_key');
        $version = $this->getOption('version', 'v2');
        return $this->validateWithGoogle($secret_key, $version);
    }

    /**
     * Validate reCAPTCHA keys with Google's servers
     *
     * Makes a test verification request to Google's reCAPTCHA API
     * to ensure the secret key is valid.
     *
     * @param string $secret_key The reCAPTCHA secret key
     * @param string $version The reCAPTCHA version (v2 or v3)
     * @return array ['success' => bool, 'message' => string]
     */
    private function validateWithGoogle(string $secret_key, string $version): array
    {
        $api_url = 'https://www.google.com/recaptcha/api/siteverify';

        // Prepare request data
        $request_body = [
            'secret' => $secret_key,
            'response' => '',
        ];

        // Make the request
        $response = wp_remote_post($api_url, [
            'body'    => $request_body,
            'timeout' => 10,
        ]);

        // Check for network errors
        $form_id = $this->resolveFormContextId();

        if (is_wp_error($response)) {
            $message = 'Unable to reach Google reCAPTCHA servers: ' . $response->get_error_message();
            $this->log->add('error', 'form', $form_id, get_current_user_id(), $message, 'Integration (recaptcha)');
            return [
                'success' => false,
                'message' => 'Unable to reach Google reCAPTCHA servers. Please check your internet connection.',
            ];
        }

        $http_code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);

        // Check HTTP status
        if ($http_code !== 200) {
            $message = 'Google reCAPTCHA API returned HTTP ' . $http_code;
            $this->log->add('error', 'form', $form_id, get_current_user_id(), 'Admin test: ' . $message, 'Integration (recaptcha)');
            return [
                'success' => false,
                'message' => sprintf('Google reCAPTCHA API returned error code %d. Please verify your internet connection.', $http_code),
            ];
        }

        // Parse the response
        $result = json_decode($body, true);

        if (!is_array($result)) {
            $message = 'Invalid response from Google reCAPTCHA API - could not decode JSON.';
            $this->log->add('error', 'form', $form_id, get_current_user_id(), 'Admin test: ' . $message, 'Integration (recaptcha)');
            return [
                'success' => false,
                'message' => 'Invalid response from Google reCAPTCHA API.',
            ];
        }

        // Check if the API returned an error
        $error_codes = $result['error-codes'] ?? [];
        if (!empty($error_codes)) {
            $critical_errors = ['missing-input-secret', 'invalid-input-secret'];
            $non_critical = ['missing-input-response', 'invalid-input-response'];

            foreach ($error_codes as $code) {
                if (in_array($code, $critical_errors, true)) {
                    $user_message = $code === 'missing-input-secret'
                        ? __('Secret key is missing.', 'griffinforms-form-builder')
                        : __('Invalid secret key. Please verify your reCAPTCHA secret key is correct.', 'griffinforms-form-builder');
                    $this->log->add('error', 'form', $form_id, get_current_user_id(), 'Admin test: reCAPTCHA validation failed - ' . $code, 'Integration (recaptcha)');
                    return ['success' => false, 'message' => $user_message];
                }
            }

            $remaining = array_diff($error_codes, $non_critical);
            if (!empty($remaining)) {
                $this->log->add('error', 'form', $form_id, get_current_user_id(), 'Admin test: reCAPTCHA validation failed - ' . implode(', ', $remaining), 'Integration (recaptcha)');
                return [
                    'success' => false,
                    /* translators: %s: reCAPTCHA error message(s) */
                    'message' => sprintf(__('Google reCAPTCHA error: %s', 'griffinforms-form-builder'), implode(', ', $remaining)),
                ];
            }
        }

        // Success! The keys are valid (non-critical errors ignored)
        $message = 'Admin test: reCAPTCHA connection test successful - Version: ' . $version;
        $this->log->add('success', 'form', $form_id, get_current_user_id(), $message, 'Integration (recaptcha)');
        return [
            'success' => true,
            'message' => sprintf('reCAPTCHA %s is properly configured and working correctly.', strtoupper($version)),
        ];
    }

    /**
     * Check if external library is installed
     *
     * @return bool True if library is installed
     */
    public function isLibraryInstalled(): bool
    {
        // reCAPTCHA doesn't require external library
        return true;
    }

    /**
     * Get library installation instructions
     *
     * @return string Installation guide HTML
     */
    public function getLibraryInstructions(): string
    {
        return 'reCAPTCHA requires no additional libraries.';
    }

    /**
     * Check if reCAPTCHA is fully configured
     *
     * Configured means all required keys are set:
     * - Version is set (v2 or v3)
     * - Site key is set
     * - Secret key is set
     *
     * @return bool True if fully configured
     */
    public function isConfigured(): bool
    {
        $version = $this->settings->getOption('recaptcha_version');
        $site_key = $this->settings->getOption('recaptcha_site_key');
        $secret_key = $this->settings->getOption('recaptcha_secret_key');

        return !empty($version) && !empty($site_key) && !empty($secret_key);
    }

    /**
     * Get configuration form HTML
     *
     * Returns HTML markup for the reCAPTCHA configuration form
     * to be displayed in the integrations modal.
     *
     * @return string HTML form markup
     */
    public function getConfigurationFormHtml(): string
    {
        $version = $this->getOption('version', 'v2');
        $site_key = $this->getOption('site_key', '');
        $secret_key = $this->getOption('secret_key', '');

        // Import form control factory
        $factory = new \GriffinForms\Includes\Integrations\FormControls\Factory();

        // Build form fields with factory
        $fields_html = '';

        $fields_html .= $factory->create(
            'select',
            'recaptcha_version',
            $version,
            'recaptcha',
            [
                'label' => __('reCAPTCHA Version', 'griffinforms-form-builder'),
                'required' => true,
                'options' => [
                    'v2' => __('reCAPTCHA v2 (Checkbox)', 'griffinforms-form-builder'),
                    'v3' => __('reCAPTCHA v3 (Invisible)', 'griffinforms-form-builder'),
                ],
                'description' => __('v2 shows a checkbox, v3 runs invisibly in the background', 'griffinforms-form-builder'),
            ]
        )->render();

        $fields_html .= $factory->create(
            'text',
            'recaptcha_site_key',
            $site_key,
            'recaptcha',
            [
                'label' => __('Site Key', 'griffinforms-form-builder'),
                'type' => 'text',
                'required' => true,
                'description' => __('Get your Site Key from Google reCAPTCHA admin console', 'griffinforms-form-builder'),
            ]
        )->render();

        $fields_html .= $factory->create(
            'password',
            'recaptcha_secret_key',
            $secret_key,
            'recaptcha',
            [
                'label' => __('Secret Key', 'griffinforms-form-builder'),
                'type' => 'password',
                'required' => true,
                'description' => __('Keep this secret key private and never share it publicly', 'griffinforms-form-builder'),
            ]
        )->render();

        // Use base template
        return $this->renderConfigurationFormTemplate('gf-recaptcha-config-form', 'recaptcha', $fields_html);
    }

    /**
     * Get configuration JavaScript
     *
     * Returns JavaScript code for form handling and validation
     *
     * @return string JavaScript code
     */
    public function getConfigurationJs(): string
    {
        $js = "
        /**
         * reCAPTCHA Configuration Handler
         */
        (function() {
            const form = document.getElementById('gf-recaptcha-config-form');
            if (!form) return;

            const cancelBtn = form.querySelector('.gf-integration-btn-cancel');

            // Cancel button handler - goes back to info view
            if (cancelBtn) {
                cancelBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    window.loadIntegrationInfo('recaptcha');
                });
            }

            // Form submission handler
            form.addEventListener('submit', function(e) {
                e.preventDefault();

                const formId = window.griffinformsResolveActiveFormId ? window.griffinformsResolveActiveFormId() : null;
                // Validate required fields
                const version = form.querySelector('#gf-recaptcha-recaptcha_version').value;
                const siteKey = form.querySelector('#gf-recaptcha-recaptcha_site_key').value.trim();
                const secretKey = form.querySelector('#gf-recaptcha-recaptcha_secret_key').value.trim();

                if (!version || !siteKey || !secretKey) {
                    alert('Please fill in all required fields');
                    return;
                }

                // Collect form data
                const data = {
                    action: 'saveIntegrationConfiguration',
                    integration_id: 'recaptcha',
                    nonce: window.griffinformsIntegrationsNonce || '',
                    form_id: formId || '',
                    recaptcha_version: version,
                    recaptcha_site_key: siteKey,
                    recaptcha_secret_key: secretKey
                };

                // Send AJAX request
                jQuery.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: data,
                    success: function(response) {
                        if (response.success) {
                            window.showIntegrationsMessage('success', 'reCAPTCHA configuration saved successfully');
                            // Reload info view after brief delay to show updated status
                            setTimeout(() => {
                                window.loadIntegrationInfo('recaptcha');
                            }, 1000);
                        } else {
                            const message = (response.data && response.data.msg) ? response.data.msg : 'Failed to save configuration';
                            window.showIntegrationsMessage('danger', message);
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error('reCAPTCHA configuration error:', error);
                        window.showIntegrationsMessage('danger', 'Error saving reCAPTCHA configuration');
                    }
                });
            });
        })();
        ";

        return $js;
    }

    /**
     * Save configuration
     *
     * Saves reCAPTCHA configuration to WordPress options.
     * All keys are required - configuration is only saved if all are provided.
     *
     * @param array $config Configuration data
     * @return bool True if saved successfully
     */
    protected function saveConfiguration(array $config): bool
    {
        try {
            $version = isset($config['recaptcha_version']) ? sanitize_text_field($config['recaptcha_version']) : '';
            $site_key = isset($config['recaptcha_site_key']) ? sanitize_text_field($config['recaptcha_site_key']) : '';
            $secret_key = isset($config['recaptcha_secret_key']) ? sanitize_text_field($config['recaptcha_secret_key']) : '';

            // Validate all required fields
            if (empty($version) || !in_array($version, ['v2', 'v3'], true)) {
                return false;
            }
            if (empty($site_key) || empty($secret_key)) {
                return false;
            }

            // Save all required options
            $this->settings->updateOption('recaptcha_version', $version, 'antispam');
            $this->settings->updateOption('recaptcha_site_key', $site_key, 'antispam');
            $this->settings->updateOption('recaptcha_secret_key', $secret_key, 'antispam');
            $this->settings->updateOption('enable_recaptcha', 1, 'antispam');
            \GriffinForms\Includes\Integrations\Categories\Captcha::getInstance()->ensureActiveProvider($this->id);

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

    /**
     * Custom disable logic for reCAPTCHA
     *
     * Toggles the enable_recaptcha flag to 0 so the settings page
     * checkbox reflects the disabled state. Called by clearAllOptions()
     * after all configuration keys are removed.
     *
     * @return void
     */
    protected function onDisable()
    {
        // Toggle the enable_recaptcha flag to indicate integration is disabled
        $this->settings->updateOption('enable_recaptcha', 0, 'antispam');
    }

    /**
     * Per-form settings schema
     */
    public function getFormSettingsSchema(): array
    {
        return [
            [
                'name' => 'disable_recaptcha',
                'type' => 'checkbox',
                'label' => __('Disable reCAPTCHA on this form', 'griffinforms-form-builder'),
            ],
        ];
    }

    /**
     * Default per-form settings
     */
    public function getDefaultFormSettings(): array
    {
        return [
            'disable_recaptcha' => false,
        ];
    }

    /**
     * Validate per-form settings
     *
     * @param array $settings
     * @return array|\WP_Error
     */
    public function validateFormSettings(array $settings)
    {
        $disable = $this->toBoolean($settings['disable_recaptcha'] ?? false);

        return [
            'disable_recaptcha' => $disable,
        ];
    }

    /**
     * Determine if reCAPTCHA is enabled for a specific form (or globally)
     *
     * Checks per-form override first; falls back to global antispam option.
     */
    public function isEnabledForForm(int $form_id = 0): bool
    {
        $manager = FormSettingsManager::getInstance();
        if ($form_id > 0) {
            $form_settings = $manager->getIntegrationSettings($form_id, $this->id);
            if (empty($form_settings)) {
                // No per-form record; defer to global setting
                return (bool) $this->settings->getOption('enable_recaptcha', false);
            }

            if (is_array($form_settings)) {
                $mode = $form_settings['mode'] ?? 'inherit';
                $settings = $form_settings['settings'] ?? [];

                if ($mode === 'disabled') {
                    return false;
                }

                $disable = $this->toBoolean($settings['disable_recaptcha'] ?? false);
                if ($disable) {
                    return false;
                }
            }
        }

        // Fallback to global or active-provider status
        $legacy_enabled = (bool) $this->settings->getOption('enable_recaptcha', false);
        if ($legacy_enabled) {
            return true;
        }

        $active = sanitize_key($this->settings->getOption('active_captcha_provider', ''));
        return $active === $this->id && $this->isConfigured();
    }

}
