<?php
/**
 * Class for managing user sessions securely
 * 
 * Features:
 * - 30-minute inactivity timeout
 * - Session regeneration every 30 minutes
 * - Secure cookie settings
 * - Singleton pattern
 */
class SessionManager {
    private static $instance = null;
    private $sessionStarted = false;
    private $sessionActive = false;

    // 30 minutes inactivity timeout
    private const INACTIVITY_TIMEOUT = 1800;

    /**
     * Private constructor to prevent direct creation of object
     */
    private function __construct() {
        // Configure stronger session security
        ini_set('session.use_strict_mode', 1);
        ini_set('session.use_only_cookies', 1);
        ini_set('session.cookie_httponly', 1);

        // Set the session cookie parameters
        session_set_cookie_params([
            'lifetime' => 0, // Session cookie - expires when browser closes
            'path' => '/',
            'domain' => '',
            'secure' => isset($_SERVER['HTTPS']),
            'httponly' => true,
            'samesite' => 'Lax'
        ]);

        // Start the session
        if (session_status() === PHP_SESSION_NONE) {
            if (session_start()) {
                $this->sessionStarted = true;
            }
        } else {
            $this->sessionStarted = true;
        }

        // Regenerate session ID periodically to prevent fixation attacks
        if ($this->sessionStarted && isset($_SESSION['last_regeneration'])) {
            if (time() - $_SESSION['last_regeneration'] > 1800) {
                session_regenerate_id(true);
                $_SESSION['last_regeneration'] = time();
            }
        } elseif ($this->sessionStarted) {
            $_SESSION['last_regeneration'] = time();
        }

        // Check inactivity timeout
        if (isset($_SESSION['is_logged_in']) && isset($_SESSION['last_activity'])) {
            if ((time() - $_SESSION['last_activity']) > self::INACTIVITY_TIMEOUT) {
                // Session expired due to inactivity
                $this->logout();
                $this->sessionActive = false;
                return;
            }
        }

        // Update last activity time
        if (isset($_SESSION['is_logged_in'])) {
            $_SESSION['last_activity'] = time();
        }

        // Check if user is logged in
        if (isset($_SESSION['is_logged_in']) && isset($_SESSION['user_id']) && isset($_SESSION['user_email'])) {
            $this->sessionActive = true;
        }
    }

    /**
     * Get singleton instance
     *
     * @return SessionManager
     */
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Login user
     *
     * @param int $userId
     * @param string $email
     * @return bool
     */
    public function login($userId, $email) {
        if (!$this->sessionStarted) {
            return false;
        }

        $_SESSION['user_id'] = $userId;
        $_SESSION['user_email'] = $email;
        $_SESSION['is_logged_in'] = true;
        $_SESSION['login_time'] = time();
        $_SESSION['last_activity'] = time();

        // Regenerate session ID on login to prevent session fixation
        session_regenerate_id(true);
        $_SESSION['last_regeneration'] = time();

        $this->sessionActive = true;
        return true;
    }

    /**
     * Logout user
     *
     * @return bool
     */
    public function logout() {
        if (!$this->sessionStarted) {
            return false;
        }

        // Clear all session data
        $_SESSION = [];

        // Delete the session cookie
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(
                session_name(),
                '',
                time() - 42000,
                $params['path'],
                $params['domain'],
                $params['secure'],
                $params['httponly']
            );
        }

        // Destroy the session
        session_destroy();

        $this->sessionActive = false;
        $this->sessionStarted = false;

        return true;
    }

    /**
     * Check if user is logged in
     *
     * @return bool
     */
    public function isLoggedIn() {
        if (!$this->sessionStarted) {
            return false;
        }

        return isset($_SESSION['is_logged_in']) && $_SESSION['is_logged_in'] === true;
    }

    /**
     * Get user ID
     *
     * @return int|null
     */
    public function getUserId() {
        return $this->isLoggedIn() ? $_SESSION['user_id'] : null;
    }

    /**
     * Get user email
     *
     * @return string|null
     */
    public function getUserEmail() {
        return $this->isLoggedIn() ? $_SESSION['user_email'] : null;
    }

    /**
     * Get login time
     *
     * @return int|null
     */
    public function getLoginTime() {
        return $this->isLoggedIn() ? $_SESSION['login_time'] : null;
    }

    /**
     * Check if session exists and is active
     *
     * @return bool
     */
    public function isSessionActive() {
        return $this->sessionActive;
    }
}
