<?php

declare(strict_types=1);

namespace FatBottom\Core;

final class Auth
{
    private ?array $cachedUser = null;
    private bool $resolved = false;

    public function __construct(private readonly Database $db)
    {
    }

    public function user(): ?array
    {
        if ($this->resolved) {
            return $this->cachedUser;
        }
        $this->resolved = true;
        $id = (int) ($_SESSION['user_id'] ?? 0);
        if ($id === 0) {
            return null;
        }

        $this->cachedUser = $this->db->fetch(
            'SELECT * FROM users WHERE id = ? AND active = 1',
            [$id]
        );
        return $this->cachedUser;
    }

    public function check(): bool
    {
        return $this->user() !== null;
    }

    public function login(array $user): void
    {
        session_regenerate_id(true);
        $_SESSION['user_id'] = (int) $user['id'];
        unset($_SESSION['pending_2fa_user_id'], $_SESSION['pending_verification_purpose']);
        $this->resolved = true;
        $this->cachedUser = $user;
    }

    public function logout(): void
    {
        unset($_SESSION['user_id'], $_SESSION['pending_2fa_user_id'], $_SESSION['pending_verification_purpose']);
        session_regenerate_id(true);
        $this->resolved = true;
        $this->cachedUser = null;
    }

    public function requireLogin(): array
    {
        $user = $this->user();
        if ($user === null) {
            Http::flash('warning', 'Please sign in to continue.');
            Http::redirect('/login');
        }
        return $user;
    }

    public function requireStaff(): array
    {
        $user = $this->requireLogin();
        if (!in_array($user['role'], ['admin', 'manager', 'staff'], true)) {
            Http::abort(403, 'You do not have access to the staff dashboard.');
        }
        return $user;
    }

    public function requireAdmin(): array
    {
        $user = $this->requireLogin();
        if ($user['role'] !== 'admin') {
            Http::abort(403, 'Administrator access is required.');
        }
        return $user;
    }
}
