<?php
require_once 'config.php';

/**
 * Track visitor information
 */
function trackVisitor($shortCode) {
    $ip = getRealIpAddr();
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    
    // Get geolocation data
    $geoData = getGeolocationData($ip);
    
    // Parse user agent
    $deviceInfo = parseUserAgent($userAgent);
    
    // Detect visitor type
    $visitorType = detectVisitorType($ip, $userAgent, $geoData);
    
    // Get network information
    $networkInfo = getNetworkInfo($userAgent);
    
    return [
        'id' => uniqid(),
        'short_code' => $shortCode,
        'ip' => $ip,
        'user_agent' => $userAgent,
        'timestamp' => date('Y-m-d H:i:s'),
        'country' => $geoData['country'] ?? 'Unknown',
        'country_code' => $geoData['country_code'] ?? 'XX',
        'region' => $geoData['region'] ?? 'Unknown',
        'city' => $geoData['city'] ?? 'Unknown',
        'latitude' => $geoData['latitude'] ?? null,
        'longitude' => $geoData['longitude'] ?? null,
        'timezone' => $geoData['timezone'] ?? 'Unknown',
        'isp' => $geoData['isp'] ?? 'Unknown',
        'org' => $geoData['org'] ?? 'Unknown',
        'as' => $geoData['as'] ?? 'Unknown',
        'device_type' => $deviceInfo['device_type'],
        'device_brand' => $deviceInfo['device_brand'],
        'device_model' => $deviceInfo['device_model'],
        'os' => $deviceInfo['os'],
        'os_version' => $deviceInfo['os_version'],
        'browser' => $deviceInfo['browser'],
        'browser_version' => $deviceInfo['browser_version'],
        'is_mobile' => $deviceInfo['is_mobile'],
        'is_tablet' => $deviceInfo['is_tablet'],
        'is_desktop' => $deviceInfo['is_desktop'],
        'connection_type' => $networkInfo['connection_type'],
        'network_generation' => $networkInfo['network_generation'],
        'carrier' => $networkInfo['carrier'],
        'is_human' => $visitorType['is_human'],
        'is_bot' => $visitorType['is_bot'],
        'is_proxy' => $visitorType['is_proxy'],
        'is_hosting' => $visitorType['is_hosting'],
        'is_vpn' => $visitorType['is_vpn'],
        'threat_level' => $visitorType['threat_level'],
        'visitor_category' => $visitorType['category']
    ];
}

/**
 * Get real IP address
 */
function getRealIpAddr() {
    $ipKeys = ['HTTP_X_REAL_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'];
    
    foreach ($ipKeys as $key) {
        if (array_key_exists($key, $_SERVER) === true) {
            $ip = $_SERVER[$key];
            if (strpos($ip, ',') !== false) {
                $ip = explode(',', $ip)[0];
            }
            $ip = trim($ip);
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                return $ip;
            }
        }
    }
    
    return $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
}

/**
 * Get enhanced geolocation and service detection data for IP
 */
function getGeolocationData($ip) {
    $geoData = [];
    
    // Try ip-api.com first with enhanced fields for threat detection
    $url = IPAPI_URL . $ip . '?fields=status,message,country,countryCode,region,regionName,city,zip,lat,lon,timezone,isp,org,as,asname,mobile,proxy,hosting,query';
    
    $response = @file_get_contents($url);
    if ($response) {
        $data = json_decode($response, true);
        if ($data && $data['status'] === 'success') {
            $geoData = [
                'country' => $data['country'] ?? 'Unknown',
                'country_code' => strtolower($data['countryCode'] ?? 'xx'),
                'region' => $data['regionName'] ?? 'Unknown',
                'city' => $data['city'] ?? 'Unknown',
                'latitude' => $data['lat'] ?? null,
                'longitude' => $data['lon'] ?? null,
                'timezone' => $data['timezone'] ?? 'Unknown',
                'isp' => $data['isp'] ?? 'Unknown',
                'org' => $data['org'] ?? 'Unknown',
                'as' => $data['as'] ?? 'Unknown',
                'asname' => $data['asname'] ?? 'Unknown',
                // Enhanced detection fields from ip-api
                'is_mobile' => $data['mobile'] ?? false,
                'is_proxy' => $data['proxy'] ?? false,
                'is_hosting' => $data['hosting'] ?? false
            ];
        }
    }
    
    // If first API failed, try ipapi.co as backup with additional threat detection
    if (empty($geoData)) {
        $url = IPINFO_URL . $ip . '/json/';
        $response = @file_get_contents($url);
        if ($response) {
            $data = json_decode($response, true);
            if ($data && !isset($data['error'])) {
                $geoData = [
                    'country' => $data['country_name'] ?? 'Unknown',
                    'country_code' => strtolower($data['country_code'] ?? 'xx'),
                    'region' => $data['region'] ?? 'Unknown',
                    'city' => $data['city'] ?? 'Unknown',
                    'latitude' => $data['latitude'] ?? null,
                    'longitude' => $data['longitude'] ?? null,
                    'timezone' => $data['timezone'] ?? 'Unknown',
                    'isp' => $data['org'] ?? 'Unknown',
                    'org' => $data['org'] ?? 'Unknown',
                    'as' => $data['asn'] ?? 'Unknown',
                    'asname' => $data['asn'] ?? 'Unknown',
                    // Additional threat detection from ipapi.co
                    'threat_types' => $data['threat_types'] ?? [],
                    'is_proxy' => in_array('proxy', $data['threat_types'] ?? []),
                    'is_hosting' => strpos(strtolower($data['connection']['type'] ?? ''), 'hosting') !== false
                ];
            }
        }
    }
    
    // Enhanced ASN analysis for better detection
    if (!empty($geoData['as'])) {
        $geoData = enhanceASNAnalysis($geoData);
    }
    
    return $geoData;
}

/**
 * Enhanced ASN analysis for better service detection
 */
function enhanceASNAnalysis($geoData) {
    $asInfo = strtolower($geoData['as'] ?? '');
    $asnameInfo = strtolower($geoData['asname'] ?? '');
    $ispInfo = strtolower($geoData['isp'] ?? '');
    $orgInfo = strtolower($geoData['org'] ?? '');
    
    // Check for known datacenter/hosting ASNs
    $hostingASNs = [
        'as13335' => 'Cloudflare', // Cloudflare
        'as16509' => 'Amazon AWS', // Amazon
        'as15169' => 'Google', // Google
        'as8075' => 'Microsoft', // Microsoft
        'as14061' => 'DigitalOcean', // DigitalOcean
        'as63949' => 'Linode', // Linode
        'as20473' => 'Vultr', // Vultr
        'as24940' => 'Hetzner', // Hetzner
        'as16276' => 'OVH' // OVH
    ];
    
    foreach ($hostingASNs as $asn => $provider) {
        if (strpos($asInfo, $asn) !== false) {
            $geoData['is_hosting'] = true;
            $geoData['hosting_provider'] = $provider;
            break;
        }
    }
    
    // Check for VPN/Proxy indicators in ASN names
    $vpnIndicators = ['vpn', 'proxy', 'tor', 'tunnel', 'anonymous', 'private', 'secure'];
    foreach ($vpnIndicators as $indicator) {
        if (strpos($asnameInfo, $indicator) !== false || 
            strpos($ispInfo, $indicator) !== false || 
            strpos($orgInfo, $indicator) !== false) {
            $geoData['is_proxy'] = true;
            $geoData['service_type'] = 'vpn/proxy';
            break;
        }
    }
    
    // Check for hosting indicators
    $hostingIndicators = ['hosting', 'server', 'cloud', 'datacenter', 'data center', 'colocation', 'colo'];
    $hostingCount = 0;
    foreach ($hostingIndicators as $indicator) {
        if (strpos($asnameInfo, $indicator) !== false || 
            strpos($ispInfo, $indicator) !== false || 
            strpos($orgInfo, $indicator) !== false) {
            $hostingCount++;
        }
    }
    
    if ($hostingCount >= 1) {
        $geoData['is_hosting'] = true;
        $geoData['service_type'] = 'hosting/vps';
    }
    
    return $geoData;
}

/**
 * Parse user agent string
 */
function parseUserAgent($userAgent) {
    $deviceInfo = [
        'device_type' => 'Unknown',
        'device_brand' => 'Unknown',
        'device_model' => 'Unknown',
        'os' => 'Unknown',
        'os_version' => 'Unknown',
        'browser' => 'Unknown',
        'browser_version' => 'Unknown',
        'is_mobile' => false,
        'is_tablet' => false,
        'is_desktop' => false
    ];
    
    // Detect mobile
    if (preg_match('/Mobile|Android|iPhone|iPad|iPod|BlackBerry|Windows Phone/', $userAgent)) {
        $deviceInfo['is_mobile'] = true;
        $deviceInfo['device_type'] = 'Mobile';
    }
    
    // Detect tablet
    if (preg_match('/iPad|Android(?!.*Mobile)|Tablet/', $userAgent)) {
        $deviceInfo['is_tablet'] = true;
        $deviceInfo['is_mobile'] = false;
        $deviceInfo['device_type'] = 'Tablet';
    }
    
    // Desktop by default
    if (!$deviceInfo['is_mobile'] && !$deviceInfo['is_tablet']) {
        $deviceInfo['is_desktop'] = true;
        $deviceInfo['device_type'] = 'Desktop';
    }
    
    // Detect OS
    $osPatterns = [
        'Windows NT 10.0' => 'Windows 10',
        'Windows NT 6.3' => 'Windows 8.1',
        'Windows NT 6.2' => 'Windows 8',
        'Windows NT 6.1' => 'Windows 7',
        'Windows NT 6.0' => 'Windows Vista',
        'Windows NT 5.1' => 'Windows XP',
        'Mac OS X' => 'macOS',
        'iPhone OS' => 'iOS',
        'iPad OS' => 'iPadOS',
        'Android' => 'Android',
        'Linux' => 'Linux',
        'Ubuntu' => 'Ubuntu',
        'CrOS' => 'Chrome OS'
    ];
    
    foreach ($osPatterns as $pattern => $os) {
        if (strpos($userAgent, $pattern) !== false) {
            $deviceInfo['os'] = $os;
            // Try to extract version
            if (preg_match('/' . preg_quote($pattern) . '\s?([\d\.]+)/', $userAgent, $matches)) {
                $deviceInfo['os_version'] = $matches[1];
            }
            break;
        }
    }
    
    // Detect browser
    $browserPatterns = [
        'Chrome' => 'Chrome',
        'Firefox' => 'Firefox',
        'Safari' => 'Safari',
        'Edge' => 'Edge',
        'Opera' => 'Opera',
        'Internet Explorer' => 'Internet Explorer'
    ];
    
    foreach ($browserPatterns as $pattern => $browser) {
        if (strpos($userAgent, $pattern) !== false) {
            $deviceInfo['browser'] = $browser;
            // Try to extract version
            if (preg_match('/' . $pattern . '\/?([\d\.]+)/', $userAgent, $matches)) {
                $deviceInfo['browser_version'] = $matches[1];
            }
            break;
        }
    }
    
    // Detect device brand and model (simplified)
    $devicePatterns = [
        'iPhone' => ['brand' => 'Apple', 'model' => 'iPhone'],
        'iPad' => ['brand' => 'Apple', 'model' => 'iPad'],
        'Samsung' => ['brand' => 'Samsung', 'model' => 'Samsung Device'],
        'Huawei' => ['brand' => 'Huawei', 'model' => 'Huawei Device'],
        'Xiaomi' => ['brand' => 'Xiaomi', 'model' => 'Xiaomi Device']
    ];
    
    foreach ($devicePatterns as $pattern => $info) {
        if (strpos($userAgent, $pattern) !== false) {
            $deviceInfo['device_brand'] = $info['brand'];
            $deviceInfo['device_model'] = $info['model'];
            break;
        }
    }
    
    return $deviceInfo;
}

/**
 * Detect visitor type (human vs bot vs proxy etc.) - AI-Enhanced with IP service detection
 */
function detectVisitorType($ip, $userAgent, $geoData) {
    $visitorType = [
        'is_human' => true,
        'is_bot' => false,
        'is_proxy' => false,
        'is_hosting' => false,
        'is_vpn' => false,
        'threat_level' => 'low',
        'category' => 'human'
    ];
    
    $userAgentLower = strtolower($userAgent);
    $isp = strtolower($geoData['isp'] ?? '');
    $org = strtolower($geoData['org'] ?? '');
    $as = strtolower($geoData['as'] ?? '');
    $asname = strtolower($geoData['asname'] ?? '');
    
    // 1. Check for bot patterns in user agent (highest priority)
    foreach (BOT_PATTERNS as $pattern) {
        if (strpos($userAgentLower, $pattern) !== false) {
            $visitorType['is_human'] = false;
            $visitorType['is_bot'] = true;
            $visitorType['category'] = 'bot';
            $visitorType['threat_level'] = 'low';
            return $visitorType;
        }
    }
    
    // 2. Use API-provided service detection (most reliable)
    if (isset($geoData['is_proxy']) && $geoData['is_proxy'] === true) {
        $visitorType['is_human'] = false;
        $visitorType['is_proxy'] = true;
        $visitorType['is_vpn'] = true;
        $visitorType['category'] = 'proxy';
        $visitorType['threat_level'] = 'high';
        return $visitorType;
    }
    
    if (isset($geoData['is_hosting']) && $geoData['is_hosting'] === true) {
        $visitorType['is_human'] = false;
        $visitorType['is_hosting'] = true;
        $visitorType['category'] = 'hosting';
        $visitorType['threat_level'] = 'medium';
        return $visitorType;
    }
    
    // 3. Enhanced VPN/Proxy pattern detection
    foreach (VPN_PATTERNS as $pattern) {
        if (strpos($isp, $pattern) !== false || 
            strpos($org, $pattern) !== false || 
            strpos($as, $pattern) !== false ||
            strpos($asname, $pattern) !== false) {
            $visitorType['is_human'] = false;
            $visitorType['is_proxy'] = true;
            $visitorType['is_vpn'] = true;
            $visitorType['category'] = 'proxy';
            $visitorType['threat_level'] = 'high';
            return $visitorType;
        }
    }
    
    // 4. Enhanced hosting/VPS detection with comprehensive matching
    foreach (HOSTING_ASNS as $hostingProvider) {
        $hostingLower = strtolower($hostingProvider);
        $patterns = [
            $hostingLower,
            str_replace(' ', '', $hostingLower),
            str_replace(' ', '-', $hostingLower),
            str_replace(' ', '.', $hostingLower)
        ];
        
        foreach ($patterns as $pattern) {
            if (strpos($isp, $pattern) !== false || 
                strpos($org, $pattern) !== false || 
                strpos($as, $pattern) !== false ||
                strpos($asname, $pattern) !== false) {
                $visitorType['is_human'] = false;
                $visitorType['is_hosting'] = true;
                $visitorType['category'] = 'hosting';
                $visitorType['threat_level'] = 'medium';
                return $visitorType;
            }
        }
    }
    
    // 5. Advanced hosting detection by keyword analysis
    $hostingKeywords = [
        'hosting', 'server', 'cloud', 'vps', 'dedicated', 'datacenter', 'data center',
        'colocation', 'colo', 'solutions', 'technology', 'systems', 'networks',
        'internet services', 'web services', 'digital', 'cyber', 'tech'
    ];
    
    $suspiciousCount = 0;
    $hostingScore = 0;
    
    foreach ($hostingKeywords as $keyword) {
        if (strpos($isp, $keyword) !== false) $hostingScore += 2;
        if (strpos($org, $keyword) !== false) $hostingScore += 2;
        if (strpos($asname, $keyword) !== false) $hostingScore += 1;
        if (strpos($as, $keyword) !== false) $hostingScore += 1;
    }
    
    // If hosting score is high, classify as hosting
    if ($hostingScore >= 3) {
        $visitorType['is_human'] = false;
        $visitorType['is_hosting'] = true;
        $visitorType['category'] = 'hosting';
        $visitorType['threat_level'] = 'medium';
        return $visitorType;
    }
    
    // 6. Check threat patterns from enhanced APIs
    if (isset($geoData['threat_types']) && !empty($geoData['threat_types'])) {
        $visitorType['is_human'] = false;
        $visitorType['threat_level'] = 'high';
        $visitorType['category'] = 'threat';
        return $visitorType;
    }
    
    // 7. Advanced threat pattern detection
    foreach (THREAT_PATTERNS as $pattern) {
        if (strpos($isp, $pattern) !== false || 
            strpos($org, $pattern) !== false || 
            strpos($as, $pattern) !== false ||
            strpos($asname, $pattern) !== false) {
            $visitorType['is_human'] = false;
            $visitorType['threat_level'] = 'high';
            $visitorType['category'] = 'threat';
            return $visitorType;
        }
    }
    
    // 8. Suspicious user agent checks
    if (empty($userAgent) || strlen($userAgent) < 20) {
        $visitorType['is_human'] = false;
        $visitorType['threat_level'] = 'high';
        $visitorType['category'] = 'suspicious';
        return $visitorType;
    }
    
    // 9. ISP type analysis for final classification
    $residentialPatterns = [
        'broadband', 'cable', 'dsl', 'fiber optic', 'mobile', 'wireless', 'home',
        'residential', 'consumer', 'retail', 'telecom', 'communication'
    ];
    
    $isResidential = false;
    foreach ($residentialPatterns as $pattern) {
        if (strpos($isp, $pattern) !== false) {
            $isResidential = true;
            $visitorType['threat_level'] = 'low';
            break;
        }
    }
    
    // 10. Final score-based decision for edge cases
    if (!$isResidential && $hostingScore >= 1) {
        $visitorType['threat_level'] = 'medium';
    }
    
    return $visitorType;
}

/**
 * Get network information
 */
function getNetworkInfo($userAgent) {
    $networkInfo = [
        'connection_type' => 'Unknown',
        'network_generation' => 'Unknown',
        'carrier' => 'Unknown'
    ];
    
    // Detect connection type (simplified)
    if (strpos($userAgent, 'Mobile') !== false) {
        $networkInfo['connection_type'] = 'Mobile Data';
        
        // Try to detect network generation
        if (preg_match('/\b(5G|NR)\b/i', $userAgent)) {
            $networkInfo['network_generation'] = '5G';
        } elseif (preg_match('/\b(4G|LTE)\b/i', $userAgent)) {
            $networkInfo['network_generation'] = '4G/LTE';
        } elseif (preg_match('/\b(3G|UMTS|HSPA)\b/i', $userAgent)) {
            $networkInfo['network_generation'] = '3G';
        } elseif (preg_match('/\b(2G|EDGE|GPRS)\b/i', $userAgent)) {
            $networkInfo['network_generation'] = '2G';
        }
    } else {
        $networkInfo['connection_type'] = 'WiFi/Broadband';
    }
    
    // Carrier detection would require more sophisticated methods
    // For now, we'll leave it as Unknown unless we can detect it from ISP
    
    return $networkInfo;
}
?>
