<?php

class Auth
{
    public static function attempt(string $username, string $password): bool
    {
        $db = Database::getConnection();
        $stmt = $db->prepare(
            "SELECT u.*, r.role_name FROM users u
             JOIN roles r ON r.id = u.role_id
             WHERE u.username = :username AND u.is_active = 1 LIMIT 1"
        );
        $stmt->execute(['username' => $username]);
        $user = $stmt->fetch();

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

        // Regenerate session id on login to prevent session fixation
        session_regenerate_id(true);

        $_SESSION['user_id']    = $user['id'];
        $_SESSION['full_name']  = $user['full_name'];
        $_SESSION['username']   = $user['username'];
        $_SESSION['role_id']    = $user['role_id'];
        $_SESSION['role_name']  = $user['role_name'];

        // Update last login + audit log
        $db->prepare("UPDATE users SET last_login = NOW() WHERE id = :id")
            ->execute(['id' => $user['id']]);

        AuditLogger::log($user['id'], 'LOGIN', 'auth', 'User logged in');

        return true;
    }

    public static function check(): bool
    {
        return isset($_SESSION['user_id']);
    }

    public static function id(): ?int
    {
        return $_SESSION['user_id'] ?? null;
    }

    public static function user(): array
    {
        return [
            'id'        => $_SESSION['user_id'] ?? null,
            'full_name' => $_SESSION['full_name'] ?? '',
            'username'  => $_SESSION['username'] ?? '',
            'role_id'   => $_SESSION['role_id'] ?? null,
            'role_name' => $_SESSION['role_name'] ?? '',
        ];
    }

    public static function logout(): void
    {
        if (self::check()) {
            AuditLogger::log(self::id(), 'LOGOUT', 'auth', 'User logged out');
        }
        $_SESSION = [];
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
        }
        session_destroy();
    }

    public static function requireLogin(): void
    {
        if (!self::check()) {
            header('Location: ' . Router::url('login'));
            exit;
        }
    }

    // RBAC check: does current user's role have permission for a module/action?
    public static function can(string $moduleKey, string $action = 'view'): bool
    {
        if (!self::check()) {
            return false;
        }
        static $cache = [];
        $roleId = $_SESSION['role_id'];
        $cacheKey = $roleId . ':' . $moduleKey;

        if (!isset($cache[$cacheKey])) {
            $db = Database::getConnection();
            $stmt = $db->prepare(
                "SELECT rp.can_view, rp.can_add, rp.can_edit, rp.can_delete
                 FROM role_permissions rp
                 JOIN permissions p ON p.id = rp.permission_id
                 WHERE rp.role_id = :role_id AND p.module_key = :module_key LIMIT 1"
            );
            $stmt->execute(['role_id' => $roleId, 'module_key' => $moduleKey]);
            $cache[$cacheKey] = $stmt->fetch() ?: null;
        }

        $row = $cache[$cacheKey];
        if (!$row) {
            return false;
        }

        return match ($action) {
            'view'   => (bool) $row['can_view'],
            'add'    => (bool) $row['can_add'],
            'edit'   => (bool) $row['can_edit'],
            'delete' => (bool) $row['can_delete'],
            default  => false,
        };
    }

    public static function requirePermission(string $moduleKey, string $action = 'view'): void
    {
        self::requireLogin();
        if (!self::can($moduleKey, $action)) {
            http_response_code(403);
            require APP_PATH . '/views/errors/403.php';
            exit;
        }
    }
}
