<?php
// Device Security System

function initDeviceTables() {
    $db = getDB();
    try {
        $db->exec("CREATE TABLE IF NOT EXISTS user_devices (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL,
            device_token VARCHAR(64) NOT NULL,
            device_name VARCHAR(200) DEFAULT NULL,
            browser VARCHAR(100) DEFAULT NULL,
            os VARCHAR(100) DEFAULT NULL,
            ip_address VARCHAR(45) DEFAULT NULL,
            country VARCHAR(100) DEFAULT NULL,
            city VARCHAR(100) DEFAULT NULL,
            is_active TINYINT(1) DEFAULT 1,
            is_blocked TINYINT(1) DEFAULT 0,
            first_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            login_count INT DEFAULT 1,
            UNIQUE KEY uq_user_device (user_id, device_token)
        ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
        // Settings
        $db->exec("INSERT IGNORE INTO settings (`key`,`value`) VALUES ('max_devices','3')");
        $db->exec("INSERT IGNORE INTO settings (`key`,`value`) VALUES ('whatsapp_number','')");
        $db->exec("INSERT IGNORE INTO settings (`key`,`value`) VALUES ('device_limit_enabled','1')");
    } catch(Exception $e) {}
}

// Generate device fingerprint from browser info
function getDeviceToken() {
    $ua      = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $ip      = getClientIP();
    $accept  = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
    // Stable fingerprint — not IP dependent
    $raw = $ua . '|' . $accept;
    return substr(hash('sha256', $raw), 0, 32);
}

function getClientIP() {
    foreach (['HTTP_CF_CONNECTING_IP','HTTP_X_FORWARDED_FOR','HTTP_X_REAL_IP','REMOTE_ADDR'] as $k) {
        if (!empty($_SERVER[$k])) {
            $ip = trim(explode(',', $_SERVER[$k])[0]);
            if (filter_var($ip, FILTER_VALIDATE_IP)) return $ip;
        }
    }
    return '0.0.0.0';
}

function parseUserAgent($ua) {
    $browser = 'Unknown'; $os = 'Unknown';
    // Browser
    if (strpos($ua,'Chrome')!==false && strpos($ua,'Edg')===false && strpos($ua,'OPR')===false) $browser='Chrome';
    elseif (strpos($ua,'Firefox')!==false) $browser='Firefox';
    elseif (strpos($ua,'Safari')!==false && strpos($ua,'Chrome')===false) $browser='Safari';
    elseif (strpos($ua,'Edg')!==false) $browser='Edge';
    elseif (strpos($ua,'OPR')!==false || strpos($ua,'Opera')!==false) $browser='Opera';
    // OS
    if (strpos($ua,'Android')!==false) { preg_match('/Android\s([0-9.]+)/i',$ua,$m); $os='Android '.($m[1]??''); }
    elseif (strpos($ua,'iPhone')!==false||strpos($ua,'iPad')!==false) $os='iOS';
    elseif (strpos($ua,'Windows')!==false) $os='Windows';
    elseif (strpos($ua,'Mac')!==false) $os='macOS';
    elseif (strpos($ua,'Linux')!==false) $os='Linux';
    // Device name
    $name = $browser.' on '.$os;
    return ['browser'=>$browser,'os'=>$os,'name'=>$name];
}

// Get IP location (simple, no external API needed)
function getIPLocation($ip) {
    if ($ip === '127.0.0.1' || $ip === '::1' || strpos($ip,'192.168.')===0) return ['country'=>'Local','city'=>'Local'];
    try {
        $ctx = stream_context_create(['http'=>['timeout'=>2,'ignore_errors'=>true]]);
        $res = @file_get_contents("http://ip-api.com/json/{$ip}?fields=country,city,status", false, $ctx);
        if($res) { $d=json_decode($res,true); if($d&&$d['status']==='success') return ['country'=>$d['country']??'','city'=>$d['city']??'']; }
    } catch(Exception $e) {}
    return ['country'=>'Unknown','city'=>'Unknown'];
}

// Check device on login — returns ['ok'=>bool, 'blocked'=>bool, 'limit'=>bool, 'device_id'=>int]
function checkDeviceLogin($userId) {
    initDeviceTables();
    $db          = getDB();
    $enabled     = getSetting('device_limit_enabled') ?? '1';
    $maxDevices  = intval(getSetting('max_devices') ?? 3);
    $token       = getDeviceToken();
    $ip          = getClientIP();
    $ua          = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $parsed      = parseUserAgent($ua);

    // Check if device exists for this user
    $s = $db->prepare("SELECT * FROM user_devices WHERE user_id=? AND device_token=?");
    $s->execute([$userId, $token]); $device = $s->fetch();

    if ($device) {
        // Device known
        if ($device['is_blocked']) {
            return ['ok'=>false,'blocked'=>true,'limit'=>false,'device_id'=>$device['id'],'device'=>$device];
        }
        // Update last seen + IP
        $loc = getIPLocation($ip);
        $db->prepare("UPDATE user_devices SET last_seen=NOW(),ip_address=?,country=?,city=?,login_count=login_count+1 WHERE id=?")
           ->execute([$ip,$loc['country'],$loc['city'],$device['id']]);
        return ['ok'=>true,'blocked'=>false,'limit'=>false,'device_id'=>$device['id']];
    }

    // New device — check limit
    if ($enabled === '1') {
        $activeCount = $db->prepare("SELECT COUNT(*) FROM user_devices WHERE user_id=? AND is_active=1 AND is_blocked=0");
        $activeCount->execute([$userId]);
        if ($activeCount->fetchColumn() >= $maxDevices) {
            return ['ok'=>false,'blocked'=>false,'limit'=>true,'device_id'=>0];
        }
    }

    // Register new device
    $loc  = getIPLocation($ip);
    try {
        $db->prepare("INSERT INTO user_devices (user_id,device_token,device_name,browser,os,ip_address,country,city) VALUES (?,?,?,?,?,?,?,?)")
           ->execute([$userId,$token,$parsed['name'],$parsed['browser'],$parsed['os'],$ip,$loc['country'],$loc['city']]);
        $newId = $db->lastInsertId();
        return ['ok'=>true,'blocked'=>false,'limit'=>false,'device_id'=>$newId];
    } catch(Exception $e) {
        return ['ok'=>true,'blocked'=>false,'limit'=>false,'device_id'=>0];
    }
}

// Check on every page load (session based — fast)
function checkDeviceSession($userId) {
    if (empty($_SESSION['device_token'])) return true; // Not set yet
    $db    = getDB();
    $token = $_SESSION['device_token'];
    try {
        $s = $db->prepare("SELECT is_blocked,is_active FROM user_devices WHERE user_id=? AND device_token=?");
        $s->execute([$userId,$token]); $d = $s->fetch();
        if (!$d) return true;
        if ($d['is_blocked'] || !$d['is_active']) return false;
    } catch(Exception $e) {}
    return true;
}
