<?php
/**
 * Centralizovana kontrola životnog ciklusa autentifikovane PHP sesije.
 * Ne uvodi paralelni autentifikacioni mehanizam i ne čuva osetljive podatke u pregledaču.
 */

function session_idle_timeout_seconds(): int
{
    $configured = defined('APP_SESSION_IDLE_SECONDS') ? (int)APP_SESSION_IDLE_SECONDS : 600;
    return max(60, $configured);
}

function session_warning_duration_seconds(): int
{
    $configured = defined('APP_SESSION_WARNING_SECONDS') ? (int)APP_SESSION_WARNING_SECONDS : 60;
    return max(10, $configured);
}

function session_activity_throttle_seconds(): int
{
    $configured = defined('APP_SESSION_ACTIVITY_THROTTLE_SECONDS') ? (int)APP_SESSION_ACTIVITY_THROTTLE_SECONDS : 60;
    return max(5, min($configured, session_idle_timeout_seconds()));
}

function session_hard_timeout_seconds(): int
{
    return session_idle_timeout_seconds() + session_warning_duration_seconds();
}

function authenticated_session_exists(): bool
{
    return !empty($_SESSION['user_id']);
}

function session_last_user_activity_at(): int
{
    return (int)($_SESSION['last_activity'] ?? 0);
}

function session_started_at(): int
{
    return (int)($_SESSION['session_started_at'] ?? 0);
}

function authenticated_session_has_expired(?int $now = null): bool
{
    if (!authenticated_session_exists()) {
        return false;
    }

    $lastActivity = session_last_user_activity_at();
    if ($lastActivity <= 0) {
        return false;
    }

    $now = $now ?? time();
    return ($now - $lastActivity) >= session_hard_timeout_seconds();
}

function mark_authenticated_user_activity(?int $timestamp = null): int
{
    if (!authenticated_session_exists()) {
        return 0;
    }

    $timestamp = $timestamp ?? time();
    $_SESSION['last_activity'] = $timestamp;
    if (empty($_SESSION['session_started_at'])) {
        $_SESSION['session_started_at'] = $timestamp;
    }
    return $timestamp;
}

function invalidate_current_session(): void
{
    $_SESSION = [];

    if (ini_get('session.use_cookies')) {
        $params = session_get_cookie_params();
        setcookie(session_name(), '', [
            'expires' => time() - 42000,
            'path' => $params['path'] ?: '/',
            'domain' => $params['domain'] ?? '',
            'secure' => (bool)($params['secure'] ?? false),
            'httponly' => (bool)($params['httponly'] ?? true),
            'samesite' => $params['samesite'] ?? 'Lax',
        ]);
    }

    if (session_status() === PHP_SESSION_ACTIVE) {
        session_destroy();
    }
}

function start_clean_anonymous_session(): void
{
    if (session_status() !== PHP_SESSION_ACTIVE) {
        session_start();
    }
}

function queue_session_expired_notice(): void
{
    if (!empty($_SESSION['session_expiry_notice_queued'])) {
        return;
    }

    $_SESSION['session_expiry_notice_queued'] = 1;
    $_SESSION['flash'][] = [
        'type' => 'warning',
        'message' => 'Sesija je istekla zbog neaktivnosti.',
    ];
}

function request_represents_user_navigation(): bool
{
    if (!authenticated_session_exists()) {
        return false;
    }

    $method = strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? 'GET'));
    if (!in_array($method, ['GET', 'POST'], true)) {
        return false;
    }

    $requestedWith = strtolower((string)($_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''));
    $accept = strtolower((string)($_SERVER['HTTP_ACCEPT'] ?? ''));
    $fetchMode = strtolower((string)($_SERVER['HTTP_SEC_FETCH_MODE'] ?? ''));
    $fetchDestination = strtolower((string)($_SERVER['HTTP_SEC_FETCH_DEST'] ?? ''));
    $purpose = strtolower((string)($_SERVER['HTTP_SEC_PURPOSE'] ?? $_SERVER['HTTP_PURPOSE'] ?? ''));

    if ($requestedWith === 'xmlhttprequest' || str_contains($accept, 'application/json') || str_contains($purpose, 'prefetch')) {
        return false;
    }

    if ($fetchMode === 'navigate' || $fetchDestination === 'document') {
        return true;
    }

    // Kompatibilni fallback za starije pregledače/proxy slojeve bez Sec-Fetch zaglavlja.
    return str_contains($accept, 'text/html');
}

function request_wants_json(): bool
{
    $accept = strtolower((string)($_SERVER['HTTP_ACCEPT'] ?? ''));
    $requestedWith = strtolower((string)($_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''));
    return str_contains($accept, 'application/json')
        || $requestedWith === 'xmlhttprequest'
        || (string)($_POST['ajax'] ?? $_GET['ajax'] ?? '') === '1';
}

function send_json_response(array $payload, int $statusCode = 200): void
{
    http_response_code($statusCode);
    header('Content-Type: application/json; charset=UTF-8');
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function session_timing_payload(): array
{
    $lastActivity = session_last_user_activity_at();
    return [
        'authenticated' => authenticated_session_exists(),
        'last_activity_at' => $lastActivity,
        'warning_at' => $lastActivity > 0 ? $lastActivity + session_idle_timeout_seconds() : 0,
        'expires_at' => $lastActivity > 0 ? $lastActivity + session_hard_timeout_seconds() : 0,
        'idle_timeout_seconds' => session_idle_timeout_seconds(),
        'warning_duration_seconds' => session_warning_duration_seconds(),
        'server_time' => time(),
    ];
}
