<?php

namespace GriffinForms\Frontend\Html\Security\Captcha;

/**
 * Google reCAPTCHA frontend adapter.
 */
class Recaptcha extends Format
{
    private $token_key = 'recaptcha';
    private $log;

    public function isEnabled(): bool
    {
        $active = sanitize_key($this->options['active_captcha_provider'] ?? '');
        if ($active !== 'recaptcha') {
            return false;
        }

        if (array_key_exists('enable_recaptcha', $this->options) && !$this->toBool($this->options['enable_recaptcha'])) {
            return false;
        }

        return !empty($this->getSiteKey()) && !empty($this->options['recaptcha_secret_key'] ?? '');
    }

    public function renderField(string $position): string
    {
        if (!$this->shouldRender($position)) {
            return '';
        }

        if ($this->getVersion() === 'v2') {
            // TODO: Phase 3 - Support re-rendering v2 widgets on subsequent pages.
            $html  = '<div class="griffinform-recaptchaV2-container d-flex justify-content-center">';
            $html .= '<div class="g-recaptcha" data-sitekey="' . esc_attr($this->getSiteKey()) . '"></div>';
            $html .= '</div>';
            return $html;
        }

        return '';
    }

    public function enqueueScripts(): void
    {
        if (!$this->isEnabled()) {
            return;
        }

        $version = $this->getVersion();
        if ($version === 'v2') {
            wp_enqueue_script('griffinforms-google-recaptcha', 'https://www.google.com/recaptcha/api.js?render=explicit&onload=griffinformsRecaptchaReady', [], '2.0', false);
        } elseif ($version === 'v3') {
            $url = 'https://www.google.com/recaptcha/api.js?render=' . rawurlencode($this->getSiteKey());
            wp_enqueue_script('griffinforms-google-recaptcha', $url, [], '3.0', false);
        }
    }

    public function getTokenKey(): string
    {
        return $this->token_key;
    }

    public function getClientContext(): array
    {
        return [
            'enabled' => $this->isEnabled(),
            'id'      => 'recaptcha',
            'token_key' => $this->token_key,
            'version' => $this->getVersion(),
            'site_key' => $this->getSiteKey(),
            'limit_to_first_page' => false,
        ];
    }

    public function validateSubmission($antispam_data, array $form_data): array
    {
        $this->initializeLogger();

        $version = $this->getVersion();
        if ($version === 'v2' && !$this->shouldRender($form_data['position'] ?? '')) {
            return ['success' => true];
        }

        $token = $antispam_data->{$this->token_key} ?? '';
        if (empty($token)) {
            return ['success' => false, 'message' => __('Unable to submit. reCAPTCHA input missing.', 'griffinforms-form-builder')];
        }

        $secret = $this->options['recaptcha_secret_key'] ?? '';
        if (empty($secret)) {
            return ['success' => false, 'message' => __('reCAPTCHA secret key missing.', 'griffinforms-form-builder')];
        }

        $response = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', [
            'body' => [
                'secret' => $secret,
                'response' => $token,
            ],
        ]);

        if (is_wp_error($response)) {
            return ['success' => false, 'message' => sprintf(__('reCAPTCHA request failed: %s', 'griffinforms-form-builder'), $response->get_error_message())];
        }

        $result = json_decode(wp_remote_retrieve_body($response), true);
        if (!is_array($result)) {
            return ['success' => false, 'message' => __('Invalid response from Google reCAPTCHA API.', 'griffinforms-form-builder')];
        }

        if (($result['success'] ?? false) !== true) {
            if ($this->log) {
                $this->log->add(
                    'warning',
                    'form',
                    (int) $this->form_id,
                    get_current_user_id(),
                    'reCAPTCHA validation failed. Codes: ' . wp_json_encode($result['error-codes'] ?? []),
                    'security'
                );
            }
            return ['success' => false, 'message' => __('Unable to submit. reCAPTCHA assessment failed.', 'griffinforms-form-builder')];
        }

        if ($version === 'v3' && isset($result['score']) && (float) $result['score'] < 0.5) {
            if ($this->log) {
                $this->log->add(
                    'warning',
                    'form',
                    (int) $this->form_id,
                    get_current_user_id(),
                    'reCAPTCHA v3 score too low. Score: ' . wp_json_encode($result['score']) . '. Action: ' . wp_json_encode($result['action'] ?? ''),
                    'security'
                );
            }
            return ['success' => false, 'message' => __('Unable to submit. reCAPTCHA score too low.', 'griffinforms-form-builder')];
        }

        return ['success' => true];
    }

    private function initializeLogger(): void
    {
        if ($this->log) {
            return;
        }

        if (class_exists('\\GriffinForms\\Log')) {
            $this->log = \GriffinForms\Log::getInstance();
        }
    }

    private function shouldRender(string $position): bool
    {
        if (!$this->isEnabled()) {
            return false;
        }

        if ($this->getVersion() === 'v2') {
            return in_array($position, ['first', 'single', 'middle', 'last'], true);
        }

        return true;
    }

    private function getVersion(): string
    {
        return $this->options['recaptcha_version'] ?? 'v2';
    }

    private function getSiteKey(): string
    {
        if (!empty($this->options['recaptcha_site_key'])) {
            return $this->options['recaptcha_site_key'];
        }

        $registry_instance = \GriffinForms\Includes\Integrations\Categories\Captcha::getInstance();
        $integration = $registry_instance ? $registry_instance->getActiveIntegration($this->form_id) : null;
        if ($integration && method_exists($integration, 'getOption')) {
            return (string) $integration->getOption('recaptcha_site_key');
        }

        return '';
    }

    private function toBool($value): bool
    {
        if (is_string($value)) {
            $value = strtolower(trim($value));
            return in_array($value, ['1', 'true', 'on', 'yes'], true);
        }

        return (bool) $value;
    }
}
