<?php
/**
 * @var string $assetsUrl @var string $baseUrl @var array $users
 * @var string|null $success @var string|null $error
 * @var \PpPhp\Core\Pagination $pager @var string $q @var int $total
 * @var int $showFrom @var int $showTo @var string $dbNow @var int $currentUserId
 */
// Relative time comparing DB timestamps against the DB clock ($dbNow) — correct
// even with PHP/MySQL timezone skew (both sides parsed the same way, diff cancels it).
$__nowTs = ($dbNow ?? '') !== '' ? strtotime($dbNow) : time();
$timeAgo = function (?string $ts) use ($__nowTs): string {
    if (!$ts) return '';
    $t = strtotime($ts);
    if ($t === false) return '';
    $d = max(0, $__nowTs - $t);
    if ($d < 45) return 'just now';
    if ($d < 90) return 'a minute ago';
    if ($d < 3600) return (int) floor($d / 60) . ' min ago';
    if ($d < 7200) return 'an hour ago';
    if ($d < 86400) return (int) floor($d / 3600) . ' hours ago';
    if ($d < 172800) return 'yesterday';
    if ($d < 2592000) return (int) floor($d / 86400) . ' days ago';
    if ($d < 5184000) return 'a month ago';
    if ($d < 31536000) return (int) floor($d / 2592000) . ' months ago';
    $y = (int) floor($d / 31536000);
    return $y . ' year' . ($y > 1 ? 's' : '') . ' ago';
};
$absTime = fn (?string $ts): string => $ts ? date('M j, Y · g:i A', (int) strtotime($ts)) : '';
$seenStatus = function (?string $ts) use ($__nowTs): string {
    if (!$ts) return 'never';
    $d = $__nowTs - (int) strtotime($ts);
    if ($d < 300) return 'online';
    if ($d < 86400) return 'away';
    return 'offline';
};
// Build a Manage-Users URL that keeps the current search + column filters, applying
// only the given overrides (a null/'' value drops that param; page resets on change).
$__curFilters = ['q' => $q ?? '', 'role' => $roleFilter ?? ''];
$filterUrl = function (array $ov) use ($baseUrl, $__curFilters): string {
    $p = array_filter(array_merge($__curFilters, $ov), static fn ($v) => $v !== null && $v !== '');
    return rtrim((string) $baseUrl, '/') . '/users' . ($p ? ('?' . http_build_query($p)) : '');
};
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>User Management</title>
    <link href="<?= $assetsUrl ?>/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <link href="<?= $assetsUrl ?>/icons/bootstrap-icons.css" rel="stylesheet">
    <?php include constant('BASE_PATH') . '/core/views/theme-head.php'; ?>
    <!-- SweetAlert2 -->
    <link href="<?= $assetsUrl ?>/sweetalert2/sweetalert2.min.css" rel="stylesheet">
    <script src="<?= $assetsUrl ?>/sweetalert2/sweetalert2.min.js"></script>

    <style>
        /* Built on --pp-* tokens so the queue follows whichever theme is active. */
        .trial-queue { border: 1px solid var(--pp-border, #e2e8f0); border-radius: 14px;
            background: var(--pp-surface, #fff); overflow: hidden; }
        .trial-queue-head { padding: 14px 16px; border-bottom: 1px solid var(--pp-border, #eef1f6);
            background: var(--pp-surface-soft, #f8fafc); }
        .trial-queue-head h5 { color: var(--pp-text); font-size: 15px; display: flex; align-items: center; gap: 8px; }
        .trial-queue-head h5 i { color: var(--pp-accent, #4f46e5); }
        .trial-count { background: var(--pp-accent, #4f46e5); color: #fff; font-size: 11px; }
        .trial-sub { display: block; margin-top: 3px; font-size: 12px; color: var(--pp-text-muted, #64748b); }

        .trial-card { display: flex; gap: 16px; align-items: flex-start; justify-content: space-between;
            padding: 15px 16px; border-bottom: 1px solid var(--pp-border, #f1f5f9); flex-wrap: wrap; }
        .trial-card:last-child { border-bottom: 0; }
        .trial-card.is-highlight { background: color-mix(in srgb, var(--pp-accent, #4f46e5) 9%, var(--pp-surface, #fff));
            box-shadow: inset 3px 0 0 var(--pp-accent, #4f46e5); }
        .trial-card-main { min-width: 0; flex: 1 1 320px; }
        .trial-who strong { display: block; font-size: 14px; color: var(--pp-text); }
        .trial-who a { font-size: 12.5px; color: var(--pp-accent, #4f46e5); text-decoration: none; }
        .trial-who a:hover { text-decoration: underline; }
        .trial-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 7px 0;
            font-size: 11.5px; color: var(--pp-text-muted, #64748b); }
        .trial-use-case { margin: 0; padding: 9px 12px; font-size: 12.5px; line-height: 1.55;
            color: var(--pp-text); background: var(--pp-surface-soft, #f8fafc);
            border-left: 3px solid var(--pp-accent, #4f46e5); border-radius: 0 8px 8px 0;
            overflow-wrap: anywhere; }
        .trial-actions { display: flex; gap: 8px; flex: 0 0 auto; }

        @media (max-width: 575.98px) {
            .trial-card { flex-direction: column; }
            .trial-actions { width: 100%; }
            .trial-actions > * { flex: 1; }
            .trial-actions .btn { width: 100%; }
        }

        /* ── themed Manage Users shell (built on --pp-* tokens for light+dark) ── */
        body { background: var(--pp-app-bg, #f5f6fa) !important; color: var(--pp-text, #172033); }
        .uu-hero h2 { font-size: 1.5rem; font-weight: 800; letter-spacing: -.02em; margin: 0; color: var(--pp-text); }
        .uu-hero p { color: var(--pp-text-muted, #64748b); font-size: .9rem; margin: .28rem 0 0; }
        .uu-search { position: relative; max-width: 420px; }
        .uu-search i { position: absolute; left: .8rem; top: 50%; transform: translateY(-50%); color: var(--pp-text-muted, #94a3b8); font-size: .9rem; }
        .uu-search input { width: 100%; height: 40px; border: 1px solid var(--pp-border, #e6e9f0); border-radius: 10px; padding: 0 .8rem 0 2.2rem; background: var(--pp-input-bg, #fff); color: var(--pp-text); font: inherit; font-size: .88rem; }
        .uu-search input:focus { outline: none; border-color: var(--pp-accent, #2563eb); box-shadow: 0 0 0 3px var(--pp-accent-soft, #eaf2ff); }

        .uu-card { background: var(--pp-surface, #fff); border: 1px solid var(--pp-border, #e6e9f0); border-radius: 14px; overflow: hidden; }
        table.uu-table { width: 100%; border-collapse: collapse; font-size: .88rem; margin: 0; }
        .uu-table th { text-align: left; font-size: .66rem; text-transform: uppercase; letter-spacing: .05em; color: var(--pp-text-muted, #64748b); font-weight: 800; padding: .78rem 1.1rem; background: var(--pp-surface-soft, #f8fafc); border-bottom: 1px solid var(--pp-border, #e6e9f0); white-space: nowrap; }
        .uu-table td { padding: .72rem 1.1rem; border-bottom: 1px solid var(--pp-border, #eef1f6); vertical-align: middle; color: var(--pp-text); }
        .uu-table tbody tr:last-child td { border-bottom: 0; }
        .uu-table tbody tr:hover td { background: color-mix(in srgb, var(--pp-accent, #2563eb) 5%, var(--pp-surface, #fff)); }
        .uu-uname { font-weight: 650; }
        .uu-email { color: var(--pp-text-muted, #64748b); }

        .uu-role { display: inline-block; font-size: .64rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; padding: 3px 10px; border-radius: 999px; border: 1px solid transparent; }
        .uu-role.owner { background: color-mix(in srgb, #7c3aed 22%, var(--pp-surface, #fff)); color: color-mix(in srgb, #7c3aed 60%, var(--pp-text, #172033)); border-color: color-mix(in srgb, #7c3aed 42%, transparent); }
        .uu-role.superadmin { background: color-mix(in srgb, #e11d48 22%, var(--pp-surface, #fff)); color: color-mix(in srgb, #e11d48 60%, var(--pp-text, #172033)); border-color: color-mix(in srgb, #e11d48 42%, transparent); }
        .uu-role.developer { background: color-mix(in srgb, #2563eb 22%, var(--pp-surface, #fff)); color: color-mix(in srgb, #2563eb 60%, var(--pp-text, #172033)); border-color: color-mix(in srgb, #2563eb 42%, transparent); }
        .uu-role.user { background: var(--pp-surface-muted, #f1f5f9); color: var(--pp-text-muted, #64748b); border-color: var(--pp-border, #e6e9f0); }


        .uu-acts { display: flex; gap: .4rem; justify-content: flex-end; }
        .uu-acts form { display: inline; margin: 0; }
        .uu-act { display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--pp-border, #e6e9f0); background: var(--pp-surface, #fff); cursor: pointer; text-decoration: none; font-size: .9rem; transition: background .12s, color .12s, border-color .12s; }
        .uu-act.edit { color: var(--pp-accent, #2563eb); }
        .uu-act.edit:hover { background: var(--pp-accent, #2563eb); color: var(--pp-accent-contrast, #fff); border-color: var(--pp-accent, #2563eb); }
        .uu-act.del { color: #dc2626; }
        .uu-act.del:hover { background: #dc2626; color: #fff; border-color: #dc2626; }

        /* stacked cards on phones */
        @media (max-width: 640px) {
            .uu-table thead { display: none; }
            .uu-table, .uu-table tbody, .uu-table tr, .uu-table td { display: block; width: 100%; }
            .uu-table tr { border-bottom: 6px solid var(--pp-app-bg, #f5f6fa); padding: .35rem 0; }
            .uu-table td { border: 0; padding: .3rem 1.1rem; }
            .uu-table tbody tr:hover td { background: transparent; }
            .uu-table td::before { content: attr(data-label); display: block; font-size: .58rem; text-transform: uppercase; letter-spacing: .05em; color: var(--pp-text-muted, #64748b); font-weight: 800; margin-bottom: 2px; }
            .uu-table td.uu-actcell::before { display: none; }
            .uu-acts { justify-content: flex-start; margin-top: .3rem; }
        }

        /* count chip in the title */
        .uu-count { display: inline-flex; align-items: center; justify-content: center; min-width: 1.7rem; height: 1.45rem; padding: 0 .5rem; margin-left: .45rem; border-radius: 999px; background: var(--pp-accent-soft, #eef2ff); color: var(--pp-accent, #4f46e5); font-size: .8rem; font-weight: 800; vertical-align: middle; }
        /* clear-search affordance */
        .uu-search input { padding-right: 2.4rem; }
        .uu-search-clear { position: absolute; right: .45rem; top: 50%; transform: translateY(-50%); width: 28px; height: 28px; display: grid; place-items: center; border-radius: 7px; color: var(--pp-text-muted, #94a3b8); text-decoration: none; }
        .uu-search-clear:hover { color: var(--pp-text, #172033); background: var(--pp-surface-muted, #f1f5f9); }
        /* username avatar */
        .uu-uname { white-space: nowrap; }
        .uu-uname-t { font-weight: 700; vertical-align: middle; }
        .uu-av { display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 9px; margin-right: .6rem; font-size: .72rem; font-weight: 800; color: #fff; background: linear-gradient(135deg, var(--pp-accent, #6366f1), #8b5cf6); vertical-align: middle; }
        .uu-av-owner { background: linear-gradient(135deg, #7c3aed, #a855f7); }
        .uu-av-superadmin { background: linear-gradient(135deg, #e11d48, #f43f5e); }
        .uu-av-developer { background: linear-gradient(135deg, #2563eb, #3b82f6); }
        .uu-av-user { background: linear-gradient(135deg, #0d9488, #14b8a6); }
        /* empty state */
        .uu-empty { display: flex; align-items: center; gap: .9rem; justify-content: center; padding: 2.4rem 1rem; color: var(--pp-text-muted, #64748b); }
        .uu-empty > i { font-size: 1.7rem; color: var(--pp-text-muted, #94a3b8); }
        .uu-empty strong { display: block; color: var(--pp-text, #172033); }
        .uu-empty span { font-size: .85rem; }
        /* footer: "showing" + pager */
        .uu-foot { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; padding: .85rem 1.1rem; border-top: 1px solid var(--pp-border, #e6e9f0); }
        .uu-showing { font-size: .82rem; color: var(--pp-text-muted, #64748b); }
        .uu-showing strong { color: var(--pp-text, #172033); font-variant-numeric: tabular-nums; }
        /* themed pager (built on Bootstrap .pagination markup) */
        .pp-pager { display: flex; margin: 0; padding: 0; gap: .25rem; list-style: none; }
        .pp-pager li a, .pp-pager li span { display: inline-flex; align-items: center; justify-content: center; min-width: 34px; height: 34px; padding: 0 .55rem; border: 1px solid var(--pp-border, #e6e9f0); border-radius: 9px; color: var(--pp-text, #334155); text-decoration: none; font-size: .84rem; font-weight: 600; background: var(--pp-surface, #fff); transition: border-color .15s ease, background .15s ease, color .15s ease; }
        .pp-pager li a:hover { border-color: var(--pp-accent, #6366f1); color: var(--pp-accent, #4f46e5); }
        .pp-pager li.active a { background: var(--pp-accent, #4f46e5); border-color: var(--pp-accent, #4f46e5); color: #fff; }
        .pp-pager li.disabled a, .pp-pager li.disabled span { opacity: .45; pointer-events: none; }

        /* Created cell — date over time */
        .uu-when { display: block; font-weight: 600; }
        .uu-when-t { display: block; font-size: .72rem; color: var(--pp-text-muted, #94a3b8); font-variant-numeric: tabular-nums; }
        /* Last seen — status dot + relative text */
        .uu-seen { display: inline-flex; align-items: center; gap: .45rem; font-size: .84rem; white-space: nowrap; }
        .uu-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--pp-text-muted, #94a3b8); }
        .uu-seen-online { color: #059669; font-weight: 700; }
        .uu-seen-online .uu-dot { background: #10b981; box-shadow: 0 0 0 3px color-mix(in srgb, #10b981 24%, transparent); animation: uuPulse 2s ease-in-out infinite; }
        .uu-seen-away .uu-dot { background: #f59e0b; }
        .uu-seen-offline .uu-dot { background: var(--pp-border-strong, #cbd5e1); }
        .uu-seen-never { color: var(--pp-text-muted, #94a3b8); }
        .uu-seen-never .uu-dot { background: transparent; border: 1.5px dashed var(--pp-border-strong, #cbd5e1); }
        @keyframes uuPulse { 0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, #10b981 24%, transparent); } 50% { box-shadow: 0 0 0 5px color-mix(in srgb, #10b981 6%, transparent); } }
        @media (prefers-reduced-motion: reduce) { .uu-seen-online .uu-dot { animation: none; } }
        /* actions header + self/locked affordances */
        .uu-th-act { text-align: right; }
        .uu-selftag { display: inline-flex; align-items: center; padding: .18rem .55rem; border-radius: 999px; font-size: .66rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--pp-accent, #4f46e5); background: var(--pp-accent-soft, #eef2ff); }
        .uu-act.is-locked { color: var(--pp-text-muted, #94a3b8); cursor: default; }
        .uu-act.is-locked:hover { background: transparent; border-color: transparent; color: var(--pp-text-muted, #94a3b8); }

        /* column-header filters (Role) */
        .uu-th-wrap { display: inline-flex; align-items: center; gap: .3rem; }
        .uu-hfilter { position: relative; display: inline-flex; }
        .uu-hfilter-btn { border: 0; background: transparent; padding: 2px 4px; border-radius: 6px; color: var(--pp-text-muted, #94a3b8); cursor: pointer; font-size: .78rem; line-height: 1; transition: color .15s ease, background .15s ease; }
        .uu-hfilter-btn:hover { color: var(--pp-accent, #4f46e5); background: var(--pp-surface-muted, #f1f5f9); }
        .uu-hfilter.is-active .uu-hfilter-btn { color: var(--pp-accent, #4f46e5); }
        .uu-hfilter-menu { position: absolute; top: calc(100% + 6px); left: 0; z-index: 30; min-width: 190px; padding: 5px; border: 1px solid var(--pp-border, #e6e9f0); border-radius: 12px; background: var(--pp-surface-raised, var(--pp-surface, #fff)); box-shadow: 0 16px 40px var(--pp-shadow-color, rgba(15,23,42,.18)); }
        .uu-hfilter-h { padding: .35rem .55rem; font-size: .62rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--pp-text-muted, #94a3b8); }
        .uu-hfilter-opt { display: flex; align-items: center; justify-content: space-between; gap: .6rem; padding: .45rem .55rem; border-radius: 8px; color: var(--pp-text, #334155); text-decoration: none; font-size: .8rem; font-weight: 600; text-transform: none; letter-spacing: 0; }
        .uu-hfilter-opt:hover { background: var(--pp-surface-muted, #f1f5f9); color: var(--pp-text, #172033); }
        .uu-hfilter-opt .bi-check2 { opacity: 0; color: var(--pp-accent, #4f46e5); }
        .uu-hfilter-opt.is-on { background: var(--pp-accent-soft, #eef2ff); }
        .uu-hfilter-opt.is-on .bi-check2 { opacity: 1; }

        /* stat bar — analytics tiles that double as quick filters */
        .uu-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: .6rem; margin: 0 0 1rem; }
        .uu-stat { position: relative; display: flex; align-items: center; gap: .6rem; padding: .6rem .7rem; border: 1px solid var(--pp-border, #e6e9f0); border-radius: 12px; background: var(--pp-surface, #fff); color: var(--pp-text, #172033); text-decoration: none; transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease; }
        .uu-stat.is-link { cursor: pointer; }
        .uu-stat.is-link:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--sc, #6366f1) 55%, var(--pp-border)); box-shadow: 0 8px 20px color-mix(in srgb, var(--sc, #6366f1) 16%, transparent); }
        .uu-stat.is-active { border-color: var(--sc, #6366f1); box-shadow: inset 0 0 0 1px var(--sc, #6366f1), 0 6px 18px color-mix(in srgb, var(--sc, #6366f1) 18%, transparent); }
        .uu-stat-ic { flex: 0 0 auto; width: 34px; height: 34px; display: grid; place-items: center; border-radius: 9px; font-size: .95rem; color: var(--sc, #6366f1); background: color-mix(in srgb, var(--sc, #6366f1) 15%, transparent); }
        .uu-stat-body { min-width: 0; display: flex; flex-direction: column; }
        .uu-stat-n { font-size: 1.2rem; font-weight: 850; line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
        .uu-stat-l { font-size: .68rem; font-weight: 600; color: var(--pp-text-muted, #64748b); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .uu-stat-total { --sc: #6366f1; }
        .uu-stat-online { --sc: #10b981; }
        .uu-stat-online .uu-stat-ic i { animation: uuPulse2 2s ease-in-out infinite; border-radius: 50%; }
        @keyframes uuPulse2 { 0%,100% { opacity: 1; } 50% { opacity: .45; } }
        .uu-stat-owner { --sc: #a855f7; }
        .uu-stat-superadmin { --sc: #f43f5e; }
        .uu-stat-developer { --sc: #3b82f6; }
        .uu-stat-user { --sc: #14b8a6; }
        .uu-stat-new { --sc: #06b6d4; }
        .uu-stat-pending { --sc: #f59e0b; }
        @media (prefers-reduced-motion: reduce) { .uu-stat.is-link:hover { transform: none; } .uu-stat-online .uu-stat-ic i { animation: none; } }
    </style>
</head>

<body class="bg-light">
    <div class="container mt-4">
        <div class="uu-hero d-flex justify-content-between align-items-start mb-3 flex-wrap gap-3">
            <div>
                <h2>Manage Users <span class="uu-count"><?= (int) $stats['total'] ?></span></h2>
                <p>Create accounts, set roles, review trial requests.</p>
            </div>
            <div class="d-flex gap-2 flex-wrap align-items-center">
                <button type="button" class="btn btn-outline-secondary" data-guide-open="usersGuide" data-tip="Open the Manage Users guide"><i class="bi bi-question-circle"></i> Guide</button>
                <?php $__exp = array_filter(['q' => $q, 'role' => $roleFilter], static fn ($v) => $v !== ''); ?>
                <a href="<?= $baseUrl ?>/users/export<?= $__exp ? '?' . htmlspecialchars(http_build_query($__exp)) : '' ?>" class="btn btn-outline-secondary" data-tip="Download the list as CSV — respects the current search &amp; filters"><i class="bi bi-download"></i> Export<?= $__exp ? ' filtered' : ' CSV' ?></a>
                <a href="<?= $baseUrl ?>/projects" class="btn btn-outline-secondary" data-tip="Return to the Projects hub"><i class="bi bi-house"></i> Back to Projects</a>
                <a href="<?= $baseUrl ?>/users/create" class="btn btn-primary" data-tip="Create a brand-new user account"><i class="bi bi-plus-lg"></i> Add User</a>
                <?php include constant('BASE_PATH') . '/core/views/theme-toggle.php'; ?>
            </div>
        </div>

        <?php
            $noFilter = ($roleFilter === '' && ($q ?? '') === '');
            $stTile = function (string $mod, string $icon, int $n, string $label, ?string $href = null, bool $active = false) {
                $tag = $href !== null ? 'a' : 'div';
                $attr = $href !== null ? ' href="' . htmlspecialchars($href) . '"' : '';
                echo "<$tag class=\"uu-stat uu-stat-$mod" . ($active ? ' is-active' : '') . ($href !== null ? ' is-link' : '') . "\"$attr>"
                    . '<span class="uu-stat-ic"><i class="bi bi-' . $icon . '"></i></span>'
                    . '<span class="uu-stat-body"><span class="uu-stat-n">' . number_format($n) . '</span>'
                    . '<span class="uu-stat-l">' . htmlspecialchars($label) . '</span></span>'
                    . "</$tag>";
            };
        ?>
        <div class="uu-stats" role="group" aria-label="User statistics and quick filters">
            <?php $stTile('total', 'people-fill', (int) $stats['total'], 'Total users', $filterUrl(['role' => '', 'q' => '', 'page' => null]), $noFilter); ?>
            <?php $stTile('online', 'broadcast', (int) $stats['online'], 'Online now'); ?>
            <?php if ((int) $stats['roles']['owner'] > 0): $stTile('owner', 'gem', (int) $stats['roles']['owner'], 'Owner', $filterUrl(['role' => 'owner', 'page' => null]), $roleFilter === 'owner'); endif; ?>
            <?php $stTile('superadmin', 'shield-lock-fill', (int) $stats['roles']['superadmin'], 'Superadmins', $filterUrl(['role' => 'superadmin', 'page' => null]), $roleFilter === 'superadmin'); ?>
            <?php $stTile('developer', 'code-slash', (int) $stats['roles']['developer'], 'Developers', $filterUrl(['role' => 'developer', 'page' => null]), $roleFilter === 'developer'); ?>
            <?php $stTile('user', 'person-fill', (int) $stats['roles']['user'], 'Users', $filterUrl(['role' => 'user', 'page' => null]), $roleFilter === 'user'); ?>
            <?php $stTile('new', 'person-plus-fill', (int) $stats['newThisWeek'], 'New this week'); ?>
            <?php if ((int) $stats['pending'] > 0): $stTile('pending', 'lightning-charge-fill', (int) $stats['pending'], 'Trial requests', '#trialQueueTitle'); endif; ?>
        </div>

        <form class="uu-search mb-3" method="get" action="<?= $baseUrl ?>/users" role="search">
            <?php if (!empty($roleFilter)): ?><input type="hidden" name="role" value="<?= htmlspecialchars($roleFilter) ?>"><?php endif; ?>
            <i class="bi bi-search"></i>
            <input type="search" id="userSearch" name="q" value="<?= htmlspecialchars($q) ?>"
                   placeholder="Search users by name, email or role…"
                   data-tip="Search across all users — results are paginated" autocomplete="off">
            <?php if ($q !== ''): ?>
                <a href="<?= $baseUrl ?>/users" class="uu-search-clear" data-tip="Clear search" aria-label="Clear search"><i class="bi bi-x-lg"></i></a>
            <?php endif; ?>
        </form>

        <?php if ($success): ?>
            <div class="alert alert-success"><?= htmlspecialchars($success) ?></div>
        <?php endif; ?>
        <?php if ($error): ?>
            <div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
        <?php endif; ?>

        <?php if (!empty($pendingRequests)): ?>
            <section class="trial-queue mb-4" aria-labelledby="trialQueueTitle">
                <div class="trial-queue-head">
                    <h5 id="trialQueueTitle" class="mb-0">
                        <i class="bi bi-lightning-charge"></i> Trial access requests
                        <span class="badge rounded-pill trial-count"><?= count($pendingRequests) ?></span>
                    </h5>
                    <span class="trial-sub">People asking to try <?= htmlspecialchars(\PpPhp\Core\Brand::name()) ?>. Approving one creates their account.</span>
                </div>

                <?php foreach ($pendingRequests as $r):
                    $isHighlight = (int) $r['id'] === (int) ($highlightRequest ?? 0);
                    $duration = \PpPhp\Core\Auth\TemporaryAccessRequestService::durationLabel((int) $r['requested_duration_hours']);
                ?>
                    <article class="trial-card<?= $isHighlight ? ' is-highlight' : '' ?>"<?= $isHighlight ? ' id="highlightedRequest"' : '' ?>>
                        <div class="trial-card-main">
                            <div class="trial-who">
                                <strong><?= htmlspecialchars((string) $r['full_name']) ?></strong>
                                <a href="mailto:<?= htmlspecialchars((string) $r['email']) ?>"><?= htmlspecialchars((string) $r['email']) ?></a>
                            </div>
                            <div class="trial-meta">
                                <?php if (!empty($r['organization'])): ?>
                                    <span><i class="bi bi-building"></i> <?= htmlspecialchars((string) $r['organization']) ?></span>
                                <?php endif; ?>
                                <?php if (!empty($r['role_title'])): ?>
                                    <span><i class="bi bi-person-badge"></i> <?= htmlspecialchars((string) $r['role_title']) ?></span>
                                <?php endif; ?>
                                <span><i class="bi bi-hourglass-split"></i> Wants <?= htmlspecialchars($duration) ?></span>
                                <span><i class="bi bi-clock"></i> <?= date('j M Y, g:i a', strtotime((string) $r['created_at'])) ?></span>
                            </div>
                            <p class="trial-use-case"><?= nl2br(htmlspecialchars((string) $r['use_case'])) ?></p>
                        </div>
                        <div class="trial-actions">
                            <a class="btn btn-sm btn-primary" href="<?= $baseUrl ?>/users/create?from_request=<?= (int) $r['id'] ?>"
                               data-tip="Create an account for this person, pre-filled from their request, and mark it approved">
                                <i class="bi bi-check2-circle"></i> Approve
                            </a>
                            <form action="<?= $baseUrl ?>/users/temporary-request/decline" method="post" class="decline-form">
                                <?= \PpPhp\Core\Security::CSRF()->HiddenField() ?>
                                <input type="hidden" name="id" value="<?= (int) $r['id'] ?>">
                                <button type="submit" class="btn btn-sm btn-outline-secondary"
                                        data-tip="Remove this request from the queue without emailing them">
                                    <i class="bi bi-x-lg"></i> Decline
                                </button>
                            </form>
                        </div>
                    </article>
                <?php endforeach; ?>
            </section>
        <?php endif; ?>

        <div class="uu-card">
            <div class="table-responsive">
            <table class="uu-table" id="usersTable">
                <thead>
                    <tr>
                        <th>Username</th>
                        <th>Email</th>
                        <th>
                            <span class="uu-th-wrap">Role
                                <div class="uu-hfilter<?= $roleFilter !== '' ? ' is-active' : '' ?>" data-hfilter>
                                    <button type="button" class="uu-hfilter-btn" data-hfilter-btn data-tip="Filter by role" aria-label="Filter by role"><i class="bi bi-funnel<?= $roleFilter !== '' ? '-fill' : '' ?>"></i></button>
                                    <div class="uu-hfilter-menu" data-hfilter-menu hidden>
                                        <div class="uu-hfilter-h">Filter by role</div>
                                        <a href="<?= htmlspecialchars($filterUrl(['role' => '', 'page' => null])) ?>" class="uu-hfilter-opt<?= $roleFilter === '' ? ' is-on' : '' ?>"><span>All roles</span><i class="bi bi-check2"></i></a>
                                        <?php foreach (['owner' => 'Owner', 'superadmin' => 'Superadmin', 'developer' => 'Developer', 'user' => 'User'] as $rk => $rl): ?>
                                            <a href="<?= htmlspecialchars($filterUrl(['role' => $rk, 'page' => null])) ?>" class="uu-hfilter-opt<?= $roleFilter === $rk ? ' is-on' : '' ?>"><span class="uu-role <?= $rk ?>"><?= $rl ?></span><i class="bi bi-check2"></i></a>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            </span>
                        </th>
                        <th>Created</th>
                        <th data-tip="When the account was last active (updates as they use the platform)">Last seen</th>
                        <th class="uu-th-act">Actions</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($users as $u):
                        $__role = strtolower((string) $u['role']);
                        $__roleClass = in_array($__role, ['owner', 'superadmin', 'developer'], true) ? $__role : 'user';
                    ?>
                        <tr data-user-row>
                            <td data-label="Username" class="uu-uname">
                                <span class="uu-av uu-av-<?= $__roleClass ?>"><?= strtoupper(htmlspecialchars(substr((string) $u['username'], 0, 2))) ?></span>
                                <span class="uu-uname-t"><?= htmlspecialchars($u['username']) ?></span>
                            </td>
                            <td data-label="Email" class="uu-email"><?= htmlspecialchars($u['email']) ?></td>
                            <td data-label="Role"><span class="uu-role <?= $__roleClass ?>"><?= htmlspecialchars($u['role']) ?></span></td>
                            <td data-label="Created" data-tip="<?= htmlspecialchars($timeAgo($u['created_at'] ?? null)) ?>">
                                <span class="uu-when"><?= $u['created_at'] ? date('M j, Y', strtotime($u['created_at'])) : '—' ?></span>
                                <?php if (!empty($u['created_at'])): ?><span class="uu-when-t"><?= date('g:i A', strtotime($u['created_at'])) ?></span><?php endif; ?>
                            </td>
                            <?php $__seen = $u['last_seen_at'] ?? null; $__st = $seenStatus($__seen); ?>
                            <td data-label="Last seen" data-tip="<?= $__seen ? htmlspecialchars($absTime($__seen) . (!empty($u['last_login_ip']) ? ' · IP ' . $u['last_login_ip'] : '')) : 'Has not signed in yet' ?>">
                                <span class="uu-seen uu-seen-<?= $__st ?>"><span class="uu-dot"></span><?= $__seen ? htmlspecialchars($timeAgo($__seen)) : 'Never' ?></span>
                            </td>
                            <?php
                                $__isSelf     = $currentUserId > 0 && (int) $u['id'] === $currentUserId;
                                $__isOwnerRow = $__role === 'owner';
                                $__canDelete  = !$__isSelf && !$__isOwnerRow;
                            ?>
                            <td class="uu-actcell" data-label="Actions">
                                <div class="uu-acts">
                                    <a href="<?= $baseUrl ?>/users/edit/<?= $u['id'] ?>" class="uu-act edit tip-left tip-up" data-tip="Edit this user’s details, role and password" aria-label="Edit user"><i class="bi bi-pencil"></i></a>
                                    <?php if ($__canDelete): ?>
                                        <form action="<?= $baseUrl ?>/users/delete/<?= $u['id'] ?>" method="post" class="delete-form" data-user-name="<?= htmlspecialchars($u['username']) ?>">
                                            <?= \PpPhp\Core\Security::CSRF()->HiddenField() ?>
                                            <button type="submit" class="uu-act del tip-left tip-up" data-tip="Delete this user permanently" aria-label="Delete user"><i class="bi bi-trash"></i></button>
                                        </form>
                                    <?php elseif ($__isSelf): ?>
                                        <span class="uu-selftag" data-tip="This is your own account">You</span>
                                    <?php else: ?>
                                        <span class="uu-act is-locked tip-left tip-up" data-tip="The owner account can’t be deleted" aria-hidden="true"><i class="bi bi-shield-lock"></i></span>
                                    <?php endif; ?>
                                </div>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    <?php if (empty($users)): ?>
                    <tr><td colspan="6">
                        <div class="uu-empty">
                            <i class="bi bi-people"></i>
                            <div><strong>No users found<?= $q !== '' ? ' for “' . htmlspecialchars($q) . '”' : '' ?></strong>
                            <span><?= $q !== '' ? 'Try a different search term.' : 'Add your first user to get started.' ?></span></div>
                        </div>
                    </td></tr>
                    <?php endif; ?>
                </tbody>
            </table>
            </div>
            <?php if ($total > 0): ?>
            <div class="uu-foot">
                <span class="uu-showing">Showing <strong><?= (int) $showFrom ?>&ndash;<?= (int) $showTo ?></strong> of <strong><?= (int) $total ?></strong> users</span>
                <?= $pager->render() ?>
            </div>
            <?php endif; ?>
        </div>
    </div>



    <script>
    // Arriving from the bell or the owner email: bring the request into view.
    var highlighted = document.getElementById('highlightedRequest');
    if (highlighted) {
        highlighted.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }

    document.querySelectorAll('.decline-form').forEach(form => {
        form.addEventListener('submit', function(e) {
            e.preventDefault();
            Swal.fire({
                title: 'Decline this request?',
                text: 'It leaves the queue. We will not email them about it.',
                icon: 'question',
                showCancelButton: true,
                confirmButtonColor: '#6c757d',
                cancelButtonColor: '#adb5bd',
                confirmButtonText: 'Yes, decline',
                cancelButtonText: 'Keep it'
            }).then((result) => {
                if (result.isConfirmed) {
                    form.submit();
                }
            });
        });
    });

    document.querySelectorAll('.delete-form').forEach(form => {
        form.addEventListener('submit', function(e) {
            e.preventDefault();
            var name = form.getAttribute('data-user-name') || 'this user';
            Swal.fire({
                title: 'Delete ' + name + '?',
                html: 'Their account and sign-in access are removed permanently. <b>This can’t be undone.</b>',
                icon: 'warning',
                showCancelButton: true,
                confirmButtonColor: '#dc3545',
                cancelButtonColor: '#6c757d',
                confirmButtonText: '<i class="bi bi-trash"></i> Delete user',
                cancelButtonText: 'Keep user',
                focusCancel: true
            }).then((result) => {
                if (result.isConfirmed) {
                    form.submit();
                }
            });
        });
    });

    // Debounced server-side search — submits the form so results span all users
    // and stay paginated (Enter also submits natively).
    (function () {
        var box = document.getElementById('userSearch');
        if (!box) return;
        var form = box.closest('form');
        var timer;
        box.addEventListener('input', function () {
            clearTimeout(timer);
            timer = setTimeout(function () { if (form) form.submit(); }, 450);
        });
    })();

    // Column-header filter dropdowns (Role) — dependency-free toggles.
    (function () {
        var btns = document.querySelectorAll('[data-hfilter-btn]');
        function closeAll() { document.querySelectorAll('[data-hfilter-menu]').forEach(function (m) { m.hidden = true; }); }
        btns.forEach(function (btn) {
            btn.addEventListener('click', function (e) {
                e.stopPropagation();
                var menu = btn.parentElement.querySelector('[data-hfilter-menu]');
                var willOpen = menu.hidden;
                closeAll();
                menu.hidden = !willOpen;
            });
        });
        document.addEventListener('click', closeAll);
        document.addEventListener('keydown', function (e) { if (e.key === 'Escape') closeAll(); });
    })();
    </script>

    <?php
    $__usersTopics = [
        [
            'id' => 'overview', 'label' => 'Overview', 'icon' => 'people-fill',
            'keywords' => 'users manage accounts overview what',
            'body' => '<h3>Managing users</h3>'
                . '<div class="og-lead"><i class="bi bi-info-circle-fill"></i><div>This screen is where you create, edit and remove accounts and review trial requests.</div></div>'
                . '<p>Use the <strong>filter box</strong> to find someone fast, and hover any button for a tooltip explaining what it does.</p>',
        ],
        [
            'id' => 'create', 'label' => 'Add & edit users', 'icon' => 'person-plus',
            'keywords' => 'add create edit user password role change',
            'body' => '<h3>Adding & editing</h3>'
                . '<ul><li><strong>Add User</strong> (top right) opens a blank form to create an account.</li>'
                . '<li>The <i class="bi bi-pencil"></i> button on a row edits that user — details, role and password.</li>'
                . '<li>The <i class="bi bi-trash"></i> button deletes a user; it asks for confirmation first.</li></ul>'
                . '<div class="og-warn"><i class="bi bi-exclamation-triangle"></i><div>Deleting a user is permanent and cannot be undone.</div></div>',
        ],
        [
            'id' => 'roles', 'label' => 'Roles', 'icon' => 'shield-lock',
            'keywords' => 'role superadmin developer user permissions access',
            'body' => '<h3>What the roles mean</h3>'
                . '<div class="og-steps">'
                . '<div class="og-step"><b><i class="bi bi-star"></i></b><strong>superadmin</strong><span>Full platform control.</span></div>'
                . '<div class="og-step"><b><i class="bi bi-code-slash"></i></b><strong>developer</strong><span>Builds apps &amp; manages projects.</span></div>'
                . '<div class="og-step"><b><i class="bi bi-person"></i></b><strong>user</strong><span>Standard account.</span></div>'
                . '</div>'
                . '<p>Set a user’s role from the edit screen. The role shown in the <strong>Role</strong> column controls what menus and actions they see.</p>',
        ],
        [
            'id' => 'trials', 'label' => 'Trial requests', 'icon' => 'lightning-charge',
            'keywords' => 'trial request approve decline queue try access temporary',
            'body' => '<h3>Trial access queue</h3>'
                . '<p>When someone asks to try ' . htmlspecialchars(\PpPhp\Core\Brand::name()) . ', their request appears at the top of this page.</p>'
                . '<ul><li><strong>Approve</strong> opens the Add User form pre-filled from their request and marks it approved.</li>'
                . '<li><strong>Decline</strong> removes it from the queue silently — no email is sent.</li></ul>'
                . '<div class="og-tip"><i class="bi bi-bell"></i><div>The bell notification and the owner email both deep-link straight to the relevant request here.</div></div>',
        ],
    ];
    $__usersTopics[] = [
        'id' => 'find', 'label' => 'Search, filters & export', 'icon' => 'funnel',
        'keywords' => 'search filter pagination export csv last seen activity role column sort online',
        'body' => '<h3>Find people fast</h3>'
            . '<p>The list is <strong>server-side paginated</strong>, so it stays fast with thousands of users.</p>'
            . '<ul><li><strong>Search</strong> — the box matches username and email as you type.</li>'
            . '<li><strong>Column filters</strong> — click the funnel on the <strong>Role</strong> header to narrow the list (e.g. only developers). The stat tiles at the top are clickable filters too.</li>'
            . '<li><strong>Last seen</strong> — the activity column shows each person\'s last sign-in in plain language (e.g. “3 hours ago”), with a coloured dot for online / away / offline.</li></ul>'
            . '<div class="og-tip"><i class="bi bi-filetype-csv"></i><div>The <strong>Export</strong> button downloads the list as CSV. It respects whatever search and filters are active — so you can export just developers or the full list.</div></div>',
    ];
    $ownerGuide = [
        'id' => 'usersGuide',
        'eyebrow' => 'Guide',
        'title' => 'Manage Users',
        'subtitle' => 'Create accounts, set roles, and handle trial requests.',
        'icon' => 'people-fill',
        'topics' => $__usersTopics,
    ];
    include constant('BASE_PATH') . '/core/views/owner-ux.php';
    ?>

</body>

</html>
