<?php

declare(strict_types=1);

namespace App\Core;

final class Auth
{
    public static function start(): void
    {
        if (session_status() === PHP_SESSION_NONE) {
            session_name(App::config('security')['session_name']);
            session_start([
                'cookie_httponly' => true,
                'cookie_samesite' => 'Lax',
            ]);
        }
    }

    /** @return array<string, mixed>|null */
    public static function user(): ?array
    {
        self::start();
        if (!isset($_SESSION['user_id'])) {
            return null;
        }
        return Database::selectOne(
            'SELECT u.id, u.name, u.email, r.name AS role
             FROM users u JOIN roles r ON r.id = u.role_id
             WHERE u.id = ? AND u.active = 1',
            [$_SESSION['user_id']],
        );
    }

    public static function attempt(string $email, string $password): bool
    {
        $user = Database::selectOne('SELECT * FROM users WHERE email = ? AND active = 1', [$email]);
        if ($user === null || !password_verify($password, $user['password_hash'])) {
            return false;
        }
        self::start();
        session_regenerate_id(true);
        $_SESSION['user_id'] = (int) $user['id'];
        Audit::log('login', 'users', (int) $user['id']);
        return true;
    }

    public static function logout(): void
    {
        self::start();
        $_SESSION = [];
        session_destroy();
    }

    /** Redirects to the login page when unauthenticated. */
    public static function requireAdmin(): array
    {
        $user = self::user();
        if ($user === null) {
            Response::redirect('/admin/login');
        }
        return $user;
    }

    // --- CSRF -------------------------------------------------------------

    public static function csrfToken(): string
    {
        self::start();
        if (empty($_SESSION['csrf'])) {
            $_SESSION['csrf'] = bin2hex(random_bytes(32));
        }
        return $_SESSION['csrf'];
    }

    public static function verifyCsrf(Request $request): void
    {
        self::start();
        $token = $request->str('_csrf');
        if ($token === '' || !hash_equals($_SESSION['csrf'] ?? '', $token)) {
            Response::error('Invalid CSRF token', 419);
        }
    }
}
