<?php

declare(strict_types=1);

class Captcha
{
    

    public static function isEnabled(string $action): bool
    {
        $provider = Setting::get('captcha_provider', 'none');
        if ($provider === 'none') {
            return false;
        }

        $siteKey = Setting::get('captcha_site_key', '');
        $secretKey = Setting::get('captcha_secret_key', '');
        if ($siteKey === '' || $secretKey === '') {
            return false;
        }

        return Setting::get('captcha_on_' . $action, '1') === '1';
    }

    

    public static function provider(): string
    {
        return Setting::get('captcha_provider', 'none');
    }

    

    public static function siteKey(): string
    {
        return Setting::get('captcha_site_key', '');
    }

    

    public static function theme(): string
    {
        $theme = Setting::get('captcha_theme', 'light');
        return in_array($theme, ['light', 'dark'], true) ? $theme : 'light';
    }

    

    public static function verify(string $action): bool
    {
        if (!self::isEnabled($action)) {
            return true;
        }

        $provider = self::provider();
        $secretKey = Setting::get('captcha_secret_key', '');
        $isTurnstile = $provider === 'turnstile';
        $token = $isTurnstile ? ($_POST['cf-turnstile-response'] ?? '') : ($_POST['g-recaptcha-response'] ?? '');

        if ($token === '') {
            return false;
        }

        $response = self::request($secretKey, $token, $isTurnstile);
        if ($response === null) {
             
             
            $response = self::request($secretKey, $token, $isTurnstile);
        }
        if ($response === null) {
            error_log('Captcha: siteverify request failed for action ' . $action . ' — failing closed');
            return false;
        }

        if (empty($response['success'])) {
            return false;
        }

         
        if ($provider === 'v3') {
            $score = $response['score'] ?? 0;
            if ($score < 0.5) {
                return false;
            }
             
            if (($response['action'] ?? '') !== $action) {
                return false;
            }
        }

        return true;
    }

    

    private static function request(string $secret, string $token, bool $turnstile = false): ?array
    {
        $data = http_build_query([
            'secret' => $secret,
            'response' => $token,
            'remoteip' => $_SERVER['REMOTE_ADDR'] ?? '',
        ]);

        $context = stream_context_create([
            'http' => [
                'method' => 'POST',
                'header' => 'Content-Type: application/x-www-form-urlencoded',
                'content' => $data,
                'timeout' => 5,
            ],
        ]);

        $endpoint = $turnstile
            ? 'https://challenges.cloudflare.com/turnstile/v0/siteverify'
            : 'https://www.google.com/recaptcha/api/siteverify';
        $result = @file_get_contents($endpoint, false, $context);
        if ($result === false) {
            return null;
        }

        return json_decode($result, true);
    }

    

    public static function renderWidget(string $action): string
    {
        if (!self::isEnabled($action)) {
            return '';
        }

        $provider = self::provider();
        $siteKey = htmlspecialchars(self::siteKey());

        if ($provider === 'turnstile') {
            $theme = htmlspecialchars(self::theme());
            return '<div class="cf-turnstile" data-sitekey="' . $siteKey . '" data-theme="' . $theme . '" style="margin:8px 0;"></div>';
        }

        if ($provider === 'v2') {
            $theme = htmlspecialchars(self::theme());
            return '<div class="g-recaptcha" data-sitekey="' . $siteKey . '" data-theme="' . $theme . '" style="margin:8px 0;"></div>';
        }

        if ($provider === 'v3') {
            $formId = 'captcha_' . $action . '_' . bin2hex(random_bytes(4));
            return '<input type="hidden" name="g-recaptcha-response" id="' . $formId . '">'
                . '<script>'
                . 'grecaptcha.ready(function(){'
                . 'var f=document.getElementById("' . $formId . '");'
                . 'if(f&&f.form){'
                . 'f.form.addEventListener("submit",function(e){'
                . 'if(f.value)return;'
                . 'e.preventDefault();'
                . 'grecaptcha.execute("' . $siteKey . '",{action:"' . $action . '"}).then(function(t){'
                . 'f.value=t;f.form.submit();'
                . '});'
                . '});'
                . '}'
                . '});'
                . '</script>';
        }

        return '';
    }

    

    public static function scriptTag(): string
    {
        $provider = self::provider();
        $siteKey = htmlspecialchars(self::siteKey());

        if ($provider === 'turnstile') {
            return '<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>';
        }

        if ($provider === 'v2') {
            return '<script src="https://www.google.com/recaptcha/api.js" async defer></script>';
        }

        if ($provider === 'v3') {
            return '<script src="https://www.google.com/recaptcha/api.js?render=' . $siteKey . '"></script>';
        }

        return '';
    }
}
