<?php
/**
 * CAPTCHA / Turnstile for table reservation forms.
 *
 * @package Maca_Menu_List
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Supported CAPTCHA providers.
 *
 * @return array<int, string>
 */
function maca_menulist_table_booking_captcha_providers() {
    return array('none', 'recaptcha_v2', 'recaptcha_v3', 'turnstile');
}

/**
 * Current CAPTCHA provider key.
 *
 * @return string
 */
function maca_menulist_get_table_booking_captcha_provider() {
    $provider = get_option('maca_menulist_table_booking_captcha_provider', 'none');

    if (!in_array($provider, maca_menulist_table_booking_captcha_providers(), true)) {
        return 'none';
    }

    return $provider;
}

/**
 * Public site key.
 *
 * @return string
 */
function maca_menulist_get_table_booking_captcha_site_key() {
    return (string) get_option('maca_menulist_table_booking_captcha_site_key', '');
}

/**
 * Secret key.
 *
 * @return string
 */
function maca_menulist_get_table_booking_captcha_secret_key() {
    return (string) get_option('maca_menulist_table_booking_captcha_secret_key', '');
}

/**
 * Minimum score for reCAPTCHA v3 (0.0–1.0).
 *
 * @return float
 */
function maca_menulist_get_table_booking_captcha_v3_score() {
    $score = (float) get_option('maca_menulist_table_booking_captcha_v3_score', '0.5');

    return max(0.1, min(1.0, $score));
}

/**
 * Whether CAPTCHA is configured and active.
 *
 * @return bool
 */
function maca_menulist_table_booking_captcha_enabled() {
    if (!maca_menulist_table_booking_enabled()) {
        return false;
    }

    $provider = maca_menulist_get_table_booking_captcha_provider();

    if ($provider === 'none') {
        return false;
    }

    return maca_menulist_get_table_booking_captcha_site_key() !== ''
        && maca_menulist_get_table_booking_captcha_secret_key() !== '';
}

/**
 * Register CAPTCHA scripts (without enqueue).
 *
 * @return void
 */
function maca_menulist_register_table_booking_captcha_assets() {
    if (!maca_menulist_pro_has_feature('table_bookings')) {
        return;
    }

    if (!wp_script_is('maca-menulist-captcha-bootstrap', 'registered')) {
        wp_register_script(
            'maca-menulist-captcha-bootstrap',
            MACA_MENULIST_PLUGIN_URL . 'assets/js/captcha-bootstrap.js',
            array(),
            MACA_MENULIST_VERSION,
            true
        );
    }

    $provider = maca_menulist_get_table_booking_captcha_provider();
    $site_key = maca_menulist_get_table_booking_captcha_site_key();

    if (($provider === 'recaptcha_v2' || $provider === 'recaptcha_v3') && !wp_script_is('maca-menulist-recaptcha', 'registered')) {
        $script_url = 'https://www.google.com/recaptcha/api.js';
        $bootstrap_deps = array('maca-menulist-captcha-bootstrap');

        if ($provider === 'recaptcha_v3') {
            $script_url = add_query_arg('render', $site_key, $script_url);
        } else {
            $script_url = add_query_arg(
                array(
                    'onload' => 'macaMenulistRecaptchaReady',
                    'render' => 'explicit',
                ),
                $script_url
            );
        }

        wp_register_script(
            'maca-menulist-recaptcha',
            $script_url,
            $bootstrap_deps,
            null,
            true
        );
        wp_script_add_data('maca-menulist-recaptcha', 'strategy', 'async');
    }

    if ($provider === 'turnstile' && !wp_script_is('maca-menulist-turnstile', 'registered')) {
        wp_register_script(
            'maca-menulist-turnstile',
            // phpcs:ignore PluginCheck.CodeAnalysis.EnqueuedResourceOffloading.OffloadedContent -- Cloudflare Turnstile requires their CDN API script.
            'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit',
            array(),
            null,
            true
        );
        wp_script_add_data('maca-menulist-turnstile', 'strategy', 'async');
    }
}

/**
 * Enqueue CAPTCHA scripts on the frontend.
 *
 * @return void
 */
function maca_menulist_enqueue_table_booking_captcha_assets() {
    if (!maca_menulist_table_booking_captcha_enabled()) {
        return;
    }

    maca_menulist_register_table_booking_captcha_assets();

    $provider = maca_menulist_get_table_booking_captcha_provider();

    if ($provider === 'recaptcha_v2' || $provider === 'recaptcha_v3') {
        wp_enqueue_script('maca-menulist-captcha-bootstrap');
        wp_enqueue_script('maca-menulist-recaptcha');
    }

    if ($provider === 'turnstile') {
        wp_enqueue_script('maca-menulist-turnstile');
    }
}

/**
 * Render CAPTCHA widget markup for the booking form.
 *
 * @return string
 */
function maca_menulist_render_table_booking_captcha_field() {
    if (!maca_menulist_table_booking_captcha_enabled()) {
        return '';
    }

    $provider = maca_menulist_get_table_booking_captcha_provider();

    ob_start();

    if ($provider === 'recaptcha_v2') {
        ?>
        <div class="maca-booking-field maca-booking-captcha">
            <div class="maca-recaptcha-v2-widget"></div>
        </div>
        <?php
    } elseif ($provider === 'recaptcha_v3') {
        ?>
        <input type="hidden" name="captcha_token" class="maca-booking-captcha-token" value="">
        <?php
    } elseif ($provider === 'turnstile') {
        ?>
        <div class="maca-booking-field maca-booking-captcha">
            <div class="maca-turnstile-widget"></div>
            <input type="hidden" name="captcha_token" class="maca-booking-captcha-token" value="">
        </div>
        <?php
    }

    return (string) ob_get_clean();
}

/**
 * Verify a CAPTCHA response token from the booking form.
 *
 * @param string $token Response token from the client.
 * @return true|WP_Error
 */
function maca_menulist_verify_table_booking_captcha($token) {
    if (!maca_menulist_table_booking_captcha_enabled()) {
        return true;
    }

    $token = sanitize_text_field($token);
    if ($token === '') {
        return new WP_Error('captcha_missing', __('Please complete the security check.', 'maca-restu-pro'));
    }

    $provider = maca_menulist_get_table_booking_captcha_provider();
    $secret = maca_menulist_get_table_booking_captcha_secret_key();

    if ($provider === 'turnstile') {
        $response = wp_remote_post(
            'https://challenges.cloudflare.com/turnstile/v0/siteverify',
            array(
                'timeout' => 15,
                'body' => array(
                    'secret' => $secret,
                    'response' => $token,
                    'remoteip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '',
                ),
            )
        );
    } else {
        $response = wp_remote_post(
            'https://www.google.com/recaptcha/api/siteverify',
            array(
                'timeout' => 15,
                'body' => array(
                    'secret' => $secret,
                    'response' => $token,
                    'remoteip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '',
                ),
            )
        );
    }

    if (is_wp_error($response)) {
        return new WP_Error('captcha_http', __('Could not verify security check. Please try again.', 'maca-restu-pro'));
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);
    if (!is_array($body) || empty($body['success'])) {
        return new WP_Error('captcha_failed', __('Security check failed. Please try again.', 'maca-restu-pro'));
    }

    if ($provider === 'recaptcha_v3') {
        $score = isset($body['score']) ? (float) $body['score'] : 0;
        if ($score < maca_menulist_get_table_booking_captcha_v3_score()) {
            return new WP_Error('captcha_score', __('Security check failed. Please try again.', 'maca-restu-pro'));
        }
    }

    return true;
}
