<?php
/**
 * lib/auth.php
 *
 * Authentication and authorisation functions.
 * Requires config/database.php to be included before use.
 */

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

// ---------------------------------------------------------------------------
// Session helpers
// ---------------------------------------------------------------------------

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

function getCurrentUserId(): ?int
{
    return isset($_SESSION['user_id']) ? (int) $_SESSION['user_id'] : null;
}

function getCurrentUser(): ?array
{
    if (!isLoggedIn()) {
        return null;
    }
    return [
        'id'       => (int) $_SESSION['user_id'],
        'fullname' => $_SESSION['user_name']  ?? '',
        'email'    => $_SESSION['user_email'] ?? '',
    ];
}

function requireLogin(): void
{
    if (!isLoggedIn()) {
        $current  = $_SERVER['REQUEST_URI'] ?? '';
        $redirect = $current !== '' ? '?redirect=' . urlencode($current) : '';
        header('Location: /login/login.php' . $redirect);
        exit;
    }
}

function hasPermission(string $permission): bool
{
    // Stub — extend with role checks when roles are introduced
    return isLoggedIn();
}

// ---------------------------------------------------------------------------
// Login / Logout
// ---------------------------------------------------------------------------

/**
 * Attempt login with email + plain-text password.
 * Returns user row array on success, null on failure.
 */
function loginUser(string $email, string $password): ?array
{
    $pdo  = getDBConnection();
    $stmt = $pdo->prepare(
        'SELECT id, fullname, email, password FROM users WHERE email = ? AND active = 1 LIMIT 1'
    );
    $stmt->execute([strtolower(trim($email))]);
    $user = $stmt->fetch();

    if (!$user || !password_verify($password, $user['password'])) {
        return null;
    }

    // Rehash on cost/algorithm upgrade
    if (password_needs_rehash($user['password'], PASSWORD_DEFAULT)) {
        $pdo->prepare('UPDATE users SET password = ? WHERE id = ?')
            ->execute([password_hash($password, PASSWORD_DEFAULT), $user['id']]);
    }

    session_regenerate_id(true);
    $_SESSION['user_id']    = $user['id'];
    $_SESSION['user_name']  = $user['fullname'];
    $_SESSION['user_email'] = $user['email'];

    return $user;
}

/**
 * Destroy session completely and clear the session cookie.
 */
function logoutUser(): void
{
    $_SESSION = [];
    if (ini_get('session.use_cookies')) {
        $p = session_get_cookie_params();
        setcookie(
            session_name(), '', time() - 42000,
            $p['path'], $p['domain'], $p['secure'], $p['httponly']
        );
    }
    session_destroy();
}

// ---------------------------------------------------------------------------
// Registration
// ---------------------------------------------------------------------------

/**
 * Register a new user.
 * Returns ['success' => true, 'user_id' => int]
 *      or ['success' => false, 'error' => string]
 */
function registerUser(array $data): array
{
    $pdo   = getDBConnection();
    $email = strtolower(trim($data['email'] ?? ''));

    // Duplicate email check
    $stmt = $pdo->prepare('SELECT id FROM users WHERE email = ? LIMIT 1');
    $stmt->execute([$email]);
    if ($stmt->fetch()) {
        return ['success' => false, 'error' => 'An account with that email already exists.'];
    }

    $stmt = $pdo->prepare('
        INSERT INTO users
            (fullname, email, password, company, mobilephone, industry, role, city, state, postcode, country, active, created_at)
        VALUES
            (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, NOW())
    ');
    $stmt->execute([
        trim($data['fullname']    ?? ''),
        $email,
        password_hash($data['password'], PASSWORD_DEFAULT),
        trim($data['company']     ?? ''),
        trim($data['mobilephone'] ?? ''),
        $data['industry'] ?? '',
        $data['role']     ?? '',
        trim($data['city']     ?? ''),
        $data['state']    ?? '',
        trim($data['postcode'] ?? ''),
        $data['country']  ?? 'Australia',
    ]);

    return ['success' => true, 'user_id' => (int) $pdo->lastInsertId()];
}

// ---------------------------------------------------------------------------
// Password reset
// ---------------------------------------------------------------------------

/**
 * Create a password-reset token for $email (1-hour expiry).
 * Returns the raw token string, or null if the email doesn't exist.
 */
function createPasswordResetToken(string $email): ?string
{
    $pdo   = getDBConnection();
    $email = strtolower(trim($email));

    $stmt = $pdo->prepare('SELECT id FROM users WHERE email = ? AND active = 1 LIMIT 1');
    $stmt->execute([$email]);
    if (!$stmt->fetch()) {
        return null;
    }

    // Remove any previous tokens for this email
    $pdo->prepare('DELETE FROM password_resets WHERE email = ?')->execute([$email]);

    $token = bin2hex(random_bytes(32));
    $pdo->prepare(
        'INSERT INTO password_resets (email, token, created_at, expires_at)
         VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 1 HOUR))'
    )->execute([$email, $token]);

    return $token;
}

/**
 * Validate a reset token. Returns the associated email on success, null if invalid/expired.
 */
function validatePasswordResetToken(string $token): ?string
{
    $pdo  = getDBConnection();
    $stmt = $pdo->prepare(
        'SELECT email FROM password_resets WHERE token = ? AND expires_at > NOW() LIMIT 1'
    );
    $stmt->execute([$token]);
    $row = $stmt->fetch();
    return $row ? $row['email'] : null;
}

/**
 * Update the user's password and delete the reset token.
 */
function resetPassword(string $token, string $newPassword): bool
{
    $pdo   = getDBConnection();
    $email = validatePasswordResetToken($token);

    if (!$email) {
        return false;
    }

    $pdo->prepare('UPDATE users SET password = ? WHERE email = ?')
        ->execute([password_hash($newPassword, PASSWORD_DEFAULT), $email]);

    $pdo->prepare('DELETE FROM password_resets WHERE email = ?')->execute([$email]);

    return true;
}

/**
 * Change password for currently logged-in user after verifying old password.
 * Returns true on success, false if old password is wrong.
 */
function changePassword(int $userId, string $oldPassword, string $newPassword): bool
{
    $pdo  = getDBConnection();
    $stmt = $pdo->prepare('SELECT password FROM users WHERE id = ? LIMIT 1');
    $stmt->execute([$userId]);
    $user = $stmt->fetch();

    if (!$user || !password_verify($oldPassword, $user['password'])) {
        return false;
    }

    $pdo->prepare('UPDATE users SET password = ? WHERE id = ?')
        ->execute([password_hash($newPassword, PASSWORD_DEFAULT), $userId]);

    return true;
}
