<?php
/* ============================================================================
   WBMCZ — Role Based Access Control

   One place decides what a staff account may see and do.

     rbac_permissions()          the master list of modules + labels
     rbac_can('manage_users')    true / false, cached for the request
     rbac_can(['a','b'])         true when the user holds ANY of them
     rbac_guard('manage_users')  stops the page with a friendly screen
     rbac_is_super()             true for the owner account (role_id empty)
                                 and for any role holding 'all'

   The sidebar uses the same functions, so a staff member only ever sees the
   menu entries for the modules they were actually given.
   ============================================================================ */

if (!function_exists('rbac_permissions')) {

/* module key => human label (this list also drives admin/roles.php) */
function rbac_permissions() {
    return [
        'manage_users'       => 'Manage Customers',
        'manage_leads'       => 'Manage Leads & Follow-up',
        'manage_sellers'     => 'Manage Sellers',
        'manage_staff_roles' => 'Manage Staff & Roles',
        'manage_services'    => 'Manage Services',
        'manage_orders'      => 'Manage Orders',
        'manage_transactions'=> 'Manage Transactions',
        'manage_tickets'     => 'Manage Support Tickets',
        'manage_settings'    => 'Manage Site Settings',
        'manage_tasks'       => 'Manage Activity & Task',
        'manage_subscriptions' => 'Manage Subscription Plans',
    ];
}

/* The raw permission array of the logged-in staff account (cached).
   Since the detailed access system arrived (includes/acl.php) this returns the
   OLD-STYLE list, worked out from the new one, so the sidebar and every page
   written before it carry on unchanged. */
function rbac_my_permissions() {
    static $cache = null;
    if ($cache !== null) return $cache;

    global $db;
    $cache = [];

    if (!function_exists('acl_effective') && @is_file(__DIR__ . '/acl.php')) {
        require_once __DIR__ . '/acl.php';
    }
    if (function_exists('acl_effective')) {
        $set = acl_effective();
        if (in_array('*', $set, true)) { return $cache = ['all']; }
        if (!empty($set)) {
            $out = [];
            foreach (acl_legacy_map() as $legacy => $mods) {
                foreach ($mods as $mk) {
                    if (acl_has_module($mk)) { $out[] = $legacy; break; }
                }
            }
            return $cache = array_values(array_unique($out));
        }
    }

    if (!isset($_SESSION['user_id']) || ($_SESSION['user_type'] ?? '') !== 'admin') { return $cache; }

    try {
        $u = $db->select("SELECT role_id FROM users WHERE id = ?", [(int)$_SESSION['user_id']]);
    } catch (\Throwable $e) { $u = []; }

    /* No role attached = the owner account, everything is open. */
    if (empty($u) || empty($u[0]['role_id'])) { return $cache = ['all']; }

    try {
        $r = $db->select("SELECT permissions FROM roles WHERE id = ?", [(int)$u[0]['role_id']]);
    } catch (\Throwable $e) { $r = []; }

    if (empty($r)) { return $cache = []; }

    $p = json_decode((string)$r[0]['permissions'], true);
    return $cache = is_array($p) ? $p : [];
}

/* Owner / full-access account? */
function rbac_is_super() {
    return in_array('all', rbac_my_permissions(), true);
}

/**
 * Can the current staff account use this module?
 * $perm may be a single key, an array of keys (ANY of them), or '' (open).
 */
function rbac_can($perm) {
    if ($perm === '' || $perm === null) return true;
    $mine = rbac_my_permissions();
    if (in_array('all', $mine, true)) return true;
    foreach ((array)$perm as $p) {
        if ($p === '' || in_array($p, $mine, true)) return true;
    }
    return false;
}

/* A friendly "no access" screen instead of a bare die() */
function rbac_deny($label = '') {
    $labels = rbac_permissions();
    $name   = '';
    foreach ((array)$label as $l) { if (isset($labels[$l])) { $name = $labels[$l]; break; } }
    if ($name === '') $name = 'this section';

    http_response_code(403);
    ?>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Access denied</title>
        <script src="https://cdn.tailwindcss.com"></script>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    </head>
    <body class="bg-slate-100 min-h-screen flex items-center justify-center p-6 font-sans">
        <div class="max-w-md w-full bg-white rounded-2xl shadow-lg border border-slate-200 p-8 text-center">
            <div class="w-16 h-16 rounded-2xl bg-rose-50 text-rose-500 flex items-center justify-center text-2xl mx-auto mb-4">
                <i class="fas fa-lock"></i>
            </div>
            <h1 class="text-xl font-extrabold text-slate-800 mb-2">You do not have access here</h1>
            <p class="text-sm text-slate-500 leading-relaxed mb-6">
                Your staff account has not been given <b><?php echo htmlspecialchars($name); ?></b>.
                Ask an administrator to add that module to your role, and it will appear in your menu.
            </p>
            <a href="index.php" class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-slate-900 text-white text-sm font-bold">
                <i class="fas fa-arrow-left"></i> Back to dashboard
            </a>
        </div>
    </body>
    </html>
    <?php
    exit;
}

/* Guard a whole page in one line */
function rbac_guard($perm) {
    if (!rbac_can($perm)) { rbac_deny($perm); }
}

/**
 * Filter a sidebar menu down to what this account may see.
 * Items carry an optional 'perm' key; groups also drop the children the
 * account cannot open, and a group left with no children disappears too.
 * A heading with nothing under it is removed as well.
 */
function rbac_filter_menu($menu) {
    if (rbac_is_super()) return $menu;

    $out = [];
    foreach ($menu as $item) {
        $type = $item['type'] ?? 'link';

        if ($type === 'heading') { $out[] = $item; continue; }

        if (!rbac_can($item['perm'] ?? '')) { continue; }

        if ($type === 'group' && !empty($item['children'])) {
            $kids = [];
            foreach ($item['children'] as $c) {
                if (rbac_can($c['perm'] ?? '')) { $kids[] = $c; }
            }
            if (empty($kids)) { continue; }
            $item['children'] = $kids;
        }
        $out[] = $item;
    }

    /* drop headings that ended up with nothing after them */
    $clean = [];
    for ($i = 0; $i < count($out); $i++) {
        if (($out[$i]['type'] ?? '') === 'heading') {
            $has = false;
            for ($j = $i + 1; $j < count($out); $j++) {
                if (($out[$j]['type'] ?? '') === 'heading') break;
                $has = true; break;
            }
            if (!$has) continue;
        }
        $clean[] = $out[$i];
    }
    return $clean;
}

} // end function_exists guard
