<?php
/**
 * TrackPro — IP Intelligence, UA Parsing & Risk Scoring
 */

class UAParser {
    public static function parse(string $ua): array {
        $result = [
            'browser_name' => 'Unknown',
            'browser_version' => '',
            'browser_engine' => '',
            'os_name' => 'Unknown',
            'os_version' => '',
            'device_type' => 'desktop',
        ];

        // Device type
        if (preg_match('/Mobile|Android.*Mobile|iPhone|iPod/i', $ua)) $result['device_type'] = 'mobile';
        elseif (preg_match('/iPad|Android(?!.*Mobile)|Tablet/i', $ua)) $result['device_type'] = 'tablet';
        elseif (preg_match('/Bot|Crawl|Spider|Slurp|Mediapartners/i', $ua)) $result['device_type'] = 'bot';

        // OS detection
        if (preg_match('/Windows NT (\d+\.\d+)/i', $ua, $m)) {
            $result['os_name'] = 'Windows';
            $map = ['10.0'=>'10/11','6.3'=>'8.1','6.2'=>'8','6.1'=>'7','6.0'=>'Vista','5.1'=>'XP'];
            $result['os_version'] = $map[$m[1]] ?? $m[1];
        } elseif (preg_match('/Mac OS X (\d+[._]\d+[._]?\d*)/i', $ua, $m)) {
            $result['os_name'] = 'macOS';
            $result['os_version'] = str_replace('_', '.', $m[1]);
        } elseif (preg_match('/iPhone OS (\d+[._]\d+)/i', $ua, $m)) {
            $result['os_name'] = 'iOS';
            $result['os_version'] = str_replace('_', '.', $m[1]);
        } elseif (preg_match('/Android (\d+[\.\d]*)/i', $ua, $m)) {
            $result['os_name'] = 'Android';
            $result['os_version'] = $m[1];
        } elseif (preg_match('/Linux/i', $ua)) {
            $result['os_name'] = 'Linux';
        } elseif (preg_match('/CrOS/i', $ua)) {
            $result['os_name'] = 'ChromeOS';
        }

        // Browser detection (order matters)
        if (preg_match('/EdgA?\/(\d+[\.\d]*)/i', $ua, $m)) {
            $result['browser_name'] = 'Edge'; $result['browser_version'] = $m[1]; $result['browser_engine'] = 'Blink';
        } elseif (preg_match('/OPR\/(\d+[\.\d]*)/i', $ua, $m)) {
            $result['browser_name'] = 'Opera'; $result['browser_version'] = $m[1]; $result['browser_engine'] = 'Blink';
        } elseif (preg_match('/Brave/i', $ua)) {
            $result['browser_name'] = 'Brave'; $result['browser_engine'] = 'Blink';
            if (preg_match('/Chrome\/(\d+[\.\d]*)/i', $ua, $m)) $result['browser_version'] = $m[1];
        } elseif (preg_match('/Vivaldi\/(\d+[\.\d]*)/i', $ua, $m)) {
            $result['browser_name'] = 'Vivaldi'; $result['browser_version'] = $m[1]; $result['browser_engine'] = 'Blink';
        } elseif (preg_match('/SamsungBrowser\/(\d+[\.\d]*)/i', $ua, $m)) {
            $result['browser_name'] = 'Samsung Browser'; $result['browser_version'] = $m[1]; $result['browser_engine'] = 'Blink';
        } elseif (preg_match('/Firefox\/(\d+[\.\d]*)/i', $ua, $m)) {
            $result['browser_name'] = 'Firefox'; $result['browser_version'] = $m[1]; $result['browser_engine'] = 'Gecko';
        } elseif (preg_match('/Chrome\/(\d+[\.\d]*)/i', $ua, $m) && !preg_match('/Edg|OPR/i', $ua)) {
            $result['browser_name'] = 'Chrome'; $result['browser_version'] = $m[1]; $result['browser_engine'] = 'Blink';
        } elseif (preg_match('/Safari\/(\d+[\.\d]*)/i', $ua, $m) && preg_match('/Version\/(\d+[\.\d]*)/i', $ua, $v)) {
            $result['browser_name'] = 'Safari'; $result['browser_version'] = $v[1]; $result['browser_engine'] = 'WebKit';
        }

        return $result;
    }
}

class IPIntelligence {

    /**
     * Lookup IP geolocation and threat data
     * Note: On shared hosting without external API, returns basic data from server vars
     */
    public static function lookup(string $ip): array {
        $result = [
            'ip' => $ip,
            'ip_version' => filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? 'IPv6' : 'IPv4',
            'country' => null,
            'country_code' => null,
            'region' => null,
            'city' => null,
            'postal_code' => null,
            'latitude' => null,
            'longitude' => null,
            'timezone' => null,
            'isp' => null,
            'mobile_carrier' => null,
            'asn' => null,
            'as_org' => null,
            'network_type' => 'unknown',
            'is_proxy' => 0,
            'is_vpn' => 0,
            'is_tor' => 0,
            'threat_score' => 0,
        ];

        // Try ip-api.com (free, no key needed, 45 req/min)
        $url = "http://ip-api.com/json/" . urlencode($ip) . "?fields=status,country,countryCode,region,regionName,city,zip,lat,lon,timezone,isp,org,as,mobile,proxy,hosting";
        $ctx = stream_context_create(['http' => ['timeout' => 3, 'ignore_errors' => true]]);
        $json = @file_get_contents($url, false, $ctx);
        if ($json) {
            $d = json_decode($json, true);
            if (isset($d['status']) && $d['status'] === 'success') {
                $result['country'] = $d['country'] ?? null;
                $result['country_code'] = $d['countryCode'] ?? null;
                $result['region'] = $d['regionName'] ?? null;
                $result['city'] = $d['city'] ?? null;
                $result['postal_code'] = $d['zip'] ?? null;
                $result['latitude'] = $d['lat'] ?? null;
                $result['longitude'] = $d['lon'] ?? null;
                $result['timezone'] = $d['timezone'] ?? null;
                $result['isp'] = $d['isp'] ?? null;
                $result['as_org'] = $d['org'] ?? null;
                $result['asn'] = isset($d['as']) ? preg_replace('/[^0-9]/', '', explode(' ', $d['as'])[0]) : null;
                $result['is_proxy'] = !empty($d['proxy']) ? 1 : 0;
                $result['is_vpn'] = !empty($d['proxy']) && !empty($d['hosting']) ? 1 : 0;
                $result['mobile_carrier'] = !empty($d['mobile']) ? ($d['isp'] ?? 'mobile') : null;
                $result['network_type'] = !empty($d['mobile']) ? 'cellular' : (!empty($d['hosting']) ? 'datacenter' : 'residential');
            }
        }

        // Tor exit node check (basic)
        $torCheck = self::isTorExitNode($ip);
        if ($torCheck) {
            $result['is_tor'] = 1;
            $result['is_vpn'] = 1;
            $result['network_type'] = 'tor';
        }

        return $result;
    }

    /**
     * Basic Tor exit node check via DNS
     */
    private static function isTorExitNode(string $ip): bool {
        if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) return false;
        $rev = implode('.', array_reverse(explode('.', $ip)));
        $lookup = $rev . '.dnsel.torproject.org';
        $result = @dns_get_record($lookup, DNS_A);
        return !empty($result);
    }

    /**
     * Calculate risk score from network + client data
     */
    public static function calculateRisk(array $data): array {
        $risk = [
            'risk_score' => 0,
            'fraud_score' => 0,
            'bot_likelihood' => 0,
            'is_emulator' => 0,
            'is_rooted' => 0,
            'risk_factors' => [],
        ];

        if (!empty($data['is_vpn'])) { $risk['fraud_score'] += 15; $risk['risk_factors'][] = 'vpn'; }
        if (!empty($data['is_tor'])) { $risk['fraud_score'] += 30; $risk['risk_factors'][] = 'tor'; }
        if (!empty($data['is_proxy'])) { $risk['fraud_score'] += 20; $risk['risk_factors'][] = 'proxy'; }

        $ua = strtolower($data['user_agent'] ?? '');
        foreach (['bot','crawl','spider','scraper','phantom','headless','selenium','puppeteer','playwright'] as $p) {
            if (strpos($ua, $p) !== false) { $risk['bot_likelihood'] += 40; $risk['risk_factors'][] = 'bot_ua'; break; }
        }

        if (!empty($data['webdriver'])) { $risk['bot_likelihood'] += 50; $risk['risk_factors'][] = 'webdriver'; }
        if (empty($data['screen_width']) && empty($data['browser_name'])) { $risk['bot_likelihood'] += 20; $risk['risk_factors'][] = 'no_js_data'; }

        $gpu = strtolower($data['gpu_renderer'] ?? '');
        if (strpos($gpu, 'swiftshader') !== false || strpos($gpu, 'llvmpipe') !== false) {
            $risk['is_emulator'] = 1; $risk['fraud_score'] += 25; $risk['risk_factors'][] = 'emulator_gpu';
        }

        $mem = floatval($data['device_memory'] ?? 0);
        if ($mem > 0 && $mem < 1) { $risk['fraud_score'] += 10; $risk['risk_factors'][] = 'low_memory'; }

        if (!empty($data['connection_type']) && $data['connection_type'] === 'datacenter') {
            $risk['fraud_score'] += 20; $risk['risk_factors'][] = 'datacenter_ip';
        }

        $risk['fraud_score'] = min(100, $risk['fraud_score']);
        $risk['bot_likelihood'] = min(100, $risk['bot_likelihood']);
        $risk['risk_score'] = min(100, max($risk['fraud_score'], $risk['bot_likelihood']) * 0.8);

        return $risk;
    }
}
