<?php

/**
 * Security Settings Provider
 * 
 * Provides security-related settings including rate limiting and CAPTCHA.
 * 
 * @package WooNooW
 */

namespace WooNooW\Compat;

class SecuritySettingsProvider
{

    /**
     * Get security settings
     * 
     * @return array
     */
    public static function get_settings()
    {
        return [
            // Rate Limiting
            'enable_checkout_rate_limit' => get_option('woonoow_enable_checkout_rate_limit', 'yes') === 'yes',
            'rate_limit_orders' => intval(get_option('woonoow_rate_limit_orders', 5)),
            'rate_limit_minutes' => intval(get_option('woonoow_rate_limit_minutes', 10)),

            // CAPTCHA
            'captcha_provider' => get_option('woonoow_captcha_provider', 'none'), // none, recaptcha, turnstile
            'recaptcha_site_key' => get_option('woonoow_recaptcha_site_key', ''),
            'recaptcha_secret_key' => get_option('woonoow_recaptcha_secret_key', ''),
            'turnstile_site_key' => get_option('woonoow_turnstile_site_key', ''),
            'turnstile_secret_key' => get_option('woonoow_turnstile_secret_key', ''),
        ];
    }

    /**
     * Get public settings (safe to expose to frontend)
     * 
     * @return array
     */
    public static function get_public_settings()
    {
        $settings = self::get_settings();

        return [
            'captcha_provider' => $settings['captcha_provider'],
            'recaptcha_site_key' => $settings['recaptcha_site_key'],
            'turnstile_site_key' => $settings['turnstile_site_key'],
        ];
    }

    /**
     * Update security settings
     * 
     * @param array $settings
     * @return bool
     */
    public static function update_settings($settings)
    {
        // Rate Limiting
        if (array_key_exists('enable_checkout_rate_limit', $settings)) {
            $value = !empty($settings['enable_checkout_rate_limit']) ? 'yes' : 'no';
            update_option('woonoow_enable_checkout_rate_limit', $value);
        }

        if (isset($settings['rate_limit_orders'])) {
            $value = max(1, intval($settings['rate_limit_orders']));
            update_option('woonoow_rate_limit_orders', $value);
        }

        if (isset($settings['rate_limit_minutes'])) {
            $value = max(1, intval($settings['rate_limit_minutes']));
            update_option('woonoow_rate_limit_minutes', $value);
        }

        // CAPTCHA Provider
        if (isset($settings['captcha_provider'])) {
            $valid_providers = ['none', 'recaptcha', 'turnstile'];
            $value = in_array($settings['captcha_provider'], $valid_providers)
                ? $settings['captcha_provider']
                : 'none';
            update_option('woonoow_captcha_provider', $value);
        }

        // reCAPTCHA Keys
        if (isset($settings['recaptcha_site_key'])) {
            update_option('woonoow_recaptcha_site_key', sanitize_text_field($settings['recaptcha_site_key']));
        }

        if (isset($settings['recaptcha_secret_key'])) {
            update_option('woonoow_recaptcha_secret_key', sanitize_text_field($settings['recaptcha_secret_key']));
        }

        // Turnstile Keys
        if (isset($settings['turnstile_site_key'])) {
            update_option('woonoow_turnstile_site_key', sanitize_text_field($settings['turnstile_site_key']));
        }

        if (isset($settings['turnstile_secret_key'])) {
            update_option('woonoow_turnstile_secret_key', sanitize_text_field($settings['turnstile_secret_key']));
        }

        return true;
    }

    /**
     * Check if rate limit is exceeded for an IP
     * 
     * @param string|null $ip IP address (null = auto-detect)
     * @return bool True if rate limit exceeded
     */
    public static function is_rate_limited($ip = null)
    {
        $settings = self::get_settings();

        if (!$settings['enable_checkout_rate_limit']) {
            return false;
        }

        if ($ip === null) {
            $ip = self::get_client_ip();
        }

        $transient_key = 'woonoow_rate_' . md5($ip);
        $attempts = get_transient($transient_key);

        if ($attempts === false) {
            return false;
        }

        return intval($attempts) >= $settings['rate_limit_orders'];
    }

    /**
     * Record an order attempt for rate limiting
     * 
     * @param string|null $ip IP address (null = auto-detect)
     * @return void
     */
    public static function record_order_attempt($ip = null)
    {
        $settings = self::get_settings();

        if (!$settings['enable_checkout_rate_limit']) {
            return;
        }

        if ($ip === null) {
            $ip = self::get_client_ip();
        }

        $transient_key = 'woonoow_rate_' . md5($ip);
        $attempts = get_transient($transient_key);

        if ($attempts === false) {
            // First attempt, set with expiration
            set_transient($transient_key, 1, $settings['rate_limit_minutes'] * MINUTE_IN_SECONDS);
        } else {
            // Increment attempts (keep same expiration by getting remaining time)
            $attempts = intval($attempts) + 1;
            set_transient($transient_key, $attempts, $settings['rate_limit_minutes'] * MINUTE_IN_SECONDS);
        }
    }

    /**
     * Validate CAPTCHA token
     * 
     * @param string $token CAPTCHA token from frontend
     * @return bool|WP_Error True if valid, WP_Error if invalid
     */
    public static function validate_captcha($token)
    {
        $settings = self::get_settings();

        if ($settings['captcha_provider'] === 'none') {
            return true; // No CAPTCHA enabled
        }

        if (empty($token)) {
            return new \WP_Error('captcha_missing', __('CAPTCHA verification required', 'woonoow'));
        }

        if ($settings['captcha_provider'] === 'recaptcha') {
            return self::validate_recaptcha($token, $settings['recaptcha_secret_key']);
        }

        if ($settings['captcha_provider'] === 'turnstile') {
            return self::validate_turnstile($token, $settings['turnstile_secret_key']);
        }

        return true;
    }

    /**
     * Validate Google reCAPTCHA v3 token
     * 
     * @param string $token Token from frontend
     * @param string $secret_key Secret key
     * @return bool|WP_Error
     */
    private static function validate_recaptcha($token, $secret_key)
    {
        if (empty($secret_key)) {
            return new \WP_Error('captcha_config', __('reCAPTCHA not configured', 'woonoow'));
        }

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

        if (is_wp_error($response)) {
            return new \WP_Error('captcha_error', __('CAPTCHA verification failed', 'woonoow'));
        }

        $body = json_decode(wp_remote_retrieve_body($response), true);

        if (!isset($body['success']) || !$body['success']) {
            return new \WP_Error('captcha_invalid', __('CAPTCHA verification failed', 'woonoow'));
        }

        // reCAPTCHA v3 returns a score (0.0 - 1.0), we accept 0.5 and above
        $score = $body['score'] ?? 0;
        if ($score < 0.5) {
            return new \WP_Error('captcha_score', __('CAPTCHA score too low', 'woonoow'));
        }

        return true;
    }

    /**
     * Validate Cloudflare Turnstile token
     * 
     * @param string $token Token from frontend
     * @param string $secret_key Secret key
     * @return bool|WP_Error
     */
    private static function validate_turnstile($token, $secret_key)
    {
        if (empty($secret_key)) {
            return new \WP_Error('captcha_config', __('Turnstile not configured', 'woonoow'));
        }

        $response = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
            'body' => [
                'secret' => $secret_key,
                'response' => $token,
                'remoteip' => self::get_client_ip(),
            ],
            'timeout' => 10,
        ]);

        if (is_wp_error($response)) {
            return new \WP_Error('captcha_error', __('CAPTCHA verification failed', 'woonoow'));
        }

        $body = json_decode(wp_remote_retrieve_body($response), true);

        if (!isset($body['success']) || !$body['success']) {
            return new \WP_Error('captcha_invalid', __('CAPTCHA verification failed', 'woonoow'));
        }

        return true;
    }

    /**
     * Get client IP address
     * 
     * @return string
     */
    private static function get_client_ip()
    {
        $headers = [
            'HTTP_CF_CONNECTING_IP', // Cloudflare
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_REAL_IP',
            'REMOTE_ADDR',
        ];

        foreach ($headers as $header) {
            if (!empty($_SERVER[$header])) {
                $ip = $_SERVER[$header];
                // Handle comma-separated list (X-Forwarded-For)
                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }
                if (filter_var($ip, FILTER_VALIDATE_IP)) {
                    return $ip;
                }
            }
        }

        return '127.0.0.1';
    }
}
