// ── User Management (with group tags and search filter) ─────────────
function secUserStatusPill(status) {
    const key = String(status || 'active').toLowerCase();
    const map = {
        active:   { cls: 'is-active',   icon: 'bi-check-circle-fill' },
        pending:  { cls: 'is-pending',  icon: 'bi-hourglass-split' },
        inactive: { cls: 'is-inactive', icon: 'bi-pause-circle-fill' },
        banned:   { cls: 'is-banned',   icon: 'bi-slash-circle-fill' }
    };
    const m = map[key] || { cls: 'is-inactive', icon: 'bi-circle' };
    return `<span class="secusr-status ${m.cls}"><i class="bi ${m.icon}"></i> ${escapeHtml(key)}</span>`;
}

async function renderUsers() {
    if (!window.securitySettings?.db_auth_enabled) {
        const container = document.getElementById('securityPageContainer');
        if (container) container.innerHTML = '<div class="alert alert-warning">Database authentication is not enabled. Please enable it in the Settings tab first.</div>';
        return;
    }
    const container = document.getElementById('securityPageContainer');
    if (!container) return;

    container.innerHTML = '<div class="text-center py-5"><div class="spinner-border"></div></div>';

    let users = [];
    let assignments = [];
    let groups = [];
    try {
        const [usersRes, assignRes, groupsRes] = await Promise.all([
            fetch(`${baseUrl}/project/${projectSlug}/security/users`),
            fetch(`${baseUrl}/project/${projectSlug}/security/user-groups`),
            fetch(`${baseUrl}/project/${projectSlug}/security/groups`)
        ]);
        const usersData = await usersRes.json();
        const assignData = await assignRes.json();
        const groupsData = await groupsRes.json();

        if (usersData.success) {
            users = usersData.users;
            window.securityData.userRoles = usersData.roles || [];
            window.securityData.userStatuses = usersData.statuses || [];
        } else throw new Error(usersData.message);

        // FIX: Ensure assignments is always an array
        assignments = (assignData.success && Array.isArray(assignData.assignments)) ? assignData.assignments : [];
        groups = (groupsData.success && Array.isArray(groupsData.groups)) ? groupsData.groups : [];
    } catch (e) {
        console.error('renderUsers error:', e);
        container.innerHTML = `<div class="alert alert-danger">Failed to load users: ${e.message}</div>`;
        return;
    }
    window.securityData.users = users;
    window.securityData.groups = groups;  // store for later use
    window.securityData.assignments = assignments;

    // Build map: user_id -> array of group names
    const userGroupsMap = {};
    assignments.forEach(a => {
        const group = groups.find(g => g.id === a.group_id);
        if (group) {
            if (!userGroupsMap[a.user_id]) userGroupsMap[a.user_id] = [];
            userGroupsMap[a.user_id].push(group.name);
        }
    });

    const settings = window.securitySettings;
    const usernameField = settings.username_field || 'username';
    const emailField = settings.email_field || 'email';
    const fullnameField = settings.fullname_field || 'fullname';
    const roleField = settings.role_field || 'role';
    const statusField = settings.status_field || 'status';

    let html = `
        <div class="d-flex justify-content-between align-items-center mb-2 flex-wrap gap-2">
            <h6 class="mb-0">Users (table: ${escapeHtml(settings.users_table)})</h6>
            <div class="d-flex gap-2">
                <div class="input-group input-group-sm" style="width: 250px;">
                    <span class="input-group-text"><i class="bi bi-search"></i></span>
                    <input type="text" id="userSearchInput" class="form-control" placeholder="Search users...">
                </div>
                <button class="btn btn-sm btn-primary" id="btnAddUser"><i class="bi bi-plus"></i> Add User</button>
            </div>
        </div>
        <div class="table-responsive">
            <table class="table table-sm table-bordered small align-middle" id="usersTable">
                <thead class="table-light">
                    <tr>
                        <th>ID</th>
                        <th>${escapeHtml(usernameField)}</th>
                        <th>${escapeHtml(emailField)}</th>
                        <th>${escapeHtml(fullnameField)}</th>
                        <th>${escapeHtml(roleField)}</th>
                        <th>${escapeHtml(statusField)}</th>
                        <th>Groups</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody id="usersTableBody">
    `;
    for (let i = 0; i < users.length; i++) {
        const u = users[i];
        const groupNames = userGroupsMap[u.id] || [];
        let badges = '';
        for (let j = 0; j < groupNames.length; j++) {
            badges += `<span class="badge bg-secondary me-1 mb-1">${escapeHtml(groupNames[j])}</span>`;
        }
        if (badges === '') badges = '<span class="text-muted small">—</span>';
        html += `
            <tr>
                <td>${u.id}</td>
                <td>${escapeHtml(u[usernameField] || '')}</td>
                <td>${escapeHtml(u[emailField] || '')}</td>
                <td>${escapeHtml(u[fullnameField] || '')}</td>
                <td><span class="secusr-role">${escapeHtml(u[roleField] || 'user')}</span></td>
                <td>${secUserStatusPill(u[statusField] || 'active')}</td>
                <td style="max-width: 200px;">${badges}</td>
                <td class="text-nowrap">
                    <button class="btn btn-sm btn-outline-secondary assign-groups-btn" data-id="${u.id}" title="Assign Groups"><i class="bi bi-tag"></i></button>
                    <button class="btn btn-sm btn-outline-primary edit-user-btn" data-id="${u.id}"><i class="bi bi-pencil"></i></button>
                    <button class="btn btn-sm btn-outline-danger delete-user-btn" data-id="${u.id}"><i class="bi bi-trash"></i></button>
                </td>
            </tr>
        `;
    }
    html += `
                </tbody>
            </table>
        </div>
    `;
    container.innerHTML = html;

    // Search filter
    const searchInput = document.getElementById('userSearchInput');
    const tableBody = document.getElementById('usersTableBody');
    if (searchInput && tableBody) {
        const filterRows = () => {
            const term = searchInput.value.toLowerCase().trim();
            const rows = tableBody.querySelectorAll('tr');
            rows.forEach(row => {
                const textContent = row.innerText.toLowerCase();
                row.style.display = (term === '' || textContent.includes(term)) ? '' : 'none';
            });
        };
        searchInput.addEventListener('input', filterRows);
    }

    // Attach event listeners
    document.getElementById('btnAddUser')?.addEventListener('click', () => openUserModal());
    document.querySelectorAll('.edit-user-btn').forEach(btn => btn.addEventListener('click', () => openUserModal(btn.dataset.id)));
    document.querySelectorAll('.delete-user-btn').forEach(btn => btn.addEventListener('click', async () => {
        if (await pp.dialog.confirm('Delete user?', 'Are you sure?')) {
            const res = await fetch(`${baseUrl}/project/${projectSlug}/security/users/${btn.dataset.id}`, { method: 'DELETE' });
            const data = await res.json();
            if (data.success) {
                pp.dialog.toast('success', data.message);
                renderUsers();
            } else {
                pp.dialog.alert('Error', data.message, 'error');
            }
        }
    }));
    document.querySelectorAll('.assign-groups-btn').forEach(btn => btn.addEventListener('click', () => {
        const userId = btn.dataset.id;
        console.log('Assign groups clicked for user ID:', userId);
        openGroupAssignmentModal(userId);
    }));
}

async function openUserModal(userId = null) {
    let user = null;
    if (userId) user = window.securityData.users.find(u => u.id == userId);

    const settings = window.securitySettings;
    const usernameField = settings.username_field || 'username';
    const emailField = settings.email_field || 'email';
    const fullnameField = settings.fullname_field || 'fullname';
    const roleField = settings.role_field || 'role';
    const statusField = settings.status_field || 'status';

    // Role and status come from the server (the actual project roles + the
    // status column's enum), never a hardcoded list — that is what used to
    // silently reset an unlisted value on edit.
    const roles = window.securityData.userRoles || ['user'];
    const statuses = window.securityData.userStatuses || ['active', 'pending', 'inactive', 'banned'];
    const currentRole = user ? String(user[roleField] ?? '') : (roles.includes('user') ? 'user' : roles[0]);
    const currentStatus = user ? String(user[statusField] ?? '') : (statuses.includes('active') ? 'active' : statuses[0]);
    // If a stored value is not among the options (e.g. a legacy role), keep it
    // as a selectable option so saving cannot quietly change it.
    const roleOpts = [...new Set([currentRole, ...roles].filter(Boolean))];
    const statusOpts = [...new Set([currentStatus, ...statuses].filter(Boolean))];

    const statusMeta = {
        active:   { label: 'Active',   hint: 'Can sign in' },
        pending:  { label: 'Pending',  hint: 'Awaiting activation — cannot sign in yet' },
        inactive: { label: 'Inactive', hint: 'Temporarily disabled' },
        banned:   { label: 'Banned',   hint: 'Blocked from signing in' }
    };
    const title = key => (statusMeta[key]?.label) || (key.charAt(0).toUpperCase() + key.slice(1));

    const opt = (v, sel, label) => `<option value="${escapeHtml(v)}" ${v === sel ? 'selected' : ''}>${escapeHtml(label)}</option>`;

    const { value: submit } = await Swal.fire({
        title: userId ? 'Edit user' : 'Add user',
        width: 540,
        customClass: { popup: 'secusr-modal' },
        html: `
            <div class="secusr-form">
                <div class="secusr-grid">
                    <label class="secusr-field">
                        <span>${escapeHtml(usernameField)} <em>*</em></span>
                        <input id="suUsername" type="text" autocomplete="off" value="${user ? escapeHtml(user[usernameField] ?? '') : ''}">
                    </label>
                    <label class="secusr-field">
                        <span>${escapeHtml(emailField)} <em>*</em></span>
                        <input id="suEmail" type="email" autocomplete="off" value="${user ? escapeHtml(user[emailField] ?? '') : ''}">
                    </label>
                    <label class="secusr-field secusr-wide">
                        <span>${escapeHtml(fullnameField)}</span>
                        <input id="suFullname" type="text" autocomplete="off" value="${user ? escapeHtml(user[fullnameField] ?? '') : ''}">
                    </label>
                    <label class="secusr-field">
                        <span>${escapeHtml(roleField)}</span>
                        <select id="suRole">${roleOpts.map(r => opt(r, currentRole, r)).join('')}</select>
                    </label>
                    <label class="secusr-field">
                        <span>${escapeHtml(statusField)}</span>
                        <select id="suStatus">${statusOpts.map(st => opt(st, currentStatus, title(st))).join('')}</select>
                    </label>
                    <label class="secusr-field secusr-wide">
                        <span>Password ${userId ? '' : '<em>*</em>'}</span>
                        <input id="suPassword" type="password" autocomplete="new-password"
                               placeholder="${userId ? 'Leave blank to keep the current password' : 'Set a password'}">
                    </label>
                </div>
                <p class="secusr-status-hint" id="suStatusHint"></p>
            </div>`,
        didOpen: () => {
            const sel = document.getElementById('suStatus');
            const hint = document.getElementById('suStatusHint');
            const paint = () => {
                const m = statusMeta[sel.value];
                hint.innerHTML = m ? `<i class="bi bi-info-circle"></i> ${m.hint}` : '';
            };
            sel.addEventListener('change', paint); paint();
            document.getElementById('suUsername').focus();
        },
        focusConfirm: false,
        showCancelButton: true,
        confirmButtonText: userId ? 'Save changes' : 'Create user',
        preConfirm: () => {
            const v = id => document.getElementById(id).value.trim();
            const data = {
                id: userId,
                username: v('suUsername'),
                email: v('suEmail'),
                fullname: v('suFullname'),
                role: document.getElementById('suRole').value,
                status: document.getElementById('suStatus').value,
                password: document.getElementById('suPassword').value
            };
            if (!data.username || !data.email) return Swal.showValidationMessage('Username and email are required.');
            if (!userId && !data.password) return Swal.showValidationMessage('A password is required for a new user.');
            return data;
        }
    });
    if (!submit) return;

    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/security/users`, {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(submit)
        });
        const data = await res.json();
        if (data.success) {
            pp.dialog.toast('success', data.message);
            renderUsers();
        } else {
            pp.dialog.alert('Could not save user', data.message, 'error');
        }
    } catch (e) { pp.dialog.toast('error', 'Network error'); }
}

async function openGroupAssignmentModal(userId) {
    console.log('openGroupAssignmentModal called for userId:', userId);
    let assignments = [];
    let groups = [];
    try {
        const [assignRes, groupsRes] = await Promise.all([
            fetch(`${baseUrl}/project/${projectSlug}/security/user-groups`),
            fetch(`${baseUrl}/project/${projectSlug}/security/groups`)
        ]);
        const assignData = await assignRes.json();
        const groupsData = await groupsRes.json();

        console.log('Assignments response:', assignData);
        console.log('Groups response:', groupsData);

        // Safe extraction
        if (assignData.success && Array.isArray(assignData.assignments)) {
            assignments = assignData.assignments.filter(a => a.user_id == userId).map(a => a.group_id);
        } else {
            assignments = [];
            console.warn('No valid assignments array received');
        }

        if (groupsData.success && Array.isArray(groupsData.groups)) {
            groups = groupsData.groups;
        } else {
            groups = [];
            console.warn('No valid groups array received');
        }
    } catch (e) {
        console.error('Error loading group data:', e);
        pp.dialog.alert('Error', 'Failed to load group data. See console for details.', 'error');
        return;
    }

    if (groups.length === 0) {
        pp.dialog.alert('No Groups', 'No groups have been created yet. Please create groups first.', 'info');
        return;
    }

    // Build checkbox list
    let groupHtml = '<div style="max-height: 400px; overflow-y: auto; column-count: 2; column-gap: 20px;">';
    for (let i = 0; i < groups.length; i++) {
        const g = groups[i];
        const checked = assignments.includes(g.id) ? 'checked' : '';
        groupHtml += `
            <div class="form-check" style="break-inside: avoid; margin-bottom: 8px; display: flex; align-items: center;">
                <input class="form-check-input" type="checkbox" value="${g.id}" id="group_${g.id}" ${checked} style="margin-right: 6px;">
                <label class="form-check-label" for="group_${g.id}" style="margin: 0;">${escapeHtml(g.name)}</label>
            </div>
        `;
    }
    groupHtml += '</div>';

    const { value: selected } = await Swal.fire({
        title: 'Assign Groups for User ID ' + userId,
        html: groupHtml,
        preConfirm: () => {
            const checkedBoxes = document.querySelectorAll('#swal2-html-container input[type="checkbox"]:checked');
            const selectedIds = Array.from(checkedBoxes).map(cb => parseInt(cb.value, 10));
            console.log('Selected group IDs:', selectedIds);
            return selectedIds;
        },
        showCancelButton: true,
        width: '600px'
    });

    if (selected !== undefined) {
        try {
            const res = await fetch(`${baseUrl}/project/${projectSlug}/security/user-groups`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ user_id: userId, group_ids: selected })
            });
            const data = await res.json();
            if (data.success) {
                pp.dialog.toast('success', data.message || 'Group assignments saved.');
                renderUsers(); // refresh table to update badges
            } else {
                pp.dialog.alert('Error', data.message || 'Failed to save assignments.', 'error');
            }
        } catch (e) {
            console.error('Save error:', e);
            pp.dialog.toast('error', 'Network error while saving.');
        }
    }
}

window.renderUsers = renderUsers;