<?php

declare(strict_types=1);

/**
 * Authentication Helpers
 *
 * Provides functions for managing user authentication state,
 * role-based access control, and session management for
 * the Gmind Institute application.
 */

/**
 * Check if a user is currently logged in.
 *
 * @return bool True if a user session exists, false otherwise
 */
function isLoggedIn(): bool
{
    return isset($_SESSION['user_id']) && !empty($_SESSION['user_id']);
}

/**
 * Check if the currently logged-in user has the admin role.
 *
 * @return bool True if the user is an admin, false otherwise
 */
function isAdmin(): bool
{
    return isset($_SESSION['user_role']) && $_SESSION['user_role'] === 'admin';
}

/**
 * Check if the currently logged-in user has the student role.
 *
 * @return bool True if the user is a student, false otherwise
 */
function isStudent(): bool
{
    return isset($_SESSION['user_role']) && $_SESSION['user_role'] === 'student';
}

/**
 * Get the currently authenticated user's data from the session.
 *
 * Returns an associative array of user session data, or null
 * if no user is logged in.
 *
 * @return array<string, mixed>|null The user data array or null
 */
function getCurrentUser(): ?array
{
    if (!isLoggedIn()) {
        return null;
    }

    return [
        'id'         => $_SESSION['user_id'] ?? null,
        'name'       => $_SESSION['user_name'] ?? '',
        'email'      => $_SESSION['user_email'] ?? '',
        'role'       => $_SESSION['user_role'] ?? '',
        'avatar'     => $_SESSION['user_avatar'] ?? null,
        'logged_in'  => $_SESSION['login_time'] ?? null,
    ];
}

/**
 * Require that a user is logged in.
 *
 * If the user is not authenticated, sets a flash message
 * and redirects to the login page. Terminates execution on redirect.
 *
 * @return void
 */
function requireLogin(): void
{
    if (!isLoggedIn()) {
        flash('error', 'Please log in to access this page.');
        redirect('/login');
    }
}

/**
 * Require that the logged-in user has the admin role.
 *
 * If the user is not an admin, sets a flash message
 * and redirects to the home page. Terminates execution on redirect.
 *
 * @return void
 */
function requireAdmin(): void
{
    if (!isAdmin()) {
        flash('error', 'You do not have permission to access this page.');
        redirect('/');
    }
}

/**
 * Log in a user by setting session variables.
 *
 * Accepts a user data array (typically from a database query)
 * and populates the session with essential user information.
 * Regenerates the session ID to prevent session fixation attacks.
 *
 * @param array<string, mixed> $user User data containing at minimum: id, name, email, role
 * @return void
 */
function login(array $user): void
{
    // Regenerate session ID to prevent session fixation
    session_regenerate_id(true);

    $_SESSION['user_id']      = $user['id'];
    $_SESSION['user_name']    = $user['name'] ?? '';
    $_SESSION['user_email']   = $user['email'] ?? '';
    $_SESSION['user_role']    = $user['role'] ?? 'student';
    $_SESSION['user_avatar']  = $user['avatar'] ?? null;
    $_SESSION['login_time']   = time();
}

/**
 * Log out the current user.
 *
 * Destroys the session completely and redirects to the home page.
 * Clears all session data, the session cookie, and the session file.
 *
 * @return never
 */
function logout(): never
{
    // Unset all session variables
    $_SESSION = [];

    // Delete the session cookie if it exists
    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();

    redirect('/');
}
