<?php
// includes/auth_utils.php
// Helper functions for secure token generation, cookie management, and persistent login validation.

// Include database connection (assumed to be in the parent directory of this file)
require_once __DIR__ . '/../config/database.php';

// --- Token Generation ---

/**
 * Generates a cryptographically secure pseudo-random string of bytes and converts it to a hex string.
 * @param int $length The number of bytes to generate (e.g., 16 bytes = 32 hex characters).
 * @return string The hex-encoded token string.
 * @throws Exception If a suitable random source cannot be found.
 */
function generate_secure_token($length = 32) {
    if ($length < 1) {
        throw new InvalidArgumentException("Token length must be positive.");
    }
    // random_bytes is preferred for cryptographic security
    return bin2hex(random_bytes($length));
}

// --- Cookie Management ---

/**
 * Helper function to set the persistent login cookie securely.
 * @param string $token The selector:validator string.
 * @param int $expiry_timestamp Unix timestamp for cookie expiration.
 */
function set_persistent_cookie($token, $expiry_timestamp) {
    setcookie(
        'persistent_login', 
        $token, 
        [
            'expires' => $expiry_timestamp,
            'path' => '/',
            'domain' => '', // Set your domain here or leave empty for current domain
            'secure' => true, // MUST be true in production (HTTPS)
            'httponly' => true, // Prevents XSS script access
            'samesite' => 'Lax' // Helps mitigate CSRF
        ]
    );
}

/**
 * Helper function to clear the persistent login cookie.
 */
function clear_persistent_cookie() {
    // Set expiry in the past to immediately delete the cookie
    // The path must match the path used when setting the cookie (usually '/')
    setcookie('persistent_login', '', time() - 3600, '/');
}

// --- Persistent Login Validation ---

/**
 * Checks for a persistent login cookie and validates it against the database.
 * If valid, it logs the user in and generates a new token/cookie to prevent replay attacks.
 * * @global PDO $pdo Database connection object.
 * @return bool True if login was successful, false otherwise.
 */
function check_persistent_login() {
    // Only proceed if the session is not active and the cookie is present.
    if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
        return true;
    }

    if (!isset($_COOKIE['persistent_login'])) {
        return false;
    }

    global $pdo;

    $cookie_token = $_COOKIE['persistent_login'];
    if (empty($cookie_token) || strpos($cookie_token, ':') === false) {
        clear_persistent_cookie();
        return false;
    }

    list($selector, $validator) = explode(':', $cookie_token, 2);
    $validator_hash = hash('sha256', $validator);

    try {
        // 1. Fetch token record from the database using the selector
        $sql = "SELECT ut.user_id, ut.validator_hash, ut.expires_at, u.username, u.full_name, u.role
                FROM user_devices ut 
                JOIN users u ON ut.user_id = u.id
                WHERE ut.selector = ? AND ut.expires_at > NOW()";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([$selector]);
        $device_record = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$device_record) {
            clear_persistent_cookie();
            return false;
        }

        // 2. Validate the token
        if (hash_equals($device_record['validator_hash'], $validator_hash)) {
            // Validation successful! Log the user in.
            $_SESSION['loggedin'] = true;
            $_SESSION['user_id'] = $device_record['user_id'];
            $_SESSION['username'] = $device_record['username'];
            $_SESSION['full_name'] = $device_record['full_name'];
            $_SESSION['user_role'] = $device_record['role'];

            // 3. Generate a new token and update the database/cookie (Prevents Replay Attack)
            $new_selector = generate_secure_token(16);
            $new_validator = generate_secure_token(32);
            $new_validator_hash = hash('sha256', $new_validator);
            $new_expiry_timestamp = strtotime($device_record['expires_at']); // Reuse existing expiry time

            // Update DB with the new selector and validator hash
            $sql_update = "UPDATE user_devices SET selector = ?, validator_hash = ? WHERE user_id = ? AND selector = ?";
            $pdo->prepare($sql_update)->execute([$new_selector, $new_validator_hash, $device_record['user_id'], $selector]);

            // Set new cookie
            set_persistent_cookie($new_selector . ':' . $new_validator, $new_expiry_timestamp);
            
            return true;
        } else {
            // Invalid validator provided (tampering likely), delete all tokens for this user.
            $sql_delete_all = "DELETE FROM user_devices WHERE user_id = ?";
            $pdo->prepare($sql_delete_all)->execute([$device_record['user_id']]);
            clear_persistent_cookie();
            return false;
        }

    } catch (PDOException $e) {
        error_log("Persistent login error: " . $e->getMessage());
        clear_persistent_cookie();
        return false;
    }
}