<?php
/**
 * Unified Session Initialization
 * 
 * Provides consistent session setup for all endpoints
 */

// Set CORS headers first if not already set by endpoint
// Use explicit origin to comply with credentials=true (wildcard is not allowed)
if (!headers_sent()) {
    $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
    if (!empty($origin)) {
        header('Access-Control-Allow-Origin: ' . $origin);
    } else {
        // Same-origin fallback
        $scheme = $_SERVER['REQUEST_SCHEME'] ?? 'https';
        $host = $_SERVER['HTTP_HOST'] ?? '';
        if (!empty($host)) {
            header('Access-Control-Allow-Origin: ' . $scheme . '://' . $host);
        }
    }
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');
}

// Handle preflight OPTIONS request
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}

// Prevent direct access
if (!defined('TONSUI_LOADED')) {
    header('HTTP/1.0 403 Forbidden');
    echo 'Forbidden';
    exit;
}

// Set consistent session parameters (adaptive for localhost dev)
ini_set('session.cookie_httponly', 1);
ini_set('session.use_only_cookies', 1);
// Determine scheme/host
$scheme = $_SERVER['REQUEST_SCHEME'] ?? ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http');
$host = $_SERVER['HTTP_HOST'] ?? '';
$isLocal = in_array(parse_url($host, PHP_URL_HOST) ?: $host, ['localhost', '127.0.0.1'], true) || $host === 'localhost' || $host === '127.0.0.1';
$isHttps = ($scheme === 'https') || (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && $_SERVER['HTTPS'] !== 'off') || (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https');

if ($isHttps) {
    ini_set('session.cookie_secure', 1);
    ini_set('session.cookie_samesite', 'None'); // Cross-site support when HTTPS
} else {
    // On localhost over HTTP, allow non-secure cookie and Lax samesite
    if ($isLocal) {
        ini_set('session.cookie_secure', 0);
        ini_set('session.cookie_samesite', 'Lax');
    } else {
        // Non-local over HTTP is discouraged; still set secure=0 to allow sessions
        ini_set('session.cookie_secure', 0);
        ini_set('session.cookie_samesite', 'Lax');
    }
}

// Set consistent session name
session_name('TONSUI_SESSION');

// Set cookie parameters with proper SameSite and Secure flags (PHP 7.2 fallback supported)
$cookieParams = session_get_cookie_params();
// IMPORTANT: Never include port in cookie Domain. For localhost, omit domain entirely (host-only cookie).
$hostHeader = $_SERVER['HTTP_HOST'] ?? '';
$hostNoPort = preg_replace('/:\\d+$/', '', $hostHeader);
$isLocalHost = in_array($hostNoPort, ['localhost', '127.0.0.1'], true);

if (PHP_VERSION_ID >= 70300) {
    $params = [
        'lifetime' => $cookieParams['lifetime'],
        'path' => $cookieParams['path'],
        'secure' => $isHttps ? true : false,
        'httponly' => true,
        'samesite' => $isHttps ? 'None' : 'Lax'
    ];
    // Only set domain when not localhost; setting domain with a port breaks cookies.
    if (!$isLocalHost && !empty($hostNoPort)) {
        $params['domain'] = $hostNoPort;
    }
    session_set_cookie_params($params);
} else {
    // PHP < 7.3: Append samesite directive to path as a workaround
    $path = rtrim($cookieParams['path'] ?: '/', '/');
    $pathWithSameSite = $path . '; samesite=' . ($isHttps ? 'None' : 'Lax');
    session_set_cookie_params(
        $cookieParams['lifetime'],
        $pathWithSameSite,
        // Empty domain string means host-only cookie (works for localhost)
        $isLocalHost ? '' : $hostNoPort,
        $isHttps ? true : false,
        true
    );
}

// Start or resume session if not already started
if (session_status() === PHP_SESSION_NONE) {
    session_start();
    
    // Initialize session variables if not set
    if (!isset($_SESSION['created_at'])) {
        $_SESSION['created_at'] = time();
        $_SESSION['last_activity'] = time();
        $_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR'] ?? '';
        $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        // Regenerate session ID to prevent fixation
        session_regenerate_id(true);
    }
    
    // Validate session security
    $currentUserAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $currentIp = $_SERVER['REMOTE_ADDR'] ?? '';
    
    // Check for session hijacking attempts (relaxed for local development with proxies)
    $isDevelopment = in_array($_SERVER['HTTP_HOST'] ?? '', ['localhost:3000', 'localhost:9000', 'localhost:8000', '127.0.0.1:3000', '127.0.0.1:9000']);
    
    if (!$isDevelopment) {
        // Only enforce strict IP checking in production
        if (($_SESSION['ip_address'] !== $currentIp) || 
            ($_SESSION['user_agent'] !== $currentUserAgent)) {
            // Security violation detected - destroy session
            session_unset();
            session_destroy();
            session_start();
            $_SESSION = [];
            
            if (!headers_sent()) {
                header('HTTP/1.1 401 Unauthorized');
                header('Content-Type: application/json');
                echo json_encode([
                    'success' => false,
                    'error' => 'Session security violation. Please log in again.'
                ]);
            }
            exit;
        }
    }
    
    // Set session timeout (30 minutes)
    $timeout = 1800; // 30 minutes in seconds
    if ((time() - $_SESSION['last_activity']) > $timeout) {
        // Session expired
        session_unset();
        session_destroy();
        
        if (!headers_sent()) {
            header('HTTP/1.1 401 Unauthorized');
            header('Content-Type: application/json');
            echo json_encode([
                'success' => false,
                'error' => 'Session expired. Please log in again.'
            ]);
        }
        exit;
    }
    
    // Update last activity time
    $_SESSION['last_activity'] = time();
}

/**
 * Check if a user is logged in
 * 
 * @return bool True if user is logged in, false otherwise
 */
function isUserLoggedIn() {
    return isset($_SESSION['user_id']) && isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true;
}

/**
 * Check if current user is an admin
 * 
 * @return bool True if user is an admin, false otherwise
 */
function isUserAdmin() {
    return isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true;
}

/**
 * Require user to be logged in
 * 
 * @param bool $returnJson Whether to return JSON response (true) or redirect (false)
 * @return void
 */
function requireLogin($returnJson = true) {
    // Allow public endpoints (e.g., login.php) to opt-out by defining TONSUI_ALLOW_GUEST=true before including this file
    if (defined('TONSUI_ALLOW_GUEST') && TONSUI_ALLOW_GUEST === true) {
        return;
    }
    if (!isUserLoggedIn()) {
        if ($returnJson) {
            header('Content-Type: application/json');
            http_response_code(401);
            echo json_encode([
                'success' => false, 
                'error' => 'Authentication required'
            ]);
        } else {
            // Redirect to login page
            header('Location: /login');
        }
        exit;
    }
}

/**
 * Require user to be an admin
 * 
 * @param bool $returnJson Whether to return JSON response (true) or redirect (false)
 * @return void
 */
function requireAdmin($returnJson = true) {
    requireLogin($returnJson);
    
    if (!isUserAdmin()) {
        if ($returnJson) {
            header('Content-Type: application/json');
            http_response_code(403);
            echo json_encode([
                'success' => false, 
                'error' => 'Admin privileges required'
            ]);
        } else {
            // Redirect to admin login
            header('Location: /admin/login');
        }
        exit;
    }
}
