<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>TieMeasureFlow &mdash; Setup</title>
    <style>
        /* --- Reset & Base -------------------------------------------------- */
        *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

        body {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #f0f4ff 0%, #e8ecf4 100%);
            color: #1e293b;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 40px 16px;
        }

        /* --- Typography ---------------------------------------------------- */
        h1 { font-size: 1.75rem; font-weight: 700; color: #0f172a; }
        h2 { font-size: 1.15rem; font-weight: 600; color: #334155; margin-bottom: 12px; }
        p  { line-height: 1.5; color: #64748b; }

        .brand-sub { font-size: 0.85rem; color: #64748b; margin-top: 4px; }
        .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }

        /* --- Layout -------------------------------------------------------- */
        .container { width: 100%; max-width: 600px; }

        .logo-header {
            text-align: center;
            margin-bottom: 32px;
        }
        .logo-header .icon {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 56px; height: 56px;
            background: #2563eb;
            border-radius: 14px;
            color: #fff;
            font-size: 1.5rem;
            font-weight: 700;
            margin-bottom: 12px;
        }

        /* --- Card ---------------------------------------------------------- */
        .card {
            background: #fff;
            border-radius: 12px;
            box-shadow: 0 1px 3px rgba(0,0,0,.08), 0 4px 16px rgba(0,0,0,.04);
            padding: 24px;
            margin-bottom: 20px;
        }
        .card.danger { border-left: 4px solid #dc2626; }

        /* --- Form elements ------------------------------------------------- */
        label {
            display: block;
            font-size: 0.82rem;
            font-weight: 500;
            color: #475569;
            margin-bottom: 4px;
        }
        input[type="text"],
        input[type="password"],
        input[type="email"] {
            width: 100%;
            padding: 10px 12px;
            border: 1px solid #cbd5e1;
            border-radius: 8px;
            font-size: 0.9rem;
            font-family: inherit;
            color: #1e293b;
            background: #f8fafc;
            transition: border-color .15s, box-shadow .15s;
            margin-bottom: 14px;
        }
        input:focus {
            outline: none;
            border-color: #2563eb;
            box-shadow: 0 0 0 3px rgba(37,99,235,.15);
        }

        /* --- Buttons ------------------------------------------------------- */
        .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            padding: 10px 20px;
            border: none;
            border-radius: 8px;
            font-family: inherit;
            font-size: 0.9rem;
            font-weight: 600;
            cursor: pointer;
            transition: background .15s, transform .1s, opacity .15s;
            width: 100%;
        }
        .btn:active { transform: scale(.98); }
        .btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }

        .btn-primary { background: #2563eb; color: #fff; }
        .btn-primary:hover:not(:disabled) { background: #1d4ed8; }

        .btn-success { background: #16a34a; color: #fff; }
        .btn-success:hover:not(:disabled) { background: #15803d; }

        .btn-danger  { background: #dc2626; color: #fff; }
        .btn-danger:hover:not(:disabled) { background: #b91c1c; }

        .btn-outline {
            background: transparent;
            color: #2563eb;
            border: 1.5px solid #2563eb;
        }
        .btn-outline:hover:not(:disabled) { background: #eff6ff; }

        /* --- Status pills -------------------------------------------------- */
        .status-bar {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 10px 14px;
            border-radius: 8px;
            font-size: 0.85rem;
            font-weight: 500;
            margin-bottom: 12px;
        }
        .status-bar.ok   { background: #f0fdf4; color: #166534; border: 1px solid #bbf7d0; }
        .status-bar.warn { background: #fffbeb; color: #92400e; border: 1px solid #fde68a; }
        .status-bar.err  { background: #fef2f2; color: #991b1b; border: 1px solid #fecaca; }

        .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
        .dot.green  { background: #16a34a; }
        .dot.yellow { background: #eab308; }
        .dot.red    { background: #dc2626; }

        /* --- Table list ---------------------------------------------------- */
        .table-list {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .table-chip {
            background: #f1f5f9;
            color: #475569;
            padding: 3px 10px;
            border-radius: 6px;
            font-size: 0.78rem;
            font-family: 'JetBrains Mono', monospace;
        }

        /* --- Checkbox ------------------------------------------------------ */
        .checkbox-row {
            display: flex;
            align-items: center;
            gap: 8px;
            margin: 12px 0 16px;
            font-size: 0.85rem;
            color: #64748b;
        }
        .checkbox-row input[type="checkbox"] {
            width: 16px; height: 16px;
            accent-color: #dc2626;
        }

        /* --- Toast --------------------------------------------------------- */
        #toast-container {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 9999;
            display: flex;
            flex-direction: column;
            gap: 8px;
            max-width: 380px;
        }
        .toast {
            padding: 12px 18px;
            border-radius: 8px;
            font-size: 0.85rem;
            font-weight: 500;
            color: #fff;
            box-shadow: 0 4px 12px rgba(0,0,0,.15);
            animation: slideIn .25s ease-out;
            word-break: break-word;
        }
        .toast.success { background: #16a34a; }
        .toast.error   { background: #dc2626; }
        .toast.info    { background: #2563eb; }

        @keyframes slideIn {
            from { opacity: 0; transform: translateX(30px); }
            to   { opacity: 1; transform: translateX(0); }
        }
        @keyframes fadeOut {
            from { opacity: 1; }
            to   { opacity: 0; transform: translateY(-10px); }
        }

        /* --- Spinner ------------------------------------------------------- */
        .spinner {
            display: inline-block;
            width: 16px; height: 16px;
            border: 2px solid rgba(255,255,255,.3);
            border-top-color: #fff;
            border-radius: 50%;
            animation: spin .6s linear infinite;
        }
        @keyframes spin { to { transform: rotate(360deg); } }

        /* --- Separator ----------------------------------------------------- */
        .sep { border: none; border-top: 1px solid #e2e8f0; margin: 18px 0; }

        /* --- Helpers ------------------------------------------------------- */
        .hidden { display: none !important; }
        .mt-2 { margin-top: 8px; }
        .mt-4 { margin-top: 16px; }
        .text-sm { font-size: 0.82rem; }
        .text-muted { color: #94a3b8; }

        /* --- User Management ----------------------------------------------- */
        .user-table {
            width: 100%;
            border-collapse: collapse;
            font-size: 0.85rem;
            margin-top: 12px;
        }
        .user-table th {
            text-align: left;
            padding: 8px 10px;
            background: #f8fafc;
            color: #475569;
            font-weight: 600;
            border-bottom: 2px solid #e2e8f0;
            font-size: 0.78rem;
            text-transform: uppercase;
            letter-spacing: 0.03em;
        }
        .user-table td {
            padding: 8px 10px;
            border-bottom: 1px solid #f1f5f9;
            vertical-align: middle;
        }
        .user-table tr:hover td { background: #f8fafc; }

        .badge {
            display: inline-block;
            padding: 2px 8px;
            border-radius: 12px;
            font-size: 0.72rem;
            font-weight: 600;
            letter-spacing: 0.02em;
        }
        .badge-maker       { background: #dbeafe; color: #1d4ed8; }
        .badge-measurement  { background: #dcfce7; color: #166534; }
        .badge-metrologist  { background: #fef3c7; color: #92400e; }
        .badge-admin        { background: #fce7f3; color: #9d174d; }
        .badge-active       { background: #dcfce7; color: #166534; }
        .badge-inactive     { background: #fee2e2; color: #991b1b; }

        .btn-sm {
            padding: 4px 10px;
            font-size: 0.75rem;
            border-radius: 6px;
            border: none;
            cursor: pointer;
            font-weight: 500;
            font-family: inherit;
            transition: background .15s;
        }
        .btn-sm-primary  { background: #2563eb; color: #fff; }
        .btn-sm-primary:hover { background: #1d4ed8; }
        .btn-sm-warning  { background: #f59e0b; color: #fff; }
        .btn-sm-warning:hover { background: #d97706; }
        .btn-sm-danger   { background: #ef4444; color: #fff; }
        .btn-sm-danger:hover { background: #dc2626; }
        .btn-sm-success  { background: #10b981; color: #fff; }
        .btn-sm-success:hover { background: #059669; }

        .action-btns { display: flex; gap: 4px; flex-wrap: wrap; }

        /* --- Modal --------------------------------------------------------- */
        .modal-overlay {
            position: fixed;
            inset: 0;
            background: rgba(0,0,0,.4);
            z-index: 1000;
            display: flex;
            align-items: center;
            justify-content: center;
            animation: fadeInOverlay .2s ease-out;
        }
        @keyframes fadeInOverlay { from { opacity: 0; } to { opacity: 1; } }

        .modal {
            background: #fff;
            border-radius: 12px;
            box-shadow: 0 8px 30px rgba(0,0,0,.2);
            padding: 24px;
            width: 90%;
            max-width: 480px;
            max-height: 90vh;
            overflow-y: auto;
            animation: scaleIn .2s ease-out;
        }
        @keyframes scaleIn { from { transform: scale(.95); opacity: 0; } to { transform: scale(1); opacity: 1; } }

        .modal h2 { margin-bottom: 16px; }
        .modal .btn { margin-top: 8px; }

        .modal-actions {
            display: flex;
            gap: 8px;
            margin-top: 16px;
        }
        .modal-actions .btn { flex: 1; }

        /* --- Checkbox group ------------------------------------------------ */
        .checkbox-group {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            margin-bottom: 14px;
        }
        .checkbox-group label {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 0.85rem;
            margin-bottom: 0;
            cursor: pointer;
        }
        .checkbox-group input[type="checkbox"] {
            width: 16px; height: 16px;
            accent-color: #2563eb;
        }
    </style>
</head>
<body>

<!-- Toast container -->
<div id="toast-container"></div>

<!-- ================================================================== -->
<!-- LOGIN SCREEN                                                        -->
<!-- ================================================================== -->
<div class="container" id="login-screen">
    <div class="logo-header">
        <div class="icon">TM</div>
        <h1>TieMeasureFlow</h1>
        <p class="brand-sub">System Setup</p>
    </div>

    <div class="card">
        <h2>Setup Password</h2>
        <p class="text-sm text-muted" style="margin-bottom:16px;">
            Enter the <span class="mono">SETUP_PASSWORD</span> from your <span class="mono">.env</span> file to continue.
        </p>
        <label for="setup-pwd">Password</label>
        <input type="password" id="setup-pwd" placeholder="Enter setup password" autofocus>
        <button class="btn btn-primary" id="btn-login" onclick="doLogin()">Unlock Setup</button>
    </div>
</div>

<!-- ================================================================== -->
<!-- SETUP PANEL (hidden until login)                                     -->
<!-- ================================================================== -->
<div class="container hidden" id="setup-panel">
    <div class="logo-header">
        <div class="icon">TM</div>
        <h1>TieMeasureFlow</h1>
        <p class="brand-sub">System Setup Panel</p>
    </div>

    <!-- 1. DB Status --------------------------------------------------- -->
    <div class="card" id="card-status">
        <h2>Database Status</h2>
        <div id="status-content">
            <p class="text-sm text-muted">Loading...</p>
        </div>
    </div>

    <!-- 2. Init DB ----------------------------------------------------- -->
    <div class="card">
        <h2>Initialize Database</h2>
        <p class="text-sm text-muted" style="margin-bottom:14px;">
            Create all required tables in the database. Safe to run multiple times.
        </p>
        <button class="btn btn-primary" id="btn-init" onclick="initDb()">Create Tables</button>
    </div>

    <!-- 3. Create Admin ------------------------------------------------ -->
    <div class="card">
        <h2>Create Admin User</h2>
        <p class="text-sm text-muted" style="margin-bottom:14px;">
            Create a new administrator with all roles enabled.
        </p>
        <label for="admin-username">Username</label>
        <input type="text" id="admin-username" placeholder="admin">
        <label for="admin-password">Password</label>
        <input type="password" id="admin-password" placeholder="Strong password">
        <label for="admin-email">Email</label>
        <input type="email" id="admin-email" placeholder="admin@example.com">
        <label for="admin-displayname">Display Name</label>
        <input type="text" id="admin-displayname" placeholder="Administrator">
        <button class="btn btn-success" id="btn-admin" onclick="createAdmin()">Create Admin</button>
    </div>

    <!-- 4. Seed Demo --------------------------------------------------- -->
    <div class="card">
        <h2>Seed Demo Data</h2>
        <p class="text-sm text-muted" style="margin-bottom:14px;">
            Populate the database with sample users, a demo recipe, and 180 measurements for SPC testing.
            Creates users: <span class="mono">admin</span>, <span class="mono">maker1</span>,
            <span class="mono">tec1</span>, <span class="mono">metro1</span>.
        </p>
        <button class="btn btn-success" id="btn-seed" onclick="seedData()">Load Demo Data</button>
    </div>

    <!-- 5. User Management ------------------------------------------------ -->
    <div class="card" id="card-users">
        <h2>User Management</h2>
        <p class="text-sm text-muted" style="margin-bottom:14px;">
            Create, edit, and manage user accounts. Changes take effect immediately.
        </p>
        <button class="btn btn-primary" style="width:auto; margin-bottom:14px;" onclick="openCreateUserModal()">+ New User</button>
        <div id="users-table-container">
            <p class="text-sm text-muted">Unlock the setup page to load users.</p>
        </div>
    </div>

    <!-- 6. Reset DB ---------------------------------------------------- -->
    <div class="card danger">
        <h2 style="color:#dc2626;">Reset Database</h2>
        <p class="text-sm" style="color:#991b1b; margin-bottom:8px;">
            This will <strong>DROP ALL TABLES</strong> and recreate them. All data will be permanently lost.
        </p>
        <div class="checkbox-row">
            <input type="checkbox" id="reset-confirm">
            <label for="reset-confirm" style="margin-bottom:0; cursor:pointer;">I understand this action is irreversible</label>
        </div>
        <button class="btn btn-danger" id="btn-reset" onclick="resetDb()" disabled>Reset Database</button>
    </div>
</div>

<!-- ================================================================== -->
<!-- MODALS                                                               -->
<!-- ================================================================== -->

<!-- Create / Edit User Modal -->
<div class="modal-overlay hidden" id="modal-user">
    <div class="modal">
        <h2 id="modal-user-title">New User</h2>
        <input type="hidden" id="mu-user-id">
        <label for="mu-username">Username</label>
        <input type="text" id="mu-username" placeholder="username">
        <label for="mu-password">Password <span id="mu-pwd-hint" class="text-muted text-sm">(required)</span></label>
        <input type="password" id="mu-password" placeholder="Password">
        <label for="mu-displayname">Display Name</label>
        <input type="text" id="mu-displayname" placeholder="Full Name">
        <label for="mu-email">Email</label>
        <input type="email" id="mu-email" placeholder="user@example.com">
        <label>Roles</label>
        <div class="checkbox-group">
            <label><input type="checkbox" id="mu-role-maker" value="Maker"> Maker</label>
            <label><input type="checkbox" id="mu-role-tec" value="MeasurementTec"> MeasurementTec</label>
            <label><input type="checkbox" id="mu-role-metro" value="Metrologist"> Metrologist</label>
        </div>
        <div class="checkbox-group">
            <label><input type="checkbox" id="mu-admin"> Administrator</label>
        </div>
        <div class="modal-actions">
            <button class="btn btn-outline" onclick="closeModal('modal-user')">Cancel</button>
            <button class="btn btn-primary" id="btn-save-user" onclick="saveUser()">Save User</button>
        </div>
    </div>
</div>

<!-- Change Password Modal -->
<div class="modal-overlay hidden" id="modal-password">
    <div class="modal">
        <h2>Change Password</h2>
        <input type="hidden" id="mp-user-id">
        <p class="text-sm text-muted" style="margin-bottom:14px;">
            Changing password for: <strong id="mp-username"></strong>
        </p>
        <label for="mp-new-password">New Password</label>
        <input type="password" id="mp-new-password" placeholder="New password">
        <label for="mp-confirm-password">Confirm Password</label>
        <input type="password" id="mp-confirm-password" placeholder="Confirm password">
        <div class="modal-actions">
            <button class="btn btn-outline" onclick="closeModal('modal-password')">Cancel</button>
            <button class="btn btn-primary" onclick="changePassword()">Change Password</button>
        </div>
    </div>
</div>

<!-- ================================================================== -->
<!-- JAVASCRIPT                                                          -->
<!-- ================================================================== -->
<script>
    /* ------------------------------------------------------------------ */
    /* State                                                               */
    /* ------------------------------------------------------------------ */
    let setupPassword = '';

    /* ------------------------------------------------------------------ */
    /* Toast notifications                                                 */
    /* ------------------------------------------------------------------ */
    function showToast(message, type) {
        type = type || 'info';
        const container = document.getElementById('toast-container');
        const el = document.createElement('div');
        el.className = 'toast ' + type;
        el.textContent = message;
        container.appendChild(el);
        setTimeout(function() {
            el.style.animation = 'fadeOut .3s ease-out forwards';
            setTimeout(function() { el.remove(); }, 300);
        }, 4000);
    }

    /* ------------------------------------------------------------------ */
    /* Loading helpers                                                     */
    /* ------------------------------------------------------------------ */
    function setLoading(btnId, loading) {
        const btn = document.getElementById(btnId);
        if (!btn) return;
        if (loading) {
            btn.disabled = true;
            btn._origText = btn.innerHTML;
            btn.innerHTML = '<span class="spinner"></span> Working...';
        } else {
            btn.disabled = false;
            btn.innerHTML = btn._origText || btn.innerHTML;
        }
    }

    /* ------------------------------------------------------------------ */
    /* API helpers                                                         */
    /* ------------------------------------------------------------------ */
    async function apiPost(path, body) {
        const resp = await fetch('/api/setup' + path, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(body),
        });
        const data = await resp.json();
        if (!resp.ok) {
            throw new Error(data.detail || 'Request failed (' + resp.status + ')');
        }
        return data;
    }

    /* Setup operations rotate api_keys (DB init, admin creation, password
     * change, user (de)activation). Any Flask session held in this browser
     * still carries the old key, so we clear it to force a fresh /auth/login. */
    async function invalidateClientSession() {
        try {
            await fetch('/auth/logout', {
                method: 'POST',
                credentials: 'same-origin',
                redirect: 'manual',
            });
        } catch (_) { /* best-effort */ }
    }

    /* ------------------------------------------------------------------ */
    /* Check DB status                                                     */
    /* ------------------------------------------------------------------ */
    async function checkStatus() {
        const container = document.getElementById('status-content');
        try {
            const resp = await fetch('/api/setup/status');
            if (!resp.ok) throw new Error('Status endpoint returned ' + resp.status);
            const data = await resp.json();

            let html = '';
            if (data.tables_exist) {
                html += '<div class="status-bar ok"><span class="dot green"></span>'
                     +  'Database initialized &mdash; ' + data.table_count + ' table(s)</div>';
                html += '<div class="table-list">';
                data.tables.forEach(function(t) {
                    html += '<span class="table-chip">' + escHtml(t) + '</span>';
                });
                html += '</div>';
            } else {
                html += '<div class="status-bar warn"><span class="dot yellow"></span>'
                     +  'No tables found. Click "Create Tables" below.</div>';
            }
            container.innerHTML = html;
        } catch (e) {
            container.innerHTML = '<div class="status-bar err"><span class="dot red"></span>'
                                + 'Could not fetch status: ' + escHtml(e.message) + '</div>';
        }
    }

    /* ------------------------------------------------------------------ */
    /* Login                                                               */
    /* ------------------------------------------------------------------ */
    async function doLogin() {
        const pwd = document.getElementById('setup-pwd').value.trim();
        if (!pwd) { showToast('Please enter a password', 'error'); return; }

        setLoading('btn-login', true);
        try {
            const resp = await fetch('/api/setup/status');
            if (resp.status === 404) {
                showToast('Setup is disabled. Set SETUP_PASSWORD in .env', 'error');
                return;
            }
            // Validate password via init-db (idempotent, no tables needed)
            await apiPost('/init-db', { password: pwd });
            setupPassword = pwd;
            document.getElementById('login-screen').classList.add('hidden');
            document.getElementById('setup-panel').classList.remove('hidden');
            await checkStatus();
            await loadUsers();
            showToast('Setup panel unlocked', 'success');
        } catch (e) {
            if (e.message.indexOf('403') !== -1 || e.message.indexOf('Invalid') !== -1) {
                showToast('Invalid setup password', 'error');
            } else {
                showToast('Connection error: ' + e.message, 'error');
            }
        } finally {
            setLoading('btn-login', false);
        }
    }

    /* Allow Enter key on password field */
    document.getElementById('setup-pwd').addEventListener('keydown', function(e) {
        if (e.key === 'Enter') doLogin();
    });

    /* ------------------------------------------------------------------ */
    /* Init DB                                                             */
    /* ------------------------------------------------------------------ */
    async function initDb() {
        setLoading('btn-init', true);
        try {
            const data = await apiPost('/init-db', { password: setupPassword });
            showToast(data.message, 'success');
            await invalidateClientSession();
            await checkStatus();
        } catch (e) {
            showToast(e.message, 'error');
        } finally {
            setLoading('btn-init', false);
        }
    }

    /* ------------------------------------------------------------------ */
    /* Create Admin                                                        */
    /* ------------------------------------------------------------------ */
    async function createAdmin() {
        const username = document.getElementById('admin-username').value.trim();
        const password = document.getElementById('admin-password').value;
        const email    = document.getElementById('admin-email').value.trim();
        const display  = document.getElementById('admin-displayname').value.trim();

        if (!username || !password || !email || !display) {
            showToast('All fields are required', 'error');
            return;
        }

        setLoading('btn-admin', true);
        try {
            const data = await apiPost('/create-admin', {
                password: setupPassword,
                admin_username: username,
                admin_password: password,
                admin_email: email,
                admin_display_name: display,
            });
            showToast(data.message, 'success');
            await invalidateClientSession();
            // Clear form
            document.getElementById('admin-username').value = '';
            document.getElementById('admin-password').value = '';
            document.getElementById('admin-email').value = '';
            document.getElementById('admin-displayname').value = '';
        } catch (e) {
            showToast(e.message, 'error');
        } finally {
            setLoading('btn-admin', false);
        }
    }

    /* ------------------------------------------------------------------ */
    /* Seed Demo Data                                                      */
    /* ------------------------------------------------------------------ */
    async function seedData() {
        setLoading('btn-seed', true);
        try {
            const data = await apiPost('/seed', { password: setupPassword });
            var msg = data.message + ' (users: ' + data.users_created.join(', ');
            if (data.measurements_created) msg += ', measurements: ' + data.measurements_created;
            msg += ')';
            showToast(msg, 'success');
            await invalidateClientSession();
            await loadUsers();
        } catch (e) {
            showToast(e.message, 'error');
        } finally {
            setLoading('btn-seed', false);
        }
    }

    /* ------------------------------------------------------------------ */
    /* Reset DB                                                            */
    /* ------------------------------------------------------------------ */

    /* Enable reset button only when checkbox is checked */
    document.getElementById('reset-confirm').addEventListener('change', function() {
        document.getElementById('btn-reset').disabled = !this.checked;
    });

    async function resetDb() {
        if (!document.getElementById('reset-confirm').checked) {
            showToast('Please confirm the checkbox first', 'error');
            return;
        }
        if (!confirm('Are you absolutely sure? This will destroy ALL data!')) {
            return;
        }

        setLoading('btn-reset', true);
        try {
            const data = await apiPost('/reset-db', {
                password: setupPassword,
                confirm: true,
            });
            showToast(data.message, 'success');
            document.getElementById('reset-confirm').checked = false;
            document.getElementById('btn-reset').disabled = true;
            await checkStatus();
        } catch (e) {
            showToast(e.message, 'error');
        } finally {
            setLoading('btn-reset', false);
        }
    }

    /* ================================================================== */
    /* USER MANAGEMENT                                                     */
    /* ================================================================== */

    function escHtml(str) {
        if (!str) return '';
        var d = document.createElement('div');
        d.textContent = str;
        return d.innerHTML;
    }

    function roleBadge(role) {
        var cls = 'badge ';
        if (role === 'Maker') cls += 'badge-maker';
        else if (role === 'MeasurementTec') cls += 'badge-measurement';
        else if (role === 'Metrologist') cls += 'badge-metrologist';
        return '<span class="' + cls + '">' + escHtml(role) + '</span> ';
    }

    async function loadUsers() {
        var container = document.getElementById('users-table-container');
        try {
            var data = await apiPost('/list-users', { password: setupPassword });
            if (!data.users || data.users.length === 0) {
                container.innerHTML = '<p class="text-sm text-muted">No users found. Use Seed Demo Data or create one.</p>';
                return;
            }
            var html = '<table class="user-table"><thead><tr>'
                     + '<th>ID</th><th>Username</th><th>Display Name</th>'
                     + '<th>Roles</th><th>Status</th><th>Actions</th>'
                     + '</tr></thead><tbody>';
            data.users.forEach(function(u) {
                var roles = '';
                (u.roles || []).forEach(function(r) { roles += roleBadge(r); });
                if (u.is_admin) roles += '<span class="badge badge-admin">Admin</span> ';
                var statusBadge = u.active
                    ? '<span class="badge badge-active">Active</span>'
                    : '<span class="badge badge-inactive">Inactive</span>';
                var toggleLabel = u.active ? 'Deactivate' : 'Activate';
                var toggleClass = u.active ? 'btn-sm-danger' : 'btn-sm-success';
                html += '<tr>'
                     + '<td class="mono">' + u.id + '</td>'
                     + '<td class="mono">' + escHtml(u.username) + '</td>'
                     + '<td>' + escHtml(u.display_name) + '</td>'
                     + '<td>' + roles + '</td>'
                     + '<td>' + statusBadge + '</td>'
                     + '<td><div class="action-btns">'
                     + '<button class="btn-sm btn-sm-primary" onclick="openEditUserModal(' + u.id + ')">Edit</button>'
                     + '<button class="btn-sm btn-sm-warning" onclick="openPasswordModal(' + u.id + ', \'' + escHtml(u.username).replace(/'/g, "\\'") + '\')">Password</button>'
                     + '<button class="btn-sm ' + toggleClass + '" onclick="toggleActive(' + u.id + ', \'' + escHtml(u.username).replace(/'/g, "\\'") + '\', ' + u.active + ')">' + toggleLabel + '</button>'
                     + '</div></td></tr>';
            });
            html += '</tbody></table>';
            container.innerHTML = html;
        } catch (e) {
            container.innerHTML = '<div class="status-bar err"><span class="dot red"></span>' + escHtml(e.message) + '</div>';
        }
    }

    /* -- Modal helpers ------------------------------------------------- */
    function closeModal(id) {
        document.getElementById(id).classList.add('hidden');
    }

    function openCreateUserModal() {
        document.getElementById('modal-user-title').textContent = 'New User';
        document.getElementById('mu-user-id').value = '';
        document.getElementById('mu-username').value = '';
        document.getElementById('mu-password').value = '';
        document.getElementById('mu-displayname').value = '';
        document.getElementById('mu-email').value = '';
        document.getElementById('mu-role-maker').checked = false;
        document.getElementById('mu-role-tec').checked = false;
        document.getElementById('mu-role-metro').checked = false;
        document.getElementById('mu-admin').checked = false;
        document.getElementById('mu-pwd-hint').textContent = '(required)';
        document.getElementById('modal-user').classList.remove('hidden');
    }

    /* Store user data for edit lookup */
    var _usersCache = [];

    async function openEditUserModal(userId) {
        /* Reload users to get fresh data */
        try {
            var data = await apiPost('/list-users', { password: setupPassword });
            _usersCache = data.users || [];
        } catch (e) {
            showToast('Failed to load user: ' + e.message, 'error');
            return;
        }
        var user = _usersCache.find(function(u) { return u.id === userId; });
        if (!user) { showToast('User not found', 'error'); return; }

        document.getElementById('modal-user-title').textContent = 'Edit User';
        document.getElementById('mu-user-id').value = user.id;
        document.getElementById('mu-username').value = user.username;
        document.getElementById('mu-password').value = '';
        document.getElementById('mu-displayname').value = user.display_name;
        document.getElementById('mu-email').value = user.email || '';
        document.getElementById('mu-role-maker').checked = (user.roles || []).indexOf('Maker') !== -1;
        document.getElementById('mu-role-tec').checked = (user.roles || []).indexOf('MeasurementTec') !== -1;
        document.getElementById('mu-role-metro').checked = (user.roles || []).indexOf('Metrologist') !== -1;
        document.getElementById('mu-admin').checked = user.is_admin;
        document.getElementById('mu-pwd-hint').textContent = '(leave blank to keep current)';
        document.getElementById('modal-user').classList.remove('hidden');
    }

    async function saveUser() {
        var userId = document.getElementById('mu-user-id').value;
        var username = document.getElementById('mu-username').value.trim();
        var pwd = document.getElementById('mu-password').value;
        var displayName = document.getElementById('mu-displayname').value.trim();
        var email = document.getElementById('mu-email').value.trim();

        if (!username || !displayName) {
            showToast('Username and Display Name are required', 'error');
            return;
        }
        if (!userId && !pwd) {
            showToast('Password is required for new users', 'error');
            return;
        }

        var roles = [];
        if (document.getElementById('mu-role-maker').checked) roles.push('Maker');
        if (document.getElementById('mu-role-tec').checked) roles.push('MeasurementTec');
        if (document.getElementById('mu-role-metro').checked) roles.push('Metrologist');

        setLoading('btn-save-user', true);
        try {
            var body = {
                password: setupPassword,
                user_id: userId ? parseInt(userId) : null,
                username: username,
                display_name: displayName,
                email: email || null,
                roles: roles,
                is_admin: document.getElementById('mu-admin').checked,
            };
            if (pwd) body.user_password = pwd;
            var data = await apiPost('/manage-user', body);
            showToast(data.message, 'success');
            await invalidateClientSession();
            closeModal('modal-user');
            await loadUsers();
        } catch (e) {
            showToast(e.message, 'error');
        } finally {
            setLoading('btn-save-user', false);
        }
    }

    function openPasswordModal(userId, username) {
        document.getElementById('mp-user-id').value = userId;
        document.getElementById('mp-username').textContent = username;
        document.getElementById('mp-new-password').value = '';
        document.getElementById('mp-confirm-password').value = '';
        document.getElementById('modal-password').classList.remove('hidden');
    }

    async function changePassword() {
        var userId = document.getElementById('mp-user-id').value;
        var newPwd = document.getElementById('mp-new-password').value;
        var confirmPwd = document.getElementById('mp-confirm-password').value;

        if (!newPwd) { showToast('Password cannot be empty', 'error'); return; }
        if (newPwd !== confirmPwd) { showToast('Passwords do not match', 'error'); return; }

        try {
            var data = await apiPost('/change-user-password', {
                password: setupPassword,
                user_id: parseInt(userId),
                new_password: newPwd,
            });
            showToast(data.message, 'success');
            await invalidateClientSession();
            closeModal('modal-password');
        } catch (e) {
            showToast(e.message, 'error');
        }
    }

    async function toggleActive(userId, username, currentlyActive) {
        var action = currentlyActive ? 'deactivate' : 'activate';
        if (!confirm('Are you sure you want to ' + action + ' user "' + username + '"?')) return;

        try {
            var data = await apiPost('/toggle-user-active', {
                password: setupPassword,
                user_id: userId,
            });
            showToast(data.message, 'success');
            await invalidateClientSession();
            await loadUsers();
        } catch (e) {
            showToast(e.message, 'error');
        }
    }
</script>
</body>
</html>
