<?php

/**
 * CAPTCHA Integration for Guard Dog
 * 
 * Supports multiple CAPTCHA providers:
 * - Google reCAPTCHA v2 (Checkbox)
 * - Google reCAPTCHA v3 (Invisible)
 * - Cloudflare Turnstile
 * 
 * @package GuardDog
 * @since 1.2.0
 */

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

class Guard_Dog_Captcha {
    
    /**
     * CAPTCHA provider constants
     */
    const PROVIDER_NONE = 'none';
    const PROVIDER_RECAPTCHA_V2 = 'recaptcha_v2';
    const PROVIDER_RECAPTCHA_V3 = 'recaptcha_v3';
    const PROVIDER_HCAPTCHA = 'hcaptcha';
    const PROVIDER_TURNSTILE = 'turnstile';
    
    /**
     * reCAPTCHA API endpoints
     */
    const RECAPTCHA_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
    const RECAPTCHA_API_URL = 'https://www.google.com/recaptcha/api.js';
    const RECAPTCHA_ENTERPRISE_API_URL = 'https://www.google.com/recaptcha/enterprise.js';
    
    /**
     * hCaptcha API endpoints
     */
    const HCAPTCHA_VERIFY_URL = 'https://hcaptcha.com/siteverify';
    const HCAPTCHA_API_URL = 'https://js.hcaptcha.com/1/api.js';
    
    /**
     * Turnstile API endpoints
     */
    const TURNSTILE_VERIFY_URL = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
    const TURNSTILE_API_URL = 'https://challenges.cloudflare.com/turnstile/v0/api.js';

    /**
     * Untranslated fallback default for CAPTCHA error messaging.
     *
     * @var string
     */
    const DEFAULT_ERROR_MESSAGE = 'Please complete the CAPTCHA verification.';
    
    /**
     * Instance of this class
     *
     * @var Guard_Dog_Captcha
     */
    private static $instance;
    
    /**
     * Current CAPTCHA provider
     *
     * @var string
     */
    private $provider;
    
    /**
     * CAPTCHA configuration
     *
     * @var array
     */
    private $config;
    
    /**
     * Initialize the CAPTCHA system
     */
    public function __construct() {
        $this->provider = get_option('guard_dog_captcha_provider', self::PROVIDER_NONE);
        
        // Handle NULL or empty provider values (emergency fix)
        if (empty($this->provider) || is_null($this->provider)) {
            $this->provider = self::PROVIDER_NONE;
        }
        
        $this->config = $this->get_captcha_config();
        
        $this->init_hooks();
    }
    
    /**
     * Get singleton instance
     *
     * @return Guard_Dog_Captcha
     */
    public static function instance(): Guard_Dog_Captcha {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Initialize WordPress hooks
     */
    private function init_hooks(): void {
        // Only add CAPTCHA hooks if a provider is actually enabled
        if ($this->provider === self::PROVIDER_NONE || empty($this->config['site_key'])) {
            return;
        }
        
        // Add CAPTCHA to login form
        add_action('login_form', [$this, 'render_captcha']);
        
        // Add CAPTCHA provider class to login container
        add_action('login_head', [$this, 'add_captcha_provider_class']);
        
        // Verify CAPTCHA on login
        add_filter('wp_authenticate_user', [$this, 'verify_captcha_on_login'], 10, 2);
        
        // Add CAPTCHA to registration form
        add_action('register_form', [$this, 'render_captcha']);
        
        // Add CAPTCHA provider class to registration container
        add_action('login_head', [$this, 'add_captcha_provider_class']);
        
        // Verify CAPTCHA on registration
        add_filter('registration_errors', [$this, 'verify_captcha_on_registration'], 10, 3);
        
        // Add CAPTCHA to password reset form
        add_action('lostpassword_form', [$this, 'render_captcha']);
        
        // Verify CAPTCHA on password reset
        add_action('lostpassword_post', [$this, 'verify_captcha_on_password_reset']);
        
        // Enqueue scripts and styles only on login pages
        add_action('login_enqueue_scripts', [$this, 'enqueue_captcha_scripts']);
        add_action('login_enqueue_scripts', [$this, 'enqueue_captcha_styles']);
        
        // Enqueue scripts and styles on frontend only for registration/login forms
        add_action('wp_enqueue_scripts', [$this, 'enqueue_captcha_scripts_frontend']);
        add_action('wp_enqueue_scripts', [$this, 'enqueue_captcha_styles']);
    }
    
    /**
     * Get CAPTCHA configuration
     *
     * @return array
     */
    /**
     * Get relevant POST keys for CAPTCHA debug logging (only CAPTCHA-specific fields)
     *
     * @return array Array of relevant POST keys
     */
    private function get_relevant_captcha_post_keys(): array {
        $relevant_keys = [];
        $expected_keys = ['_wpnonce', 'g-recaptcha-response', 'guard_dog_recaptcha_token', 'h-captcha-response', 'cf-turnstile-response', 'action'];
        
        foreach ($expected_keys as $key) {
            if (isset($_POST[$key])) {
                $relevant_keys[] = $key;
            }
        }
        
        return $relevant_keys;
    }

    /**
     * Get the default CAPTCHA error message.
     *
     * Avoids triggering translation loading before init while preserving
     * localization once WordPress initialization has progressed.
     *
     * @return string
     */
    private function get_default_error_message(): string {
        if ( did_action( 'init' ) || doing_action( 'init' ) ) {
            return __( self::DEFAULT_ERROR_MESSAGE, 'guard-dog' );
        }

        return self::DEFAULT_ERROR_MESSAGE;
    }

    private function get_captcha_config(): array {
        $provider = $this->get_provider();
        $default_error_message = $this->get_default_error_message();
        
        // If no provider is selected, return empty configuration
        if ($provider === self::PROVIDER_NONE) {
            return [
                'site_key' => '',
                'secret_key' => '',
                'theme' => 'light',
                'size' => 'normal',
                'v3_score_threshold' => 0.5,
                'error_message' => get_option('guard_dog_captcha_error_message', $default_error_message),
            ];
        }
        
        return [
            'site_key' => get_option('guard_dog_' . $provider . '_site_key', ''),
            'secret_key' => get_option('guard_dog_' . $provider . '_secret_key', ''),
            'theme' => get_option('guard_dog_recaptcha_v2_theme', 'light'),
            'size' => get_option('guard_dog_recaptcha_v2_size', 'normal'),
            'v3_score_threshold' => get_option('guard_dog_recaptcha_v3_threshold', 0.5),
            'error_message' => get_option('guard_dog_captcha_error_message', $default_error_message),
        ];
    }
    
    /**
     * Render CAPTCHA on forms
     */
    public function render_captcha(): void {
        if ($this->provider === self::PROVIDER_NONE || empty($this->config['site_key'])) {
            return;
        }
        
        // Add nonce field for CAPTCHA verification
        wp_nonce_field('login', '_wpnonce', true, true);
        
        Guard_Dog_View_Loader::render_partial('captcha-render', [
            'provider' => $this->provider,
            'config' => $this->config
        ]);
    }
    
    /**
     * Add CAPTCHA provider class to login container
     */
    public function add_captcha_provider_class(): void {
        if ($this->provider === self::PROVIDER_NONE || empty($this->config['site_key'])) {
            return;
        }
        
        // Map provider constants to CSS-friendly class names
        $provider_classes = [
            self::PROVIDER_RECAPTCHA_V2 => 'captcha-recaptcha-v2',
            self::PROVIDER_RECAPTCHA_V3 => 'captcha-recaptcha-v3',
            self::PROVIDER_HCAPTCHA => 'captcha-hcaptcha',
            self::PROVIDER_TURNSTILE => 'captcha-turnstile'
        ];
        
        $provider_class = $provider_classes[$this->provider] ?? '';
        
        if ($provider_class) {
            // Enqueue CAPTCHA login styles
            wp_enqueue_style(
                'guard-dog-captcha-login',
                plugins_url('assets/css/guard-dog-captcha-login.css', dirname(dirname(__FILE__))),
                [],
                GUARD_DOG_VERSION
            );
            
            // Enqueue CAPTCHA login JavaScript
            wp_enqueue_script(
                'guard-dog-captcha-login',
                plugins_url('assets/js/guard-dog-captcha-login.js', dirname(dirname(__FILE__))),
                [],
                GUARD_DOG_VERSION,
                true
            );
            
            // Pass the provider class to JavaScript
            wp_localize_script('guard-dog-captcha-login', 'guard_dog_captcha', [
                'providerClass' => $provider_class
            ]);
        }
    }
    
    /**
     * Enqueue CAPTCHA scripts
     */
    public function enqueue_captcha_scripts(): void {
        // Get debug instance for logging
        $debug = null;
        if (isset($GLOBALS['guard_dog']) && $GLOBALS['guard_dog']->debug) {
            $debug = $GLOBALS['guard_dog']->debug;
        }
        
        // Check if we're on the 2FA page - don't load CAPTCHA scripts there
        $action = filter_input(INPUT_GET, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
        if ($action === null) {
            $action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
        }
        
        // Check for state-token-based 2FA flow
        $login_state = Guard_Dog_Utils::consume_login_state();
        $has_2fa_state = is_array($login_state) && isset($login_state['type']) && $login_state['type'] === '2fa';

        // Skip CAPTCHA scripts on 2FA pages only
        if ($action === 'guard_dog_2fa') {
            return;
        }

        // Only skip if we have a 2FA state AND we're not on the main login page
        if ($has_2fa_state && $action !== '') {
            return;
        }

        if ($this->provider === self::PROVIDER_NONE || empty($this->config['site_key'])) {
            return;
        }

        switch ($this->provider) {
            case self::PROVIDER_RECAPTCHA_V2:
                // Enqueue Google reCAPTCHA v2 API
                wp_enqueue_script('google-recaptcha', self::RECAPTCHA_API_URL, [], null, true); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- External API script, version controlled by provider
                
                // Enqueue our custom script
                wp_enqueue_script(
                    'guard-dog-recaptcha-v2',
                    plugins_url('assets/js/guard-dog-captcha-recaptcha-v2.js', dirname(dirname(__FILE__))),
                    ['google-recaptcha'],
                    GUARD_DOG_VERSION,
                    true
                );
                
                if ($debug) {
                    $debug->captcha('Enqueued reCAPTCHA v2 scripts');
                }
                break;
                
            case self::PROVIDER_RECAPTCHA_V3:
                // Use standard API by default (enterprise API is for Google Cloud customers)
                $use_enterprise = get_option('guard_dog_captcha_use_enterprise', false);
                $base_url = $use_enterprise ? self::RECAPTCHA_ENTERPRISE_API_URL : self::RECAPTCHA_API_URL;
                
                // For standard API, add render parameter; for enterprise, it's not needed
                if ($use_enterprise) {
                    $script_url = $base_url;
                } else {
                    $script_url = add_query_arg(['render' => $this->config['site_key']], $base_url);
                }
                
                // Enqueue Google reCAPTCHA v3 API
                wp_enqueue_script('google-recaptcha-v3', $script_url, [], null, true); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- External API script, version controlled by provider
                
                // Enqueue our custom script (without dependency to avoid loading issues)
                wp_enqueue_script(
                    'guard-dog-recaptcha-v3',
                    plugins_url('assets/js/guard-dog-captcha-recaptcha-v3.js', dirname(dirname(__FILE__))),
                    [], // Remove dependency to avoid loading order issues
                    GUARD_DOG_VERSION,
                    true
                );
                
                // Pass configuration to JavaScript
                wp_localize_script('guard-dog-recaptcha-v3', 'guard_dog_captcha', [
                    'sitekey' => $this->config['site_key'],
                    'action' => 'login',
                    'debug' => defined('WP_DEBUG') && WP_DEBUG,
                    'scriptUrl' => $script_url,
                    'domain' => isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : 'unknown',
                    'useEnterprise' => $use_enterprise
                ]);
                
                if ($debug) {
                    $debug->captcha('Enqueued reCAPTCHA v3 scripts');
                }
                break;
                
            case self::PROVIDER_HCAPTCHA:
                // Enqueue hCaptcha API
                wp_enqueue_script('hcaptcha-api', self::HCAPTCHA_API_URL, [], null, true); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- External API script, version controlled by provider
                
                // Enqueue our custom script
                wp_enqueue_script(
                    'guard-dog-hcaptcha',
                    plugins_url('assets/js/guard-dog-captcha-hcaptcha.js', dirname(dirname(__FILE__))),
                    ['hcaptcha-api'],
                    GUARD_DOG_VERSION,
                    true
                );
                
                // Pass configuration to JavaScript
                wp_localize_script('guard-dog-hcaptcha', 'guard_dog_captcha', [
                    'sitekey' => $this->config['site_key'],
                    'theme' => $this->config['theme'],
                    'size' => $this->config['size'],
                    'debug' => defined('WP_DEBUG') && WP_DEBUG,
                    'domain' => isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : 'unknown'
                ]);
                
                if ($debug) {
                    $debug->captcha('Enqueued hCaptcha scripts');
                }
                break;
                
            case self::PROVIDER_TURNSTILE:
                // Enqueue Cloudflare Turnstile API
                wp_enqueue_script('cloudflare-turnstile', self::TURNSTILE_API_URL, [], null, true); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- External API script, version controlled by provider
                
                // Enqueue our custom script
                wp_enqueue_script(
                    'guard-dog-turnstile',
                    plugins_url('assets/js/guard-dog-captcha-cloudflare.js', dirname(dirname(__FILE__))),
                    ['cloudflare-turnstile'],
                    GUARD_DOG_VERSION,
                    true
                );
                
                // Pass configuration to JavaScript
                wp_localize_script('guard-dog-turnstile', 'guard_dog_captcha', [
                    'sitekey' => $this->config['site_key'],
                    'theme' => $this->config['theme'],
                    'debug' => defined('WP_DEBUG') && WP_DEBUG,
                    'domain' => isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : 'unknown'
                ]);
                
                if ($debug) {
                    $debug->captcha('Enqueued Turnstile scripts');
                }
                break;
        }
    }
    
    /**
     * Enqueue CAPTCHA styles
     */
    public function enqueue_captcha_styles(): void {
        // Check if we're on the 2FA page - don't load CAPTCHA styles there
        $action = filter_input(INPUT_GET, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
        if ($action === null) {
            $action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
        }
        
        // Check for state-token-based 2FA flow
        $login_state = Guard_Dog_Utils::consume_login_state();
        $has_2fa_state = is_array($login_state) && isset($login_state['type']) && $login_state['type'] === '2fa';

        // Skip CAPTCHA styles on 2FA pages only
        if ($action === 'guard_dog_2fa') {
            return;
        }

        // Only skip if we have a 2FA state AND we're not on the main login page
        if ($has_2fa_state && $action !== '') {
            return;
        }
        
        if ($this->provider === self::PROVIDER_NONE || empty($this->config['site_key'])) {
            return;
        }
        
        wp_enqueue_style(
            'guard-dog-captcha-styles',
            plugins_url('assets/css/guard-dog-captcha.css', dirname(dirname(__FILE__))),
            [],
            GUARD_DOG_VERSION
        );
    }
    
    /**
     * Enqueue CAPTCHA scripts on frontend (only when needed)
     */
    public function enqueue_captcha_scripts_frontend(): void {
        // Only enqueue on pages that might have registration forms
        // or if we're on a page with custom login forms
        if (!is_admin() && (is_page() || is_single() || is_front_page())) {
            // Check if the page content contains registration forms or login forms
            global $post;
            if ($post && (
                strpos($post->post_content, 'wp_login_form') !== false ||
                strpos($post->post_content, '[registration') !== false ||
                strpos($post->post_content, 'loginform') !== false ||
                get_option('users_can_register') // WordPress registration enabled
            )) {
                $this->enqueue_captcha_scripts();
                $this->enqueue_captcha_styles();
            }
        }
    }
    
    /**
     * Verify CAPTCHA on login
     *
     * @param WP_User|WP_Error $user
     * @param string $password
     * @return WP_User|WP_Error
     */
    public function verify_captcha_on_login($user, string $password) {
        // Safety check: if CAPTCHA is disabled, allow through
        if ($this->provider === self::PROVIDER_NONE || empty($this->config['secret_key'])) {
            return $user;
        }
        
        if (is_wp_error($user)) {
            return $user;
        }
        if (isset($_POST['guard_dog_2fa_interim_login']) && sanitize_text_field(wp_unslash($_POST['guard_dog_2fa_interim_login'])) === '1') {
            // For 2FA steps, check if we have a stored CAPTCHA token in transient data
            $username = filter_input(INPUT_POST, 'log', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
            if ($username) {
                $transient_key = 'guard_dog_2fa_user_' . hash( 'sha256', $username );
                $transient_data = get_transient($transient_key);
                if ($transient_data && !empty($transient_data['captcha_token'])) {
                    // We have a stored CAPTCHA token, so allow the 2FA step to proceed
                    return $user;
                }
            }
            // No stored CAPTCHA token, but this is a 2FA step, so allow through
            return $user;
        }
        
        if (!$this->verify_captcha_response()) {
            return new WP_Error('captcha_failed', $this->config['error_message']);
        }
        
        return $user;
    }
    
    /**
     * Verify CAPTCHA on registration
     *
     * @param WP_Error $errors
     * @param string $sanitized_user_login
     * @param string $user_email
     * @return WP_Error
     */
    public function verify_captcha_on_registration(WP_Error $errors, string $sanitized_user_login, string $user_email): WP_Error {
        // Safety check: if CAPTCHA is disabled, allow through
        if ($this->provider === self::PROVIDER_NONE || empty($this->config['secret_key'])) {
            return $errors;
        }
        
        if (!$this->verify_captcha_response()) {
            $errors->add('captcha_failed', $this->config['error_message']);
        }
        
        return $errors;
    }
    
    /**
     * Verify CAPTCHA on password reset
     */
    public function verify_captcha_on_password_reset(): void {
        // Safety check: if CAPTCHA is disabled, allow through
        if ($this->provider === self::PROVIDER_NONE || empty($this->config['secret_key'])) {
            return;
        }
        
        if (!$this->verify_captcha_response()) {
            wp_safe_redirect(add_query_arg('captcha_error', '1', wp_login_url() . '?action=lostpassword'));
            exit;
        }
    }
    
    /**
     * Verify CAPTCHA response
     *
     * @return bool
     */
    private function verify_captcha_response(): bool {
        // Safety check: if CAPTCHA is disabled, allow through immediately
        if ($this->provider === self::PROVIDER_NONE || empty($this->config['secret_key'])) {
            return true; // No CAPTCHA configured, allow through
        }
        
        try {
            // Initialize debug logging
            $debug = null;
            if (isset($GLOBALS['guard_dog']) && $GLOBALS['guard_dog']->debug) {
                $debug = $GLOBALS['guard_dog']->debug;
            }
            
            if ($debug) {
                $debug->captcha('Starting CAPTCHA verification', [
                    'provider' => $this->provider,
                    'config_available' => !empty($this->config['secret_key'])
                ]);
            }
            
            $response_token = $this->get_captcha_response_token();
            if ($debug) {
                $debug->captcha('Response token retrieved', [
                    'token_present' => !empty($response_token),
                    'token_length' => strlen($response_token)
                ]);
            }
            
            if (empty($response_token)) {
                if ($debug) {
                    $debug->captcha('No response token found - verification failed');
                }
                return false;
            }
            
            $verification_result = $this->verify_with_provider($response_token);
            if ($debug) {
                $debug->captcha('Verification result: ' . ($verification_result ? 'success' : 'failed'));
            }
            
            // Log CAPTCHA verification attempts (with error handling)
            try {
                // Access activity log through the main Guard Dog instance
                if (isset($GLOBALS['guard_dog']) && $GLOBALS['guard_dog']->activity_log) {
                    $activity_log = $GLOBALS['guard_dog']->activity_log;
                    if (method_exists($activity_log, 'add_log_entry')) {
                        $posted_username = isset($_POST['log']) ? sanitize_user(sanitize_text_field(wp_unslash($_POST['log'])), true) : '';
                        $current_user = wp_get_current_user();
                        $final_username = $posted_username ?: ($current_user && $current_user->exists() ? $current_user->user_login : 'Unknown');

                        $activity_log->add_log_entry(
                            'captcha_verification',
                            [
                                'username' => $final_username,
                                'user_id' => ($current_user && $current_user->exists()) ? $current_user->ID : null,
                                'ip_address' => $this->get_client_ip(),
                                'details' => [
                                    'provider' => $this->provider,
                                    'success' => (bool) $verification_result
                                ],
                            ]
                        );
                    }
                }
            } catch (Exception $e) {
                // Silently fail activity logging to prevent breaking CAPTCHA functionality
                if ($debug) {
                    $debug->captcha('Activity logging failed: ' . $e->getMessage());
                }
            }
            
            return $verification_result;
            
        } catch (Exception $e) {
            if (isset($GLOBALS['guard_dog']) && $GLOBALS['guard_dog']->debug) {
                $GLOBALS['guard_dog']->debug->error('Fatal error in verify_captcha_response: ' . $e->getMessage(), 'captcha', [
                    'stack_trace' => $e->getTraceAsString()
                ]);
            }
            return false; // Fail secure
        }
    }
    
    /**
     * Get CAPTCHA response token from request
     *
     * @return string
     */
    private function get_captcha_response_token(): string {
        // Get debug instance for logging
        $debug = null;
        if (isset($GLOBALS['guard_dog']) && $GLOBALS['guard_dog']->debug) {
            $debug = $GLOBALS['guard_dog']->debug;
        }
        
        $token = '';

        // Check for nonce - fail early if missing or invalid
        if (!isset($_POST['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'login')) {
            if ($debug) {
                $debug->captcha('Nonce missing or invalid');
            }
            return '';
        }
        
        switch ($this->provider) {
            case self::PROVIDER_RECAPTCHA_V2:
                $token = isset($_POST['g-recaptcha-response']) ? sanitize_text_field(wp_unslash($_POST['g-recaptcha-response'])) : '';
                if ($debug) {
                    $debug->captcha('reCAPTCHA v2 token retrieval', [
                        'field_name' => 'g-recaptcha-response',
                        'token_present' => !empty($token),
                        'token_length' => strlen($token),
                        'relevant_post_keys' => $this->get_relevant_captcha_post_keys()
                    ]);
                }
                break;
                
            case self::PROVIDER_RECAPTCHA_V3:
                // Try HTML approach first (g-recaptcha-response), then programmatic approach
                $html_token = isset($_POST['g-recaptcha-response']) ? sanitize_text_field(wp_unslash($_POST['g-recaptcha-response'])) : '';
                $prog_token = isset($_POST['guard_dog_recaptcha_token']) ? sanitize_text_field(wp_unslash($_POST['guard_dog_recaptcha_token'])) : '';
                $token = $html_token ?: $prog_token;
                if ($debug) {
                    $debug->captcha('reCAPTCHA v3 token retrieval', [
                        'html_approach_token' => !empty($html_token),
                        'programmatic_token' => !empty($prog_token),
                        'final_token_present' => !empty($token),
                        'token_length' => strlen($token),
                        'relevant_post_keys' => $this->get_relevant_captcha_post_keys()
                    ]);
                }
                break;
                
            case self::PROVIDER_HCAPTCHA:
                $token = isset($_POST['h-captcha-response']) ? sanitize_text_field(wp_unslash($_POST['h-captcha-response'])) : '';
                if ($debug) {
                    $debug->captcha('hCaptcha token retrieval', [
                        'field_name' => 'h-captcha-response',
                        'token_present' => !empty($token),
                        'token_length' => strlen($token),
                        'relevant_post_keys' => $this->get_relevant_captcha_post_keys()
                    ]);
                }
                break;
                
            case self::PROVIDER_TURNSTILE:
                $raw_token = isset($_POST['cf-turnstile-response']) ? sanitize_text_field(wp_unslash($_POST['cf-turnstile-response'])) : '';
                $token = $raw_token;
                if ($debug) {
                    $debug->captcha('Turnstile token retrieval', [
                        'field_name' => 'cf-turnstile-response',
                        'raw_token_present' => !empty($raw_token),
                        'raw_token_length' => strlen($raw_token),
                        'sanitized_token_present' => !empty($token),
                        'sanitized_token_length' => strlen($token),
                        'raw_token_preview' => !empty($raw_token) ? substr($raw_token, 0, 20) . '...' : 'empty',
                        'relevant_post_keys' => $this->get_relevant_captcha_post_keys()
                    ]);
                }
                break;
                
            default:
                if ($debug) {
                    $debug->captcha('Unknown CAPTCHA provider', ['provider' => $this->provider]);
                }
                return '';
        }
        
        return $token;
    }
    
    /**
     * Verify CAPTCHA with the provider
     *
     * @param string $response_token
     * @return bool
     */
    private function verify_with_provider(string $response_token): bool {
        try {
            // Get debug instance for logging
            $debug = null;
            if (isset($GLOBALS['guard_dog']) && $GLOBALS['guard_dog']->debug) {
                $debug = $GLOBALS['guard_dog']->debug;
            }
            
            $verify_url = $this->get_verify_url();
            if ($debug) {
                $debug->captcha('Verify URL: ' . $verify_url);
            }
            
            if (empty($verify_url)) {
                if ($debug) {
                    $debug->captcha('No verify URL for provider: ' . $this->provider);
                }
                return false;
            }
            
            $post_data = [
                'secret' => $this->config['secret_key'],
                'response' => $response_token,
                'remoteip' => $this->get_client_ip()
            ];
            
            if ($debug) {
                $debug->captcha('Sending verification request');
            }
            
            $response = wp_remote_post($verify_url, [
                'body' => $post_data,
                'timeout' => 10,
                'headers' => [
                    'Content-Type' => 'application/x-www-form-urlencoded'
                ]
            ]);
            
            if (is_wp_error($response)) {
                if ($debug) {
                    $debug->captcha('wp_remote_post error: ' . $response->get_error_message());
                }
                return false;
            }
            
            $body = wp_remote_retrieve_body($response);
            if ($debug) {
                $debug->captcha('Response body: ' . $body);
            }
            
            $result = json_decode($body, true);
            
            if (!$result || !isset($result['success'])) {
                if ($debug) {
                    $debug->captcha('Invalid JSON response or missing success field');
                }
                return false;
            }
            
            if (!$result['success']) {
                $errors = isset($result['error-codes']) ? implode(', ', $result['error-codes']) : 'Unknown error';
                if ($debug) {
                    $debug->captcha('Verification failed with errors: ' . $errors);
                }
            }
            
            // For reCAPTCHA v3, also check the score
            if ($this->provider === self::PROVIDER_RECAPTCHA_V3) {
                $score = $result['score'] ?? 0;
                if ($debug) {
                    $debug->captcha('reCAPTCHA v3 score: ' . $score);
                }
                return $result['success'] && $score >= $this->config['v3_score_threshold'];
            }
            
            return $result['success'];
            
        } catch (Exception $e) {
            if ($debug) {
                $debug->captcha('Exception in verify_with_provider: ' . $e->getMessage());
            }
            return false;
        }
    }
    
    /**
     * Get verification URL for current provider
     *
     * @return string
     */
    private function get_verify_url(): string {
        switch ($this->provider) {
            case self::PROVIDER_RECAPTCHA_V2:
            case self::PROVIDER_RECAPTCHA_V3:
                return self::RECAPTCHA_VERIFY_URL;
                
            case self::PROVIDER_HCAPTCHA:
                return self::HCAPTCHA_VERIFY_URL;
                
            case self::PROVIDER_TURNSTILE:
                return self::TURNSTILE_VERIFY_URL;
                
            default:
                return '';
        }
    }
    
    /**
     * Get client IP address.
     *
     * Delegates to Guard_Dog_Utils for centralized, proxy-aware IP detection.
     *
     * @since 1.9.33 Consolidated to use Guard_Dog_Utils::get_client_ip().
     * @return string The client IP address.
     */
    private function get_client_ip(): string {
        if ( class_exists( 'Guard_Dog_Utils' ) && method_exists( 'Guard_Dog_Utils', 'get_client_ip' ) ) {
            $ip = Guard_Dog_Utils::get_client_ip();
            if ( $ip ) {
                return $ip;
            }
        }

        return isset( $_SERVER['REMOTE_ADDR'] )
            ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) )
            : '127.0.0.1';
    }
    
    /**
     * Get available CAPTCHA providers
     *
     * @return array
     */
    public static function get_available_providers(): array {
        return [
            self::PROVIDER_NONE => __('Disabled', 'guard-dog'),
            self::PROVIDER_RECAPTCHA_V2 => __('Google reCAPTCHA v2 (Checkbox)', 'guard-dog'),
            self::PROVIDER_RECAPTCHA_V3 => __('Google reCAPTCHA v3 (Invisible)', 'guard-dog'),
            self::PROVIDER_HCAPTCHA => __('hCaptcha', 'guard-dog'),
            self::PROVIDER_TURNSTILE => __('Cloudflare Turnstile', 'guard-dog'),
        ];
    }
    
    /**
     * Check if current provider is active
     *
     * @return bool
     */
    public function is_active(): bool {
        return $this->provider !== self::PROVIDER_NONE && !empty($this->config['site_key']) && !empty($this->config['secret_key']);
    }
    
    /**
     * Get current provider
     *
     * @return string
     */
    public function get_provider(): string {
        return $this->provider;
    }

    /**
     * Debug CAPTCHA configuration - Helper for troubleshooting
     *
     * @return array
     */
    public function get_debug_info(): array {
        return [
            'provider' => $this->provider,
            'site_key_length' => strlen($this->config['site_key']),
            'secret_key_length' => strlen($this->config['secret_key']),
            'site_key_prefix' => substr($this->config['site_key'], 0, 10) . '...',
            'theme' => $this->config['theme'],
            'size' => $this->config['size'],
            'v3_threshold' => $this->config['v3_score_threshold'],
            'current_domain' => isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : 'unknown',
            'is_active' => $this->is_active(),
        ];
    }
} 
