<?php

declare(strict_types=1);

namespace App\Core;

/**
 * Google reCAPTCHA v3 (invisible, sans interaction utilisateur).
 * Actif uniquement si activé en réglages ET clés présentes.
 * Les clés se saisissent dans les Paramètres (repli sur config/local.php si vides).
 */
final class Recaptcha
{
    /** Score minimal accepté (v3 : 0.0 = bot probable, 1.0 = humain probable). */
    private const MIN_SCORE = 0.5;

    /** Action attendue (doit correspondre au grecaptcha.execute côté front). */
    public const ACTION = 'contact';

    public static function isActive(): bool
    {
        return (string) Settings::get('contact_recaptcha_enabled', '0') === '1'
            && self::siteKey() !== ''
            && self::secretKey() !== '';
    }

    public static function siteKey(): string
    {
        $s = trim((string) Settings::get('recaptcha_site_key', ''));
        return $s !== '' ? $s : (string) Config::get('recaptcha.site_key', '');
    }

    private static function secretKey(): string
    {
        $s = trim((string) Settings::get('recaptcha_secret_key', ''));
        return $s !== '' ? $s : (string) Config::get('recaptcha.secret_key', '');
    }

    public static function verify(?string $token, ?string $ip): bool
    {
        if (!self::isActive()) {
            return true; // non actif : on ne bloque pas
        }
        if (!is_string($token) || $token === '') {
            return false;
        }

        $payload = http_build_query([
            'secret'   => self::secretKey(),
            'response' => $token,
            'remoteip' => $ip ?? '',
        ]);
        $context = stream_context_create([
            'http' => [
                'method'        => 'POST',
                'header'        => 'Content-Type: application/x-www-form-urlencoded',
                'content'       => $payload,
                'timeout'       => 5,
                'ignore_errors' => true,
            ],
        ]);

        $response = @file_get_contents('https://www.google.com/recaptcha/api/siteverify', false, $context);
        if ($response === false) {
            return false;
        }
        $data = json_decode($response, true);
        if (!is_array($data) || empty($data['success'])) {
            return false;
        }

        // v3 : on rejette les scores trop faibles (comportement robotique).
        if (isset($data['score']) && (float) $data['score'] < self::MIN_SCORE) {
            return false;
        }

        return true;
    }
}
