<?php

declare(strict_types=1);

namespace Core;

/**
 * Auth — session-based authentication and permission checks.
 */
final class Auth
{
    private static ?array $user = null;

    // ── Login / Logout ────────────────────────────────────────────────────────

    public static function login(array $user): void
    {
        session_regenerate_id(true);

        Session::set('auth_user_id',   (int) $user['id']);
        Session::set('auth_user_name', $user['name']);
        Session::set('auth_role_id',   (int) $user['role_id']);
        Session::set('auth_role',      $user['role_name']);
        Session::set('_last_regen',    time());

        self::$user = null; // clear static cache
    }

    public static function logout(): void
    {
        Session::destroy();
        self::$user = null;
    }

    public static function check(): bool
    {
        return Session::has('auth_user_id');
    }

    // ── Current User ──────────────────────────────────────────────────────────

    /** @return array<string, mixed>|null */
    public static function user(): ?array
    {
        if (!self::check()) {
            return null;
        }

        if (self::$user === null) {
            $db = Database::getInstance();
            self::$user = $db->fetchOne(
                "SELECT u.*, r.name AS role_name
                   FROM users u
                   JOIN roles r ON r.id = u.role_id
                  WHERE u.id = ? AND u.is_active = 1",
                [Session::get('auth_user_id')]
            );
        }

        return self::$user;
    }

    public static function id(): ?int
    {
        return Session::get('auth_user_id');
    }

    public static function role(): ?string
    {
        return Session::get('auth_role');
    }

    public static function isSuperAdmin(): bool
    {
        return self::role() === 'super_admin';
    }

    // ── Permissions ───────────────────────────────────────────────────────────

    public static function can(string $permission): bool
    {
        if (!self::check()) {
            return false;
        }

        // Super admin bypasses all permission checks
        if (self::isSuperAdmin()) {
            return true;
        }

        $db     = Database::getInstance();
        $roleId = Session::get('auth_role_id');

        $result = $db->fetchValue(
            "SELECT COUNT(*) FROM role_permissions rp
               JOIN permissions p ON p.id = rp.permission_id
              WHERE rp.role_id = ? AND p.name = ?",
            [$roleId, $permission]
        );

        return (int) $result > 0;
    }

    /**
     * Abort with 403 if the current user lacks the given permission.
     */
    public static function require(string $permission): void
    {
        if (!self::can($permission)) {
            http_response_code(403);
            require VIEW_PATH . '/errors/403.php';
            exit;
        }
    }

    /**
     * Redirect to login if not authenticated.
     */
    public static function requireLogin(string $loginUrl = '/auth/login'): void
    {
        if (!self::check()) {
            Session::flash('redirect_after_login', $_SERVER['REQUEST_URI'] ?? '/');
            header('Location: ' . base_url() . $loginUrl);
            exit;
        }
    }
}
