<?php
/**
 * Advanced AntiBot Protection System
 * Prevents bots, scanners, and crawlers from accessing the site
 * Highly advanced system that doesn't rely on external APIs
 */

class AntiBot {
    private $config;
    private $sessionKey = 'antibot_session';
    private $logFile = 'logs/antibot.log';
    
    public function __construct($config) {
        $this->config = $config;
        $this->ensureLogDirectory();
        $this->startSession();
    }
    
    private function ensureLogDirectory() {
        if (!file_exists('logs')) {
            mkdir('logs', 0755, true);
        }
    }
    
    private function startSession() {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
    }
    
    /**
     * Main protection method - call this at the beginning of your pages
     */
    public function protect() {
        if (!$this->config['antibot_enabled']) {
            return true;
        }
        
        // Skip most checks for localhost testing
        $isLocalhost = in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1']) || 
                       $_SERVER['HTTP_HOST'] === 'localhost' || 
                       strpos($_SERVER['HTTP_HOST'], '127.0.0.1') !== false;
        
        if ($isLocalhost) {
            // Only check honeypot on localhost
            if (!$this->checkHoneypot()) {
                $this->logAttempt('Honeypot Triggered');
                $this->blockAccess();
                return false;
            }
            
            // Update session data for behavioral analysis
            $this->updateSessionData();
            return true;
        }
        
        // Check multiple protection layers for production
        if (!$this->checkUserAgent()) {
            $this->logAttempt('Invalid User Agent');
            $this->blockAccess();
            return false;
        }
        
        if (!$this->checkRequestPattern()) {
            $this->logAttempt('Suspicious Request Pattern');
            $this->blockAccess();
            return false;
        }
        
        if (!$this->checkBehavioralPattern()) {
            $this->logAttempt('Bot-like Behavior Detected');
            $this->blockAccess();
            return false;
        }
        
        if (!$this->checkJavaScriptChallenge()) {
            $this->logAttempt('JavaScript Challenge Failed');
            $this->blockAccess();
            return false;
        }
        
        if (!$this->checkTimeBasedProtection()) {
            $this->logAttempt('Time-based Protection Triggered');
            $this->blockAccess();
            return false;
        }
        
        if (!$this->checkHoneypot()) {
            $this->logAttempt('Honeypot Triggered');
            $this->blockAccess();
            return false;
        }
        
        // Update session data for behavioral analysis
        $this->updateSessionData();
        
        return true;
    }
    
    /**
     * Check User Agent for bot patterns
     */
    private function checkUserAgent() {
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        // Empty user agent
        if (empty($userAgent)) {
            return false;
        }
        
        // Known bot patterns
        $botPatterns = [
            '/bot/i', '/crawler/i', '/spider/i', '/scraper/i',
            '/curl/i', '/wget/i', '/python/i', '/java/i',
            '/php/i', '/perl/i', '/ruby/i', '/go-http/i',
            '/libwww/i', '/lwp/i', '/winhttp/i', '/okhttp/i',
            '/apache/i', '/nginx/i', '/monitor/i', '/check/i',
            '/test/i', '/scan/i', '/probe/i', '/fetch/i'
        ];
        
        foreach ($botPatterns as $pattern) {
            if (preg_match($pattern, $userAgent)) {
                return false;
            }
        }
        
        // Check for suspicious user agent characteristics
        if (strlen($userAgent) < 10 || strlen($userAgent) > 500) {
            return false;
        }
        
        // Check for missing common browser components
        $browserComponents = ['Mozilla', 'Chrome', 'Safari', 'Firefox', 'Edge', 'Opera'];
        $hasBrowserComponent = false;
        foreach ($browserComponents as $component) {
            if (stripos($userAgent, $component) !== false) {
                $hasBrowserComponent = true;
                break;
            }
        }
        
        return $hasBrowserComponent;
    }
    
    /**
     * Check request patterns for suspicious behavior
     */
    private function checkRequestPattern() {
        // Check referer patterns
        $referer = $_SERVER['HTTP_REFERER'] ?? '';
        if (!empty($referer)) {
            $suspiciousReferers = ['localhost', '127.0.0.1', 'test.com', 'example.com'];
            foreach ($suspiciousReferers as $suspicious) {
                if (stripos($referer, $suspicious) !== false) {
                    return false;
                }
            }
        }
        
        // Check for missing common headers
        $requiredHeaders = ['HTTP_ACCEPT', 'HTTP_ACCEPT_LANGUAGE', 'HTTP_ACCEPT_ENCODING'];
        foreach ($requiredHeaders as $header) {
            if (!isset($_SERVER[$header])) {
                return false;
            }
        }
        
        // Check request method
        if ($_SERVER['REQUEST_METHOD'] !== 'GET' && $_SERVER['REQUEST_METHOD'] !== 'POST') {
            return false;
        }
        
        return true;
    }
    
    /**
     * Check behavioral patterns
     */
    private function checkBehavioralPattern() {
        $sessionData = $this->getSessionData();
        
        // Check request frequency
        $currentTime = time();
        if (isset($sessionData['last_request'])) {
            $timeDiff = $currentTime - $sessionData['last_request'];
            if ($timeDiff < 2) { // Less than 2 seconds between requests
                return false;
            }
        }
        
        // Check for rapid successive requests
        if (isset($sessionData['request_count'])) {
            $sessionData['request_count']++;
            if ($sessionData['request_count'] > 10) { // More than 10 requests in session
                return false;
            }
        } else {
            $sessionData['request_count'] = 1;
        }
        
        $sessionData['last_request'] = $currentTime;
        $this->setSessionData($sessionData);
        
        return true;
    }
    
    /**
     * JavaScript challenge verification
     */
    private function checkJavaScriptChallenge() {
        // Skip JavaScript challenge for localhost testing
        $isLocalhost = in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1']) || 
                       $_SERVER['HTTP_HOST'] === 'localhost' || 
                       strpos($_SERVER['HTTP_HOST'], '127.0.0.1') !== false;
        
        if ($isLocalhost) {
            return true; // Skip challenge on localhost
        }
        
        // Check if JavaScript challenge was completed
        $challengeToken = $_POST['js_challenge'] ?? $_GET['js_challenge'] ?? '';
        $sessionData = $this->getSessionData();
        
        if (empty($challengeToken)) {
            // Generate new challenge
            $challenge = $this->generateChallenge();
            $sessionData['js_challenge'] = $challenge;
            $this->setSessionData($sessionData);
            return false; // Will trigger JavaScript challenge
        }
        
        // Verify challenge
        if (!isset($sessionData['js_challenge']) || $challengeToken !== $sessionData['js_challenge']) {
            return false;
        }
        
        return true;
    }
    
    /**
     * Time-based protection
     */
    private function checkTimeBasedProtection() {
        $sessionData = $this->getSessionData();
        
        // Check if user spent minimum time on page
        if (isset($sessionData['page_load_time'])) {
            $timeSpent = time() - $sessionData['page_load_time'];
            if ($timeSpent < 3) { // Less than 3 seconds on page
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * Honeypot protection
     */
    private function checkHoneypot() {
        // Check honeypot field
        $honeypot = $_POST['website'] ?? $_GET['website'] ?? '';
        if (!empty($honeypot)) {
            return false; // Honeypot triggered
        }
        
        return true;
    }
    
    /**
     * Generate JavaScript challenge
     */
    private function generateChallenge() {
        $numbers = [rand(1, 10), rand(1, 10)];
        $operation = rand(0, 1) ? '+' : '-';
        
        if ($operation === '+') {
            $answer = $numbers[0] + $numbers[1];
        } else {
            $answer = $numbers[0] - $numbers[1];
        }
        
        return base64_encode($numbers[0] . $operation . $numbers[1] . '=' . $answer);
    }
    
    /**
     * Get session data
     */
    private function getSessionData() {
        return $_SESSION[$this->sessionKey] ?? [];
    }
    
    /**
     * Set session data
     */
    private function setSessionData($data) {
        $_SESSION[$this->sessionKey] = $data;
    }
    
    /**
     * Update session data for behavioral analysis
     */
    private function updateSessionData() {
        $sessionData = $this->getSessionData();
        $sessionData['page_load_time'] = time();
        $sessionData['ip_address'] = $this->getClientIP();
        $sessionData['user_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? '';
        $this->setSessionData($sessionData);
    }
    
    /**
     * Get client IP address
     */
    private function getClientIP() {
        $ipKeys = ['HTTP_CF_CONNECTING_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'];
        foreach ($ipKeys as $key) {
            if (!empty($_SERVER[$key])) {
                $ip = $_SERVER[$key];
                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
        return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    }
    
    /**
     * Log security attempts
     */
    private function logAttempt($reason) {
        $logEntry = [
            'timestamp' => date('Y-m-d H:i:s'),
            'ip' => $this->getClientIP(),
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
            'reason' => $reason,
            'url' => $_SERVER['REQUEST_URI'] ?? '',
            'method' => $_SERVER['REQUEST_METHOD'] ?? ''
        ];
        
        $logLine = json_encode($logEntry) . "\n";
        file_put_contents($this->logFile, $logLine, FILE_APPEND | LOCK_EX);
    }
    
    /**
     * Block access and show error page
     */
    private function blockAccess() {
        http_response_code(403);
        
        // Log the attempt
        $this->logAttempt('Access Blocked');
        
        // Show error page
        echo '<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Access Denied</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            color: white;
        }
        .error-container {
            text-align: center;
            background: rgba(255, 255, 255, 0.1);
            padding: 40px;
            border-radius: 10px;
            backdrop-filter: blur(10px);
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
        }
        .error-code {
            font-size: 72px;
            font-weight: bold;
            margin-bottom: 20px;
            color: #ff6b6b;
        }
        .error-message {
            font-size: 24px;
            margin-bottom: 20px;
        }
        .error-description {
            font-size: 16px;
            opacity: 0.8;
            max-width: 500px;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    <div class="error-container">
        <div class="error-code">403</div>
        <div class="error-message">Access Denied</div>
        <div class="error-description">
            Your request has been blocked by our security system. 
            Please ensure you are using a legitimate web browser and try again.
        </div>
    </div>
</body>
</html>';
        exit;
    }
    
    /**
     * Generate JavaScript challenge code
     */
    public function generateChallengeScript() {
        // Skip JavaScript challenge for localhost testing
        $isLocalhost = in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1']) || 
                       $_SERVER['HTTP_HOST'] === 'localhost' || 
                       strpos($_SERVER['HTTP_HOST'], '127.0.0.1') !== false;
        
        if ($isLocalhost) {
            return ''; // No challenge script on localhost
        }
        
        $sessionData = $this->getSessionData();
        $challenge = $sessionData['js_challenge'] ?? '';
        
        if (empty($challenge)) {
            return '';
        }
        
        $decoded = base64_decode($challenge);
        preg_match('/(\d+)([+\-])(\d+)=(\d+)/', $decoded, $matches);
        
        if (count($matches) === 5) {
            $num1 = $matches[1];
            $operator = $matches[2];
            $num2 = $matches[3];
            $answer = $matches[4];
            
            return "
            <script>
            document.addEventListener('DOMContentLoaded', function() {
                var challengeForm = document.createElement('form');
                challengeForm.method = 'POST';
                challengeForm.style.display = 'none';
                
                var challengeInput = document.createElement('input');
                challengeInput.type = 'hidden';
                challengeInput.name = 'js_challenge';
                challengeInput.value = '$challenge';
                
                challengeForm.appendChild(challengeInput);
                document.body.appendChild(challengeForm);
                challengeForm.submit();
            });
            </script>";
        }
        
        return '';
    }
    
    /**
     * Generate honeypot field
     */
    public function generateHoneypot() {
        return '<input type="text" name="website" style="position: absolute; left: -9999px; opacity: 0;" tabindex="-1" autocomplete="off">';
    }
    
    /**
     * Get security statistics
     */
    public function getSecurityStats() {
        if (!file_exists($this->logFile)) {
            return ['total_attempts' => 0, 'recent_attempts' => []];
        }
        
        $logs = file($this->logFile, FILE_IGNORE_NEW_LINES);
        $totalAttempts = count($logs);
        $recentAttempts = array_slice($logs, -10); // Last 10 attempts
        
        return [
            'total_attempts' => $totalAttempts,
            'recent_attempts' => array_map('json_decode', $recentAttempts)
        ];
    }
}
?>
