<?php
/**
 * VMPFence reCAPTCHA Integration
 * Handles Google reCAPTCHA v3 integration for login and registration pages
 *
 * @package VMPFence
 * @since 2.1.0
 * @since 2.2.1 Updated text-domain to vmpfence-security
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

class VMPFence_ReCAPTCHA_Integration {
    
    /**
     * Initialize reCAPTCHA integration
     */
    public static function init() {
        // Only initialize if reCAPTCHA is enabled
        if (!self::is_enabled()) {
            return;
        }

        // Enqueue scripts on login and registration pages
        add_action('login_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'));
        
        // Display reCAPTCHA on forms
        add_action('login_form', array(__CLASS__, 'display_recaptcha'));
        add_action('register_form', array(__CLASS__, 'display_recaptcha'));
        
        // Verify reCAPTCHA on authentication
        add_filter('authenticate', array(__CLASS__, 'verify_recaptcha'), 30, 3);
        add_filter('registration_errors', array(__CLASS__, 'verify_recaptcha_registration'), 10, 3);
    }

    /**
     * Check if reCAPTCHA is enabled
     *
     * @return bool
     */
    public static function is_enabled() {
        // PHASE 7: Skip reCAPTCHA for allowlisted IPs
        $user_ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
        if (!empty($user_ip) && class_exists('VMPFence_IP_Allowlist') && VMPFence_IP_Allowlist::is_ip_allowlisted($user_ip)) {
            return false; // Treat as disabled for allowlisted IPs
        }
        
        return (bool) VMPFence_Config::get('vmpfence_recaptcha_enabled', false);
    }

    /**
     * Get reCAPTCHA site key
     *
     * @return string
     */
    public static function get_site_key() {
        return VMPFence_Config::get('vmpfence_recaptcha_site_key', '');
    }

    /**
     * Get reCAPTCHA secret key
     *
     * @return string
     */
    public static function get_secret_key() {
        return VMPFence_Config::get('vmpfence_recaptcha_secret_key', '');
    }

    /**
     * Get reCAPTCHA threshold
     *
     * @return float
     */
    public static function get_threshold() {
        return floatval(VMPFence_Config::get('vmpfence_recaptcha_threshold', 0.5));
    }

    /**
     * Enqueue Google reCAPTCHA scripts
     */
    public static function enqueue_scripts() {
        $site_key = self::get_site_key();
        
        if (empty($site_key)) {
            return;
        }

        // Enqueue reCAPTCHA v3 API
        wp_enqueue_script(
            'google-recaptcha-v3',
            'https://www.google.com/recaptcha/api.js?render=' . esc_attr($site_key),
            array(),
            null,
            true
        );

        // Enqueue custom reCAPTCHA handler
        wp_add_inline_script(
            'google-recaptcha-v3',
            "
            document.addEventListener('DOMContentLoaded', function() {
                const forms = document.querySelectorAll('#loginform, #registerform');
                forms.forEach(function(form) {
                    form.addEventListener('submit', function(e) {
                        e.preventDefault();
                        const submitBtn = form.querySelector('#wp-submit');
                        const originalText = submitBtn ? submitBtn.value : '';
                        if (submitBtn) {
                            submitBtn.disabled = true;
                            submitBtn.value = 'Verifying...';
                        }
                        
                        grecaptcha.ready(function() {
                            grecaptcha.execute('" . esc_js($site_key) . "', {action: 'login'}).then(function(token) {
                                // Add token to form
                                let tokenInput = form.querySelector('input[name=\"g-recaptcha-response\"]');
                                if (!tokenInput) {
                                    tokenInput = document.createElement('input');
                                    tokenInput.type = 'hidden';
                                    tokenInput.name = 'g-recaptcha-response';
                                    form.appendChild(tokenInput);
                                }
                                tokenInput.value = token;
                                
                                // Submit form
                                form.submit();
                            }).catch(function(error) {
                                console.error('reCAPTCHA error:', error);
                                if (submitBtn) {
                                    submitBtn.disabled = false;
                                    submitBtn.value = originalText;
                                }
                                // Display error message in the login form
                                let errorDiv = document.getElementById('login_error');
                                if (!errorDiv) {
                                    errorDiv = document.createElement('div');
                                    errorDiv.id = 'login_error';
                                    errorDiv.style.border = '1px solid #d63638';
                                    errorDiv.style.borderLeft = '4px solid #d63638';
                                    errorDiv.style.padding = '12px';
                                    errorDiv.style.marginLeft = '0';
                                    errorDiv.style.marginBottom = '20px';
                                    errorDiv.style.backgroundColor = '#fff';
                                    form.parentNode.insertBefore(errorDiv, form);
                                }
                                errorDiv.innerHTML = '<strong>ERROR</strong>: reCAPTCHA verification failed. Please try again.';
                            });
                        });
                    });
                });
            });
            "
        );
    }

    /**
     * Display reCAPTCHA notice on forms
     */
    public static function display_recaptcha() {
        $site_key = self::get_site_key();
        
        if (empty($site_key)) {
            return;
        }

        // Display a notice about reCAPTCHA protection
        echo '<p class="vmpfence-recaptcha-notice" style="margin: 10px 0; font-size: 12px; color: #666;">';
        echo '<span class="dashicons dashicons-shield" style="font-size: 14px; vertical-align: middle;"></span> ';
        echo esc_html__('This site is protected by reCAPTCHA and the Google ', 'vmpfence-security');
        echo '<a href="https://policies.google.com/privacy" target="_blank" rel="noopener">' . esc_html__('Privacy Policy', 'vmpfence-security') . '</a> ';
        echo esc_html__('and ', 'vmpfence-security');
        echo '<a href="https://policies.google.com/terms" target="_blank" rel="noopener">' . esc_html__('Terms of Service', 'vmpfence-security') . '</a> ';
        echo esc_html__('apply.', 'vmpfence-security');
        echo '</p>';
    }

    /**
     * Verify reCAPTCHA response on login
     *
     * @param WP_User|WP_Error|null $user
     * @param string $username
     * @param string $password
     * @return WP_User|WP_Error
     */
    public static function verify_recaptcha($user, $username, $password) {
        // Don't verify if already an error
        if (is_wp_error($user)) {
            return $user;
        }

        // Don't verify empty login attempts
        if (empty($username) || empty($password)) {
            return $user;
        }

        // Check for reCAPTCHA response
        if (!isset($_POST['g-recaptcha-response']) || empty($_POST['g-recaptcha-response'])) {
            return new WP_Error(
                'recaptcha_missing',
                __('<strong>ERROR</strong>: reCAPTCHA verification is required. Please try again.', 'vmpfence-security')
            );
        }

        $response_token = sanitize_text_field($_POST['g-recaptcha-response']);
        $verify_result = self::verify_token($response_token, 'login');

        if (is_wp_error($verify_result)) {
            return $verify_result;
        }

        return $user;
    }

    /**
     * Verify reCAPTCHA response on registration
     *
     * @param WP_Error $errors
     * @param string $sanitized_user_login
     * @param string $user_email
     * @return WP_Error
     */
    public static function verify_recaptcha_registration($errors, $sanitized_user_login, $user_email) {
        // Check for reCAPTCHA response
        if (!isset($_POST['g-recaptcha-response']) || empty($_POST['g-recaptcha-response'])) {
            $errors->add(
                'recaptcha_missing',
                __('<strong>ERROR</strong>: reCAPTCHA verification is required.', 'vmpfence-security')
            );
            return $errors;
        }

        $response_token = sanitize_text_field($_POST['g-recaptcha-response']);
        $verify_result = self::verify_token($response_token, 'register');

        if (is_wp_error($verify_result)) {
            $errors->add(
                'recaptcha_failed',
                $verify_result->get_error_message()
            );
        }

        return $errors;
    }

    /**
     * Verify reCAPTCHA token with Google API
     *
     * @param string $token
     * @param string $action
     * @return bool|WP_Error
     */
    private static function verify_token($token, $action = 'login') {
        $secret_key = self::get_secret_key();
        $threshold = self::get_threshold();

        if (empty($secret_key)) {
            return new WP_Error(
                'recaptcha_config_error',
                __('<strong>ERROR</strong>: reCAPTCHA is not properly configured.', 'vmpfence-security')
            );
        }

        // Make request to Google API
        $response = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', array(
            'body' => array(
                'secret' => $secret_key,
                'response' => $token,
                'remoteip' => self::get_client_ip()
            ),
            'timeout' => 10,
            'sslverify' => true
        ));

        if (is_wp_error($response)) {
            VMPFence_Secure_Logger::error('reCAPTCHA API Error', array(
                'error' => $response->get_error_message()
            ));
            
            // Fail open - allow login if API is down
            return true;
        }

        $response_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);
        $result = json_decode($response_body, true);

        if ($response_code !== 200 || !isset($result['success'])) {
            VMPFence_Secure_Logger::error('reCAPTCHA Invalid Response', array(
                'code' => $response_code,
                'body' => $response_body
            ));
            
            // Fail open - allow login if API returns invalid response
            return true;
        }

        // Check if verification was successful
        if (!$result['success']) {
            $error_codes = isset($result['error-codes']) ? implode(', ', $result['error-codes']) : 'unknown';
            
            VMPFence_Secure_Logger::warning('reCAPTCHA Verification Failed', array(
                'errors' => $error_codes,
                'action' => $action
            ));
            
            return new WP_Error(
                'recaptcha_failed',
                __('<strong>ERROR</strong>: reCAPTCHA verification failed. Please try again.', 'vmpfence-security')
            );
        }

        // Check score against threshold
        $score = isset($result['score']) ? floatval($result['score']) : 0.0;
        
        if ($score < $threshold) {
            VMPFence_Secure_Logger::warning('reCAPTCHA Low Score', array(
                'score' => $score,
                'threshold' => $threshold,
                'action' => $action,
                'ip' => self::get_client_ip()
            ));
            
            return new WP_Error(
                'recaptcha_low_score',
                sprintf(
                    __('<strong>ERROR</strong>: reCAPTCHA verification failed. Your score (%s) is below the threshold (%s). Please try again.', 'vmpfence-security'),
                    number_format($score, 2),
                    number_format($threshold, 2)
                )
            );
        }

        // Log successful verification
        VMPFence_Secure_Logger::info('reCAPTCHA Verified', array(
            'score' => $score,
            'threshold' => $threshold,
            'action' => $action
        ));

        return true;
    }

    /**
     * Get client IP address
     *
     * @return string
     */
    private static function get_client_ip() {
        $ip = '';
        
        if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
            $ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
        } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
        } elseif (isset($_SERVER['HTTP_X_REAL_IP'])) {
            $ip = $_SERVER['HTTP_X_REAL_IP'];
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        
        return sanitize_text_field(trim($ip));
    }
}

// Initialize reCAPTCHA integration
add_action('plugins_loaded', array('VMPFence_ReCAPTCHA_Integration', 'init'));
