<?php
/**
 * Advanced Anti-Bot System
 * Detects and blocks bots, crawlers, and automated tools
 */

class AntiBot {
    private static $botPatterns = [
        'bot', 'crawl', 'spider', 'scrape', 'curl', 'wget', 'python', 'java',
        'http', 'libwww', 'perl', 'php', 'ruby', 'scan', 'check', 'monitor'
    ];
    
    /**
     * Check if request is from a bot
     */
    public static function isBot() {
        $userAgent = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');
        
        // Check user agent patterns
        foreach (self::$botPatterns as $pattern) {
            if (strpos($userAgent, $pattern) !== false) {
                return true;
            }
        }
        
        // Check for missing headers
        if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) || 
            empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
            return true;
        }
        
        // Check for suspicious headers
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && 
            count(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])) > 3) {
            return true;
        }
        
        return false;
    }
    
    /**
     * Get browser fingerprint
     */
    public static function getFingerprint() {
        $data = [
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
            'accept_language' => $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '',
            'accept_encoding' => $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '',
            'ip' => self::getIP()
        ];
        
        return md5(json_encode($data));
    }
    
    /**
     * Get real IP address
     */
    public static function getIP() {
        $headers = [
            'HTTP_CF_CONNECTING_IP', // Cloudflare
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_REAL_IP',
            'REMOTE_ADDR'
        ];
        
        foreach ($headers as $header) {
            if (!empty($_SERVER[$header])) {
                $ip = $_SERVER[$header];
                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }
                if (filter_var($ip, FILTER_VALIDATE_IP)) {
                    return $ip;
                }
            }
        }
        
        return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    }
    
    /**
     * Check IP reputation using multiple services
     */
    public static function checkIPReputation($ip) {
        $cacheKey = 'ip_reputation_' . $ip;
        
        // Check cache first
        $cached = Cache::get($cacheKey);
        if ($cached !== null) {
            return $cached;
        }
        
        $reputation = [
            'is_vpn' => false,
            'is_proxy' => false,
            'is_tor' => false,
            'is_hosting' => false,
            'fraud_score' => 0,
            'country' => 'Unknown',
            'city' => 'Unknown',
            'isp' => 'Unknown'
        ];
        
        // Check with ip-api.com (free, no key required)
        try {
            $response = @file_get_contents("http://ip-api.com/json/{$ip}?fields=status,country,city,isp,proxy,hosting");
            if ($response) {
                $data = json_decode($response, true);
                if ($data['status'] === 'success') {
                    $reputation['country'] = $data['country'] ?? 'Unknown';
                    $reputation['city'] = $data['city'] ?? 'Unknown';
                    $reputation['isp'] = $data['isp'] ?? 'Unknown';
                    $reputation['is_proxy'] = $data['proxy'] ?? false;
                    $reputation['is_hosting'] = $data['hosting'] ?? false;
                }
            }
        } catch (Exception $e) {
            // Silently fail
        }
        
        // Cache for 1 hour
        Cache::set($cacheKey, $reputation, 3600);
        
        return $reputation;
    }
    
    /**
     * Get geolocation data
     */
    public static function getGeolocation($ip) {
        $cacheKey = 'geolocation_' . $ip;
        
        // Check cache first
        $cached = Cache::get($cacheKey);
        if ($cached !== null) {
            return $cached;
        }
        
        $geo = [
            'country' => 'Unknown',
            'country_code' => 'XX',
            'city' => 'Unknown',
            'region' => 'Unknown',
            'latitude' => 0,
            'longitude' => 0,
            'timezone' => 'UTC',
            'currency' => 'USD',
            'flag' => '🌍'
        ];
        
        try {
            // Using ip-api.com (free, 45 requests/minute)
            $response = @file_get_contents("http://ip-api.com/json/{$ip}");
            if ($response) {
                $data = json_decode($response, true);
                if ($data['status'] === 'success') {
                    $geo['country'] = $data['country'] ?? 'Unknown';
                    $geo['country_code'] = $data['countryCode'] ?? 'XX';
                    $geo['city'] = $data['city'] ?? 'Unknown';
                    $geo['region'] = $data['regionName'] ?? 'Unknown';
                    $geo['latitude'] = $data['lat'] ?? 0;
                    $geo['longitude'] = $data['lon'] ?? 0;
                    $geo['timezone'] = $data['timezone'] ?? 'UTC';
                    $geo['flag'] = self::getCountryFlag($data['countryCode'] ?? 'XX');
                }
            }
        } catch (Exception $e) {
            // Silently fail
        }
        
        // Cache for 24 hours
        Cache::set($cacheKey, $geo, 86400);
        
        return $geo;
    }
    
    /**
     * Get country flag emoji
     */
    private static function getCountryFlag($countryCode) {
        $flags = [
            'US' => '🇺🇸', 'GB' => '🇬🇧', 'CA' => '🇨🇦', 'AU' => '🇦🇺',
            'DE' => '🇩🇪', 'FR' => '🇫🇷', 'ES' => '🇪🇸', 'IT' => '🇮🇹',
            'BR' => '🇧🇷', 'MX' => '🇲🇽', 'AR' => '🇦🇷', 'CL' => '🇨🇱',
            'IN' => '🇮🇳', 'CN' => '🇨🇳', 'JP' => '🇯🇵', 'KR' => '🇰🇷',
            'RU' => '🇷🇺', 'UA' => '🇺🇦', 'PL' => '🇵🇱', 'TR' => '🇹🇷',
            'SA' => '🇸🇦', 'AE' => '🇦🇪', 'EG' => '🇪🇬', 'ZA' => '🇿🇦',
            'NG' => '🇳🇬', 'KE' => '🇰🇪', 'MA' => '🇲🇦', 'DZ' => '🇩🇿',
            'SE' => '🇸🇪', 'NO' => '🇳🇴', 'DK' => '🇩🇰', 'FI' => '🇫🇮',
            'NL' => '🇳🇱', 'BE' => '🇧🇪', 'CH' => '🇨🇭', 'AT' => '🇦🇹',
            'PT' => '🇵🇹', 'GR' => '🇬🇷', 'IE' => '🇮🇪', 'CZ' => '🇨🇿'
        ];
        
        return $flags[$countryCode] ?? '🌍';
    }
    
    /**
     * Detect language from IP and headers
     */
    public static function detectLanguage($ip = null) {
        // First check Accept-Language header
        if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
            $supportedLangs = ['en', 'es', 'fr', 'de', 'pt', 'no'];
            if (in_array($lang, $supportedLangs)) {
                return $lang;
            }
        }
        
        // Then check by country
        if ($ip) {
            $geo = self::getGeolocation($ip);
            $countryToLang = [
                'US' => 'en', 'GB' => 'en', 'CA' => 'en', 'AU' => 'en',
                'ES' => 'es', 'MX' => 'es', 'AR' => 'es', 'CL' => 'es',
                'FR' => 'fr', 'BE' => 'fr', 'CH' => 'fr',
                'DE' => 'de', 'AT' => 'de',
                'BR' => 'pt', 'PT' => 'pt',
                'NO' => 'no', 'SE' => 'no', 'DK' => 'no'
            ];
            
            if (isset($countryToLang[$geo['country_code']])) {
                return $countryToLang[$geo['country_code']];
            }
        }
        
        return 'en'; // Default to English
    }
    
    /**
     * BIN Lookup - Get card information from BIN
     */
    public static function binLookup($cardNumber) {
        $bin = substr(str_replace(' ', '', $cardNumber), 0, 6);
        $cacheKey = 'bin_' . $bin;
        
        // Check cache first
        $cached = Cache::get($cacheKey);
        if ($cached !== null) {
            return $cached;
        }
        
        $binInfo = [
            'valid' => false,
            'brand' => 'Unknown',
            'type' => 'Unknown',
            'level' => 'Unknown',
            'bank' => 'Unknown',
            'country' => 'Unknown',
            'country_code' => 'XX'
        ];
        
        try {
            // Using binlist.net (free API)
            $response = @file_get_contents("https://lookup.binlist.net/{$bin}");
            if ($response) {
                $data = json_decode($response, true);
                $binInfo['valid'] = true;
                $binInfo['brand'] = ucfirst($data['scheme'] ?? 'Unknown');
                $binInfo['type'] = ucfirst($data['type'] ?? 'Unknown');
                $binInfo['level'] = ucfirst($data['brand'] ?? 'Unknown');
                $binInfo['bank'] = $data['bank']['name'] ?? 'Unknown';
                $binInfo['country'] = $data['country']['name'] ?? 'Unknown';
                $binInfo['country_code'] = $data['country']['alpha2'] ?? 'XX';
            }
        } catch (Exception $e) {
            // Silently fail
        }
        
        // Cache for 7 days (BIN data doesn't change often)
        Cache::set($cacheKey, $binInfo, 604800);
        
        return $binInfo;
    }
    
    /**
     * Rate limiting check
     */
    public static function checkRateLimit($ip, $maxRequests = 10, $timeWindow = 60) {
        $cacheKey = 'rate_limit_' . $ip;
        $requests = Cache::get($cacheKey) ?? [];
        
        // Clean old requests
        $now = time();
        $requests = array_filter($requests, function($timestamp) use ($now, $timeWindow) {
            return ($now - $timestamp) < $timeWindow;
        });
        
        // Check if limit exceeded
        if (count($requests) >= $maxRequests) {
            return false;
        }
        
        // Add current request
        $requests[] = $now;
        Cache::set($cacheKey, $requests, $timeWindow);
        
        return true;
    }
}
