// ── Permissions (Security → Permissions) ────────────────────────────────────
// Chooses the authorization strategy for the GENERATED app and, for Static
// mode, edits per-group table permissions that are compiled into the build and
// enforced by core/Auth/Permissions.

const SECPERM_ACTIONS = [
    { key: 'view',   label: 'List/View', col: 'perm_view' },
    { key: 'add',    label: 'Add',       col: 'perm_add' },
    { key: 'edit',   label: 'Edit',      col: 'perm_edit' },
    { key: 'delete', label: 'Delete',    col: 'perm_delete' },
    { key: 'export', label: 'Export/Print', col: 'perm_export' },
    { key: 'import', label: 'Import',    col: 'perm_import' }
];

async function renderPermissions() {
    const container = document.getElementById('securityPageContainer');
    if (!container) return;
    if (!window.securitySettings?.db_auth_enabled) {
        container.innerHTML = `<div class="secdb-empty"><i class="bi bi-shield-lock"></i>
            <strong>Database authentication is off</strong>
            <span>Enable it under Settings → Database before configuring permissions.</span></div>`;
        return;
    }
    container.innerHTML = '<div class="text-center py-5"><div class="spinner-border"></div></div>';

    let data;
    try {
        data = await (await fetch(`${baseUrl}/project/${projectSlug}/security/permissions`)).json();
        if (!data.success) throw new Error(data.message || 'Unable to load permissions.');
    } catch (e) {
        container.innerHTML = `<div class="secdb-empty"><i class="bi bi-exclamation-triangle"></i>
            <strong>Could not load permissions</strong><span>${escapeHtml(e.message)}</span></div>`;
        return;
    }

    window.updateSecurityChrome?.('permissions');
    let mode = ['off', 'static', 'dynamic'].includes(data.mode) ? data.mode : 'off';
    const tables = Array.isArray(data.tables) ? data.tables : [];
    const groups = Array.isArray(data.groups) ? data.groups : [];

    // perm[groupId][table] = {view,add,edit,delete,export,import}
    const perm = {};
    groups.forEach(g => { perm[g.id] = {}; });
    (data.groupPermissions || []).forEach(p => {
        (perm[p.group_id] = perm[p.group_id] || {})[p.table_name] = {
            view: !!+p.perm_view, add: !!+p.perm_add, edit: !!+p.perm_edit,
            delete: !!+p.perm_delete, export: !!+p.perm_export, import: !!+p.perm_import
        };
    });
    const cell = (gid, table, key) => !!(perm[gid]?.[table]?.[key]);
    const setCell = (gid, table, key, v) => {
        (perm[gid] = perm[gid] || {});
        (perm[gid][table] = perm[gid][table] || {})[key] = v;
    };

    let activeGroupId = groups[0]?.id ?? null;

    container.innerHTML = `
        <div class="secdb" style="gap:12px">
            <div class="secdb-master ${mode !== 'off' ? 'is-on' : ''}" id="secpermMaster">
                <span class="secdb-master-icon"><i class="bi bi-shield-check"></i></span>
                <div class="secdb-master-copy">
                    <strong>Permission mode</strong>
                    <p>How the generated app decides who may view, add, edit, delete, export or import each table.</p>
                </div>
                <select class="form-select form-select-sm" id="secpermMode" style="max-width:230px">
                    <option value="off"     ${mode === 'off' ? 'selected' : ''}>Off — everyone signed in</option>
                    <option value="static"  ${mode === 'static' ? 'selected' : ''}>Static — set here, baked in</option>
                    <option value="dynamic" ${mode === 'dynamic' ? 'selected' : ''}>Dynamic — managed in the app</option>
                </select>
            </div>

            <div id="secpermModeHint"></div>
            <div id="secpermBody"></div>
        </div>`;

    const modeHint = () => {
        const host = document.getElementById('secpermModeHint');
        const map = {
            off: `<span><i class="bi bi-info-circle"></i> No enforcement — any signed-in user can reach every page. This is the historical behaviour.</span>`,
            static: `<span><i class="bi bi-lock"></i> You set each group's table permissions below; they are compiled into the build and cannot be changed without rebuilding. <strong>Unchecked = denied.</strong> Admin groups always have full access.</span>`,
            dynamic: `<span><i class="bi bi-people"></i> The generated app creates the permission tables and provides its own admin screen, so your customer manages groups and permissions live — no rebuild needed. There is nothing to set here.</span>`
        };
        host.innerHTML = `<div class="secdb-empty" style="padding:12px;text-align:left;flex-direction:row;gap:8px;align-items:flex-start">${map[mode]}</div>`;
    };

    function renderBody() {
        const body = document.getElementById('secpermBody');
        if (mode !== 'static') { body.innerHTML = ''; return; }
        if (groups.length === 0) {
            body.innerHTML = `<div class="secdb-empty"><i class="bi bi-people"></i>
                <strong>No groups yet</strong>
                <span>Create groups under Users &amp; Groups → Groups, then assign users to them.</span></div>`;
            return;
        }
        body.innerHTML = `
            <div class="secperm">
                <div class="secperm-groups" id="secpermGroups"></div>
                <div class="secperm-panel">
                    <div class="secperm-toolbar">
                        <div class="secdb-field" style="flex:1;max-width:280px">
                            <input class="form-control form-control-sm" id="secpermSearch" placeholder="Filter tables…" spellcheck="false">
                        </div>
                        <div class="secperm-toolbar-actions" id="secpermGroupActions"></div>
                    </div>
                    <div class="secperm-matrix-wrap"><table class="secperm-matrix" id="secpermMatrix"></table></div>
                </div>
            </div>
            <div class="secdb-foot">
                <div class="secdb-summary" id="secpermSummary"></div>
                <button class="btn btn-primary btn-sm" id="secpermSave"><i class="bi bi-save me-1"></i> Save permissions</button>
            </div>`;
        renderGroupTabs();
        renderGroupActions();
        renderMatrix('');
        document.getElementById('secpermSearch').addEventListener('input', e => renderMatrix(e.target.value.trim()));
        document.getElementById('secpermSave').addEventListener('click', savePermissions);
    }

    function renderGroupTabs() {
        const host = document.getElementById('secpermGroups');
        host.innerHTML = groups.map(g => `
            <button type="button" class="secperm-group ${g.id === activeGroupId ? 'is-active' : ''}" data-gid="${g.id}">
                <span class="secperm-group-name">${escapeHtml(g.name)}</span>
                ${g.is_admin_group ? '<span class="secperm-badge">admin</span>' : ''}
            </button>`).join('');
        host.querySelectorAll('.secperm-group').forEach(b => b.addEventListener('click', () => {
            activeGroupId = parseInt(b.dataset.gid, 10);
            renderGroupTabs(); renderGroupActions();
            renderMatrix(document.getElementById('secpermSearch').value.trim());
        }));
    }

    function activeGroup() { return groups.find(g => g.id === activeGroupId); }

    function renderGroupActions() {
        const host = document.getElementById('secpermGroupActions');
        const g = activeGroup();
        if (g?.is_admin_group) { host.innerHTML = ''; return; }
        const others = groups.filter(x => x.id !== activeGroupId);
        host.innerHTML = `
            <button type="button" class="btn btn-sm btn-outline-secondary" id="secpermGrantAll" title="Grant everything to this group"><i class="bi bi-check2-all"></i> Grant all</button>
            <button type="button" class="btn btn-sm btn-outline-secondary" id="secpermRevokeAll" title="Revoke everything from this group"><i class="bi bi-x-lg"></i> Revoke all</button>
            ${others.length ? `<div class="secperm-copy">
                <select class="form-select form-select-sm" id="secpermCopyFrom">
                    <option value="">Copy from…</option>
                    ${others.map(o => `<option value="${o.id}">${escapeHtml(o.name)}</option>`).join('')}
                </select></div>` : ''}`;
        document.getElementById('secpermGrantAll')?.addEventListener('click', () => bulkSet(true));
        document.getElementById('secpermRevokeAll')?.addEventListener('click', () => bulkSet(false));
        document.getElementById('secpermCopyFrom')?.addEventListener('change', e => {
            const from = parseInt(e.target.value, 10);
            if (!from) return;
            tables.forEach(t => SECPERM_ACTIONS.forEach(a => setCell(activeGroupId, t, a.key, cell(from, t, a.key))));
            renderMatrix(document.getElementById('secpermSearch').value.trim());
            refreshSummary();
            e.target.value = '';
        });
    }

    function bulkSet(v) {
        tables.forEach(t => SECPERM_ACTIONS.forEach(a => setCell(activeGroupId, t, a.key, v)));
        renderMatrix(document.getElementById('secpermSearch').value.trim());
        refreshSummary();
    }

    function renderMatrix(filter) {
        const g = activeGroup();
        const el = document.getElementById('secpermMatrix');
        if (g?.is_admin_group) {
            el.innerHTML = `<tbody><tr><td class="secperm-admin-note">
                <i class="bi bi-shield-fill-check"></i> <strong>${escapeHtml(g.name)}</strong> is an administrator group —
                it always has full access to every table. Uncheck “Administrator group” in Users &amp; Groups to make it restrictable.
            </td></tr></tbody>`;
            return;
        }
        const shown = filter ? tables.filter(t => t.toLowerCase().includes(filter.toLowerCase())) : tables;
        const head = `<thead><tr><th class="secperm-th-table">Table</th>${SECPERM_ACTIONS.map(a =>
            `<th class="secperm-th-act"><span>${a.label}</span>
             <input type="checkbox" class="secperm-colall" data-act="${a.key}" title="Toggle ${a.label} for every table"></th>`).join('')}</tr></thead>`;
        const rows = shown.length ? shown.map(t => `
            <tr data-table="${escapeHtml(t)}">
                <td class="secperm-td-table">${escapeHtml(t)}
                    <button type="button" class="secperm-rowall" data-table="${escapeHtml(t)}" title="Toggle all for this table"><i class="bi bi-check2-square"></i></button>
                </td>
                ${SECPERM_ACTIONS.map(a => `<td class="secperm-td-act">
                    <input type="checkbox" class="secperm-cb" data-table="${escapeHtml(t)}" data-act="${a.key}" ${cell(activeGroupId, t, a.key) ? 'checked' : ''}>
                </td>`).join('')}
            </tr>`).join('') : `<tr><td colspan="${SECPERM_ACTIONS.length + 1}" class="secperm-empty">No matching tables.</td></tr>`;
        el.innerHTML = head + '<tbody>' + rows + '</tbody>';

        el.querySelectorAll('.secperm-cb').forEach(cb => cb.addEventListener('change', () => {
            setCell(activeGroupId, cb.dataset.table, cb.dataset.act, cb.checked);
            syncColHeader(cb.dataset.act); refreshSummary();
        }));
        el.querySelectorAll('.secperm-colall').forEach(h => {
            syncColHeader(h.dataset.act);
            h.addEventListener('change', () => {
                shown.forEach(t => setCell(activeGroupId, t, h.dataset.act, h.checked));
                renderMatrix(filter); refreshSummary();
            });
        });
        el.querySelectorAll('.secperm-rowall').forEach(b => b.addEventListener('click', () => {
            const t = b.dataset.table;
            const allOn = SECPERM_ACTIONS.every(a => cell(activeGroupId, t, a.key));
            SECPERM_ACTIONS.forEach(a => setCell(activeGroupId, t, a.key, !allOn));
            renderMatrix(filter); refreshSummary();
        }));
        refreshSummary();
    }

    function syncColHeader(act) {
        const header = document.querySelector(`.secperm-colall[data-act="${act}"]`);
        if (!header) return;
        const boxes = [...document.querySelectorAll(`.secperm-cb[data-act="${act}"]`)];
        const on = boxes.filter(b => b.checked).length;
        header.checked = boxes.length > 0 && on === boxes.length;
        header.indeterminate = on > 0 && on < boxes.length;
    }

    function refreshSummary() {
        const host = document.getElementById('secpermSummary');
        if (!host) return;
        const parts = groups.map(g => {
            if (g.is_admin_group) return `<span class="secdb-pill is-ok"><i class="bi bi-shield-fill-check"></i> ${escapeHtml(g.name)}: full</span>`;
            let granted = 0;
            tables.forEach(t => SECPERM_ACTIONS.forEach(a => { if (cell(g.id, t, a.key)) granted++; }));
            const cls = granted ? '' : 'is-warn';
            return `<span class="secdb-pill ${cls}"><i class="bi bi-key"></i> ${escapeHtml(g.name)}: ${granted}</span>`;
        });
        host.innerHTML = parts.join('');
    }

    async function savePermissions() {
        const payload = [];
        groups.forEach(g => {
            if (g.is_admin_group) return;   // admin groups aren't stored as rows
            tables.forEach(t => {
                const c = perm[g.id]?.[t] || {};
                payload.push({
                    group_id: g.id, table_name: t,
                    perm_view: c.view ? 1 : 0, perm_add: c.add ? 1 : 0, perm_edit: c.edit ? 1 : 0,
                    perm_delete: c.delete ? 1 : 0, perm_export: c.export ? 1 : 0, perm_import: c.import ? 1 : 0,
                    perm_admin: 0
                });
            });
        });
        try {
            const res = await fetch(`${baseUrl}/project/${projectSlug}/security/group-permissions`, {
                method: 'POST', headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ permissions: payload })
            });
            const d = await res.json();
            if (!d.success) return pp.dialog.alert('Error', d.message, 'error');
            pp.dialog.toast('success', 'Permissions saved. Rebuild the app to publish them.');
        } catch (e) { pp.dialog.toast('error', 'Network error'); }
    }

    document.getElementById('secpermMode').addEventListener('change', async function () {
        const next = this.value;
        try {
            const res = await fetch(`${baseUrl}/project/${projectSlug}/security/permission-mode`, {
                method: 'POST', headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ mode: next })
            });
            const d = await res.json();
            if (!d.success) { this.value = mode; return pp.dialog.alert('Error', d.message, 'error'); }
            mode = next;
            document.getElementById('secpermMaster').classList.toggle('is-on', mode !== 'off');
            modeHint(); renderBody();
            pp.dialog.toast('success', d.message);
        } catch (e) { this.value = mode; pp.dialog.toast('error', 'Network error'); }
    });

    modeHint();
    renderBody();
}

window.renderPermissions = renderPermissions;
