<?php
/**
 * reCAPTCHA Service - v3 API Implementation with Scoring
 */
require_once 'config_loader.php';
require_once 'Logger.php';

class RecaptchaService {
    private $siteKey;
    private $secretKey;
    
    public function __construct() {
        $this->siteKey = env('RECAPTCHA_SITE_KEY');
        $this->secretKey = env('RECAPTCHA_SECRET_KEY');
        
        if (empty($this->siteKey) || empty($this->secretKey)) {
            throw new Exception('reCAPTCHA configuration missing. Please check environment variables.');
        }
        
        Logger::debug('RecaptchaService initialized', [
            'site_key' => $this->siteKey,
            'version' => 'v3'
        ]);
    }
    
    public function verifyToken($token, $action = 'submit') {
        if (empty($token)) {
            Logger::warning('Empty reCAPTCHA token provided');
            return ['success' => false, 'message' => 'reCAPTCHA token is missing'];
        }
        
        try {
            Logger::debug('Verifying reCAPTCHA v3 token', ['action' => $action]);
            
            // Use reCAPTCHA v3 verification API
            $url = 'https://www.google.com/recaptcha/api/siteverify';
            $data = [
                'secret' => $this->secretKey,
                'response' => $token,
                'remoteip' => $_SERVER['REMOTE_ADDR'] ?? null
            ];
            
            $options = [
                'http' => [
                    'header' => "Content-type: application/x-www-form-urlencoded\r\n",
                    'method' => 'POST',
                    'content' => http_build_query($data)
                ]
            ];
            
            $context = stream_context_create($options);
            $response = file_get_contents($url, false, $context);
            $result = json_decode($response, true);
            
            if (!$result['success']) {
                $errorCodes = $result['error-codes'] ?? [];
                Logger::warning('reCAPTCHA verification failed', [
                    'errors' => $errorCodes,
                    'action' => $action
                ]);
                return [
                    'success' => false, 
                    'message' => 'reCAPTCHA verification failed',
                    'error_codes' => $errorCodes
                ];
            }
            
            // v3 specific response handling
            $score = $result['score'] ?? 0.0;
            $actionMatch = ($result['action'] ?? '') === $action;
            $hostname = $result['hostname'] ?? '';
            
            Logger::info('reCAPTCHA v3 verification successful', [
                'action' => $action,
                'score' => $score,
                'action_match' => $actionMatch,
                'hostname' => $hostname
            ]);
            
            return [
                'success' => true,
                'message' => 'reCAPTCHA verification successful',
                'score' => (float) $score,
                'action' => $result['action'] ?? $action,
                'challenge_ts' => $result['challenge_ts'] ?? null,
                'hostname' => $hostname,
                'action_match' => $actionMatch
            ];
            
        } catch (Exception $e) {
            Logger::error('reCAPTCHA Error', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
            return ['success' => false, 'message' => 'An error occurred during verification'];
        }
    }
    
    public function getSiteKey() {
        return $this->siteKey;
    }
    
    /**
     * Get reCAPTCHA v3 configuration for JavaScript
     */
    public function getScriptConfig($action = 'submit') {
        return [
            'sitekey' => $this->siteKey,
            'action' => $action,
            'callback' => 'onloadCallback'
        ];
    }
    
    /**
     * Determine if score indicates bot activity
     */
    public function isBot($score, $threshold = 0.5) {
        return $score < $threshold;
    }
    
    /**
     * Get risk level based on score
     */
    public function getRiskLevel($score) {
        if ($score >= 0.7) return 'low';
        if ($score >= 0.5) return 'medium';
        if ($score >= 0.3) return 'high';
        return 'very_high';
    }
}