// ── All Modal Handlers (Key Columns, Page Settings, Click Actions) ───
function openKeyColumnsModal() {
    const body = document.getElementById('keyColumnsBody');
    const tableName = currentTableName;
    if (!tableFieldCache[tableName]) {
        fetch(`${baseUrl}/project/${projectSlug}/tables/details/${tableName}`)
            .then(res => res.json())
            .then(data => { if (data.success) { tableFieldCache[tableName] = data.columns; fillKeyColumnsBody(data.columns); } });
    } else {
        fillKeyColumnsBody(tableFieldCache[tableName]);
    }
    bootstrap.Modal.getOrCreateInstance(document.getElementById('keyColumnsModal')).show();
    initializePageTooltips(document.getElementById('keyColumnsModal'));
}

function openPageSettingsModal(pageType) {
    document.getElementById('pageSettingsTitle').textContent = pageType.charAt(0).toUpperCase() + pageType.slice(1) + ' Settings';
    // Stash the canonical type on the modal so the save handler never has to
    // reverse-parse the (translatable) title text to recover it.
    document.getElementById('pageSettingsModal').dataset.pageType = pageType;
    const body = document.getElementById('pageSettingsBody');
    const settings = (currentConfig && currentConfig.settings && currentConfig.settings[pageType]) || {};

    if (pageType === 'list') {
        clickActions = (currentConfig.settings?.list?.clickActions || []).slice();
        body.innerHTML = `
            <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="listScrollTable" ${settings.scrollTable ? 'checked' : ''}><label class="form-check-label" for="listScrollTable">Scroll table data (fixed header)</label></div>
            <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="listReorderFields" ${settings.reorderFields ? 'checked' : ''}><label class="form-check-label" for="listReorderFields">Allow reordering of fields on the page</label></div>
            <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="listResizableColumns" ${settings.resizableColumns ? 'checked' : ''}><label class="form-check-label" for="listResizableColumns">Resizeable table columns</label></div>
            <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="listPinColumns" ${settings.pinColumns ? 'checked' : ''}><label class="form-check-label" for="listPinColumns">Freeze / pin columns <span class="text-muted">— a pin toggle appears in each header (frozen while scrolling)</span></label></div>
            <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="listSavedViews" ${settings.savedViews ? 'checked' : ''}><label class="form-check-label" for="listSavedViews">Saved views <span class="text-muted">— users save named presets of search, sort, filters &amp; columns</span></label></div>
            <hr class="my-2">
            <label class="form-label small mb-2 fw-bold">Group rows by a column</label>
            <select class="form-select form-select-sm mb-2" id="listGroupBy"><option value="">No grouping</option></select>
            <label class="form-label small mb-2 fw-bold">Board (Kanban) — group cards by</label>
            <select class="form-select form-select-sm mb-1" id="listKanbanField"><option value="">Disabled</option></select>
            <p class="text-muted small mb-2">Adds a Board view toggle; drag a card between columns to change this field.</p>
            <hr class="my-2">
            <label class="form-label small mb-2 fw-bold">Click Actions</label>
            <div id="clickActionsTableContainer" class="small"></div>
            <button class="btn btn-sm btn-outline-primary mt-1" id="btnAddClickAction" title="Add an action that runs when a row or field is clicked"><i class="bi bi-plus"></i> Add Click Action</button>
        `;
        // Populate the Group By + Kanban-field dropdowns from the table columns.
        const fillColSelects = (columns) => {
            const gsel = document.getElementById('listGroupBy'), ksel = document.getElementById('listKanbanField');
            const savedG = (currentConfig.settings?.list?.groupBy) || '';
            const savedK = (currentConfig.settings?.list?.kanbanField) || '';
            columns.forEach(col => {
                const n = escapePageHtml(col.COLUMN_NAME);
                if (gsel) gsel.innerHTML += `<option value="${n}" ${col.COLUMN_NAME === savedG ? 'selected' : ''}>${n}</option>`;
                if (ksel) ksel.innerHTML += `<option value="${n}" ${col.COLUMN_NAME === savedK ? 'selected' : ''}>${n}</option>`;
            });
        };
        if (tableFieldCache[currentTableName]) fillColSelects(tableFieldCache[currentTableName]);
        else fetch(`${baseUrl}/project/${projectSlug}/tables/details/${currentTableName}`).then(r => r.json())
            .then(d => { if (d.success) { tableFieldCache[currentTableName] = d.columns; fillColSelects(d.columns); } });
    } else if (pageType === 'add') {
        const afterAdd = settings.afterAdd || 'list';
        body.innerHTML = `
            <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="addShowInPopup" ${settings.showInPopup ? 'checked' : ''}><label class="form-check-label" for="addShowInPopup">Show Add page in popup</label></div>
            <label class="form-label small mt-2 mb-1">After record is added:</label>
            <select class="form-select form-select-sm" id="addAfterAction"><option value="list" ${afterAdd === 'list' ? 'selected' : ''}>Return to list page</option><option value="next" ${afterAdd === 'next' ? 'selected' : ''}>Add next record – stay on Add page</option><option value="edit" ${afterAdd === 'edit' ? 'selected' : ''}>Open edit page</option><option value="view" ${afterAdd === 'view' ? 'selected' : ''}>Open view page</option></select>
            <div class="form-check small mt-2"><input class="form-check-input" type="checkbox" id="addClosePopup" ${settings.closePopup ? 'checked' : ''}><label class="form-check-label" for="addClosePopup">Just close after adding in Popup Mode</label></div>
        `;
    } else if (pageType === 'edit') {
        const afterEdit = settings.afterEdit || 'list';
        body.innerHTML = `
            <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="editShowInPopup" ${settings.showInPopup ? 'checked' : ''}><label class="form-check-label" for="editShowInPopup">Show Edit page in popup</label></div>
            <label class="form-label small mt-2 mb-1">After record is updated:</label>
            <select class="form-select form-select-sm" id="editAfterAction"><option value="list" ${afterEdit === 'list' ? 'selected' : ''}>Return to list page</option><option value="stay" ${afterEdit === 'stay' ? 'selected' : ''}>Stay on Edit page</option><option value="view" ${afterEdit === 'view' ? 'selected' : ''}>Go to the View page</option><option value="next" ${afterEdit === 'next' ? 'selected' : ''}>Edit next record</option><option value="previous" ${afterEdit === 'previous' ? 'selected' : ''}>Edit previous record</option></select>
            <div class="form-check small mt-2"><input class="form-check-input" type="checkbox" id="editClosePopup" ${settings.closePopup ? 'checked' : ''}><label class="form-check-label" for="editClosePopup">Just close after updating in Popup Mode</label></div>
        `;
    } else if (pageType === 'view') {
        // SEO settings (features A1/A2/A4) live with the View page since that is
        // the crawlable record page. Stored at settings.view.seo; the build turns
        // it into slug URLs + per-record meta + a sitemap entry.
        const seo = settings.seo || {};
        const esc = s => escapePageHtml(String(s == null ? '' : s));
        const freqOpts = ['', 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'].map(function (f) {
            return '<option value="' + f + '"' + (seo.changefreq === f ? ' selected' : '') + '>' + (f || '—') + '</option>';
        }).join('');
        body.innerHTML = `
            <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="viewShowInPopup" ${settings.showInPopup ? 'checked' : ''}><label class="form-check-label" for="viewShowInPopup">Show View page in popup</label></div>
            <div class="form-check small"><input class="form-check-input" type="checkbox" id="viewHideEmpty" ${settings.hideEmptyFields ? 'checked' : ''}><label class="form-check-label" for="viewHideEmpty">Hide empty fields</label></div>
            <hr class="my-2">
            <div class="form-check small mb-2"><input class="form-check-input" type="checkbox" id="seoEnabled" ${seo.enabled ? 'checked' : ''}><label class="form-check-label fw-bold" for="seoEnabled">SEO-friendly URL &amp; meta for this record page</label></div>
            <div id="seoFields" class="row g-2" style="${seo.enabled ? '' : 'opacity:.5'}">
              <div class="col-12"><div class="form-check small"><input class="form-check-input" type="checkbox" id="seoPublicRead" ${seo.public_read ? 'checked' : ''}><label class="form-check-label" for="seoPublicRead">Publicly readable (no login) — list &amp; view open to anyone; write actions still require login</label></div></div>
              <div class="col-6"><label class="form-label small mb-1">URL prefix</label><input class="form-control form-control-sm" id="seoPrefix" value="${esc(seo.prefix)}" placeholder="q"></div>
              <div class="col-6"><label class="form-label small mb-1">Slug column</label><input class="form-control form-control-sm" id="seoSlugCol" value="${esc(seo.slug_column)}" placeholder="slug"></div>
              <div class="col-6"><label class="form-label small mb-1">Title column</label><input class="form-control form-control-sm" id="seoTitleCol" value="${esc(seo.title_column)}" placeholder="title"></div>
              <div class="col-6"><label class="form-label small mb-1">Last-modified column</label><input class="form-control form-control-sm" id="seoLastmod" value="${esc(seo.lastmod_column)}" placeholder="updated_at"></div>
              <div class="col-12"><label class="form-label small mb-1">Title template <span class="text-muted">— {column} placeholders</span></label><input class="form-control form-control-sm" id="seoTitleTpl" value="${esc(seo.title_template)}" placeholder="{title} — My Community"></div>
              <div class="col-6"><label class="form-label small mb-1">Description column</label><input class="form-control form-control-sm" id="seoDescField" value="${esc(seo.description_field)}" placeholder="body"></div>
              <div class="col-6"><label class="form-label small mb-1">OG image column</label><input class="form-control form-control-sm" id="seoOgField" value="${esc(seo.og_image_field)}"></div>
              <div class="col-12"><label class="form-label small mb-1">Default OG image URL</label><input class="form-control form-control-sm" id="seoOgDefault" value="${esc(seo.og_image_default)}" placeholder="https://…/og.png"></div>
              <div class="col-4"><label class="form-label small mb-1">Robots</label><select class="form-select form-select-sm" id="seoRobots"><option value="index" ${seo.robots !== 'noindex' ? 'selected' : ''}>Index</option><option value="noindex" ${seo.robots === 'noindex' ? 'selected' : ''}>No-index</option></select></div>
              <div class="col-4"><label class="form-label small mb-1">Change freq</label><select class="form-select form-select-sm" id="seoFreq">${freqOpts}</select></div>
              <div class="col-4"><label class="form-label small mb-1">Priority</label><input class="form-control form-control-sm" id="seoPriority" type="number" min="0" max="1" step="0.1" value="${esc(seo.priority)}" placeholder="0.7"></div>
              <div class="col-12 form-text small mt-0">Serves this page at <code>/&lt;prefix&gt;/&lt;id&gt;/&lt;slug&gt;</code> with per-record title, description, canonical, Open Graph, and a sitemap entry.</div>
            </div>
        `;
        document.getElementById('seoEnabled')?.addEventListener('change', function (e) {
            document.getElementById('seoFields').style.opacity = e.target.checked ? '1' : '.5';
        });
    } else if (pageType === 'pdf') {
        // The PDF is built from one source layout — the Print page or the View
        // page — so these are mutually exclusive (radio, not checkbox). Derive the
        // selection from the new `source` field, falling back to older booleans.
        const pdfSource = settings.source || (settings.viewPage && !settings.printPage ? 'view' : 'print');
        body.innerHTML = `
            <label class="form-label small mb-1 fw-bold">Build the PDF from</label>
            <div class="form-check small mb-1"><input class="form-check-input" type="radio" name="pdfSource" id="pdfSourcePrint" value="print" ${pdfSource === 'print' ? 'checked' : ''}><label class="form-check-label" for="pdfSourcePrint">Print Page <span class="text-muted">— compact document layout</span></label></div>
            <div class="form-check small mb-2"><input class="form-check-input" type="radio" name="pdfSource" id="pdfSourceView" value="view" ${pdfSource === 'view' ? 'checked' : ''}><label class="form-check-label" for="pdfSourceView">View Page <span class="text-muted">— record card layout</span></label></div>
            <label class="form-label small mb-1">Orientation</label>
            <select class="form-select form-select-sm" id="pdfOrientation"><option value="portrait" ${settings.orientation !== 'landscape' ? 'selected' : ''}>Portrait</option><option value="landscape" ${settings.orientation === 'landscape' ? 'selected' : ''}>Landscape</option></select>
        `;
    } else if (pageType === 'export') {
        // Formats are listed by the DataOps registry. Legacy per-format booleans
        // (exportCsv/exportXlsx/exportDoc) are still honoured when no `formats`
        // list has been saved yet, so existing projects keep their selection.
        const legacyExport = { csv: 'exportCsv', xlsx: 'exportXlsx', word: 'exportDoc' };
        const chosen = Array.isArray(settings.formats)
            ? settings.formats
            : (ppFormats.exports || []).filter(f => {
                const k = legacyExport[f.id];
                return k ? (k === 'exportCsv' ? settings.exportCsv !== false : !!settings[k]) : false;
              }).map(f => f.id);
        body.innerHTML = `
            <label class="form-label small mb-1">Export Formats <span class="text-muted">— which downloads this page offers</span></label>
            ${(ppFormats.exports || []).map(f => `
              <div class="form-check small"><input class="form-check-input pp-exp-fmt" type="checkbox" value="${f.id}" id="expFmt_${f.id}" ${chosen.includes(f.id) ? 'checked' : ''}>
              <label class="form-check-label" for="expFmt_${f.id}">${f.label} <span class="text-muted">.${f.extension}</span></label></div>`).join('')}
            <p class="text-muted small mt-2 mb-2"><i class="bi bi-shield-lock"></i> Clearing every format disables export for this table — the endpoint is not generated at all.</p>
            <hr class="my-2">
            <div class="form-check small"><input class="form-check-input" type="checkbox" id="expHeaders" ${settings.includeHeaders !== false ? 'checked' : ''}><label class="form-check-label" for="expHeaders">Include the header row</label></div>
        `;
    } else if (pageType === 'import') {
        const legacyReaders = ['importCsv', 'importXls', 'importTxt'];
        const chosenR = Array.isArray(settings.readers)
            ? settings.readers
            : (legacyReaders.some(k => settings[k]) || settings.importCsv !== false ? ['csv'] : []);
        const modes = Array.isArray(settings.modes) ? settings.modes : ['insert', 'skip', 'update'];
        const delim = settings.delimiter || 'auto';
        body.innerHTML = `
            <label class="form-label small mb-1">Import Sources <span class="text-muted">— file types accepted</span></label>
            ${(ppFormats.readers || []).map(r => `
              <div class="form-check small"><input class="form-check-input pp-imp-fmt" type="checkbox" value="${r.id}" id="impFmt_${r.id}" ${chosenR.includes(r.id) ? 'checked' : ''}>
              <label class="form-check-label" for="impFmt_${r.id}">${r.label} <span class="text-muted">${r.extensions.map(e => '.' + e).join(' ')}</span></label></div>`).join('')}
            <p class="text-muted small mt-2 mb-2"><i class="bi bi-shield-lock"></i> Clearing every source disables import for this table.</p>
            <hr class="my-2">
            <div class="row g-2">
              <div class="col-6"><label class="form-label small mb-1">Default delimiter</label>
                <select class="form-select form-select-sm" id="impDelim">
                  ${['auto', 'comma', 'semicolon', 'tab', 'pipe'].map(d => `<option value="${d}" ${delim === d ? 'selected' : ''}>${d === 'auto' ? 'Detect automatically' : d}</option>`).join('')}
                </select></div>
              <div class="col-6"><label class="form-label small mb-1">Max upload size (MB)</label>
                <input type="number" min="1" max="512" class="form-control form-control-sm" id="impMaxMb" value="${parseInt(settings.maxMb, 10) || 8}"></div>
            </div>
            <label class="form-label small mb-1 mt-2">Allowed import modes</label>
            <div class="d-flex gap-3 flex-wrap">
              ${[['insert', 'Insert'], ['skip', 'Skip existing'], ['update', 'Update existing']].map(([v, l]) => `
                <div class="form-check small"><input class="form-check-input pp-imp-mode" type="checkbox" value="${v}" id="impMode_${v}" ${modes.includes(v) ? 'checked' : ''}>
                <label class="form-check-label" for="impMode_${v}">${l}</label></div>`).join('')}
            </div>
            <hr class="my-2">
            <div class="form-check small"><input class="form-check-input" type="checkbox" id="impPaste" ${settings.allowPaste !== false ? 'checked' : ''}><label class="form-check-label" for="impPaste">Allow Copy / Paste source</label></div>
            <div class="form-check small"><input class="form-check-input" type="checkbox" id="impUpload" ${settings.allowUpload !== false ? 'checked' : ''}><label class="form-check-label" for="impUpload">Allow file upload</label></div>
            <div class="form-check small"><input class="form-check-input" type="checkbox" id="impHeaders" ${settings.hasHeaderDefault !== false ? 'checked' : ''}><label class="form-check-label" for="impHeaders">First row contains headers (default)</label></div>
            <div class="form-check small"><input class="form-check-input" type="checkbox" id="impValidate" ${settings.validateDefault ? 'checked' : ''}><label class="form-check-label" for="impValidate">Validate before import (default)</label></div>
        `;
    } else if (pageType === 'cards') {
        // Card Template — server-rendered card layout for the Cards view. Field
        // dropdowns/checkboxes are populated from the table's columns (fetched
        // if not cached); leaving everything blank falls back to an auto layout.
        body.innerHTML = `
            <p class="text-muted small mb-2">Design the card shown in the Cards view. Leave a field empty to skip it; leave everything blank for an automatic layout (first field = title, the rest = body).</p>
            <div class="row g-2">
                <div class="col-6"><label class="form-label small mb-1">Title field</label><select class="form-select form-select-sm" id="cardTitle"></select></div>
                <div class="col-6"><label class="form-label small mb-1">Subtitle field</label><select class="form-select form-select-sm" id="cardSubtitle"></select></div>
                <div class="col-6"><label class="form-label small mb-1">Image field <span class="text-muted">(URL/path)</span></label><select class="form-select form-select-sm" id="cardImage"></select></div>
                <div class="col-6"><label class="form-label small mb-1">Badge field</label><select class="form-select form-select-sm" id="cardBadge"></select></div>
            </div>
            <div id="cardBadgeColorsWrap" class="mt-2" style="display:none">
                <label class="form-label small mb-1 fw-bold">Badge colors <span class="text-muted fw-normal">— map a value to a color (blank value = default for all)</span></label>
                <div id="cardBadgeColors"></div>
                <button type="button" class="btn btn-sm btn-outline-secondary mt-1" id="btnAddBadgeColor"><i class="bi bi-plus"></i> Add color rule</button>
            </div>
            <hr class="my-2">
            <label class="form-label small mb-1 fw-bold">Body fields</label>
            <div id="cardBodyFields" class="pp-card-field-picker border rounded p-2" style="max-height:180px;overflow:auto">
                <span class="text-muted small">Loading columns…</span>
            </div>
            <hr class="my-2">
            <div class="row g-2 align-items-start">
                <div class="col-6">
                    <label class="form-label small mb-1">Cards per row</label>
                    <select class="form-select form-select-sm" id="cardPerRow">
                        <option value="0">Auto (responsive)</option>
                        <option value="1">1</option><option value="2">2</option>
                        <option value="3">3</option><option value="4">4</option>
                    </select>
                </div>
                <div class="col-6">
                    <div class="form-check small mb-1"><input class="form-check-input" type="checkbox" id="cardShowLabels" ${settings.showLabels !== false ? 'checked' : ''}><label class="form-check-label" for="cardShowLabels">Show field labels</label></div>
                    <div class="form-check small"><input class="form-check-input" type="checkbox" id="cardActions" ${settings.actions !== false ? 'checked' : ''}><label class="form-check-label" for="cardActions">Show action buttons</label></div>
                </div>
            </div>
        `;
        const applyCols = (columns) => fillCardTemplate(columns, settings);
        if (tableFieldCache[currentTableName]) {
            applyCols(tableFieldCache[currentTableName]);
        } else {
            fetch(`${baseUrl}/project/${projectSlug}/tables/details/${currentTableName}`)
                .then(res => res.json())
                .then(data => { if (data.success) { tableFieldCache[currentTableName] = data.columns; applyCols(data.columns); } });
        }
    }

    bootstrap.Modal.getOrCreateInstance(document.getElementById('pageSettingsModal')).show();
    if (pageType === 'list') renderClickActionsTable();
    initializePageTooltips(document.getElementById('pageSettingsModal'));
}

// Populate the Card Template modal's field pickers from the table columns and
// wire the badge-colors repeater. `c` is the saved settings.cards object.
function fillCardTemplate(columns, c) {
    c = c || {};
    const names = columns.map(col => col.COLUMN_NAME);
    const optionList = (selected) => '<option value="">— none —</option>' +
        names.map(n => `<option value="${escapePageHtml(n)}" ${n === selected ? 'selected' : ''}>${escapePageHtml(n)}</option>`).join('');
    const set = (id, val) => { const el = document.getElementById(id); if (el) el.innerHTML = optionList(val); };
    set('cardTitle', c.title || '');
    set('cardSubtitle', c.subtitle || '');
    set('cardImage', c.image || '');
    set('cardBadge', c.badge || '');

    // Body fields — checkbox list preserving the saved order first.
    const chosen = Array.isArray(c.body) ? c.body.filter(n => names.includes(n)) : [];
    const ordered = chosen.concat(names.filter(n => !chosen.includes(n)));
    const picker = document.getElementById('cardBodyFields');
    if (picker) {
        picker.innerHTML = ordered.map(n => `
            <div class="form-check small mb-0">
                <input class="form-check-input pp-card-body-cb" type="checkbox" id="cardBody_${escapePageHtml(n)}" value="${escapePageHtml(n)}" ${chosen.includes(n) ? 'checked' : ''}>
                <label class="form-check-label" for="cardBody_${escapePageHtml(n)}">${escapePageHtml(n)}</label>
            </div>`).join('');
    }

    const perRow = document.getElementById('cardPerRow');
    if (perRow) perRow.value = String(c.perRow || 0);

    // Badge colors repeater — shown only when a badge field is chosen.
    const badgeSel = document.getElementById('cardBadge');
    const wrap = document.getElementById('cardBadgeColorsWrap');
    const toggleBadge = () => { if (wrap) wrap.style.display = badgeSel && badgeSel.value ? 'block' : 'none'; };
    if (badgeSel) badgeSel.addEventListener('change', toggleBadge);
    const rows = document.getElementById('cardBadgeColors');
    if (rows) {
        rows.innerHTML = '';
        const colors = (c.badgeColors && typeof c.badgeColors === 'object') ? c.badgeColors : {};
        Object.keys(colors).forEach(k => addBadgeColorRow(k === '*' ? '' : k, colors[k]));
        if (Object.keys(colors).length === 0) addBadgeColorRow('', '#6366f1');
    }
    document.getElementById('btnAddBadgeColor')?.addEventListener('click', () => addBadgeColorRow('', '#6366f1'));
    toggleBadge();
}

function addBadgeColorRow(value, color) {
    const rows = document.getElementById('cardBadgeColors');
    if (!rows) return;
    const row = document.createElement('div');
    row.className = 'd-flex gap-1 mb-1 align-items-center pp-badge-color-row';
    row.innerHTML = `
        <input type="text" class="form-control form-control-sm pp-bc-value" placeholder="value (blank = default)" value="${escapePageHtml(value || '')}">
        <input type="color" class="form-control form-control-color form-control-sm pp-bc-color" value="${escapePageHtml(color || '#6366f1')}">
        <button type="button" class="btn btn-sm btn-outline-danger pp-bc-remove" title="Remove"><i class="bi bi-x"></i></button>`;
    row.querySelector('.pp-bc-remove').addEventListener('click', () => row.remove());
    rows.appendChild(row);
}

function openClickActionModal(index = -1) {
    document.getElementById('clickActionEditIndex').value = index;
    document.getElementById('clickActionTitle').textContent = index >= 0 ? 'Edit Click Action' : 'Add Click Action';
    const fieldSelect = document.getElementById('clickActionField');
    fieldSelect.innerHTML = '<option value="row">Row Click</option>';
    const tableName = currentTableName;
    const addFieldOpt = col => { const n = escapePageHtml(col.COLUMN_NAME); fieldSelect.innerHTML += `<option value="${n}">${n}</option>`; };
    if (tableFieldCache[tableName]) {
        tableFieldCache[tableName].forEach(addFieldOpt);
    } else {
        fetch(`${baseUrl}/project/${projectSlug}/tables/details/${tableName}`)
            .then(res => res.json())
            .then(data => { if (data.success) { tableFieldCache[tableName] = data.columns; data.columns.forEach(addFieldOpt); } });
    }
    const setVal = (id, v) => { const el = document.getElementById(id); if (el) el.value = v; };
    if (index >= 0) {
        const ca = clickActions[index];
        setVal('clickActionField', ca.field);
        setVal('clickActionType', ca.actionType);
        setVal('clickActionOn', ca.on || 'single');
        setVal('clickActionTarget', ca.target || 'view');
        setVal('clickActionUrl', ca.url || '');
        setVal('clickActionOpenIn', ca.openIn || 'current');
        setVal('clickActionConfirm', ca.confirm || '');
        setVal('clickActionOnlyWhen', ca.onlyWhen || '');
        setVal('clickActionRefresh', ca.refresh || 'none');
        setVal('clickActionClientBefore', ca.clientBefore || '');
        setVal('clickActionServer', ca.server || '');
        setVal('clickActionClientAfter', ca.clientAfter || '');
        syncClickActionUI(ca.actionType);
    } else {
        setVal('clickActionField', 'row');
        setVal('clickActionType', 'openPage');
        setVal('clickActionOn', 'single');
        setVal('clickActionTarget', 'view');
        setVal('clickActionUrl', '');
        setVal('clickActionOpenIn', 'current');
        setVal('clickActionConfirm', '');
        setVal('clickActionOnlyWhen', '');
        setVal('clickActionRefresh', 'none');
        setVal('clickActionClientBefore', '');
        setVal('clickActionServer', '');
        setVal('clickActionClientAfter', '');
        syncClickActionUI('openPage');
    }
    bootstrap.Modal.getOrCreateInstance(document.getElementById('clickActionModal')).show();
    initializePageTooltips(document.getElementById('clickActionModal'));
}

function toggleClickActionCode(show) {
    document.getElementById('clickActionCodeGroup').style.display = show ? 'block' : 'none';
}
// Show/hide the type-specific field groups for the chosen action type.
function syncClickActionUI(type) {
    const show = (id, on) => { const el = document.getElementById(id); if (el) el.style.display = on ? 'block' : 'none'; };
    show('clickActionTargetGroup', type === 'openPage');
    show('clickActionUrlGroup', type === 'openUrl');
    show('clickActionOpenInGroup', type === 'openPage' || type === 'openUrl');
    toggleClickActionCode(type === 'executeCode');
}
// Back-compat shim — older callers passed a bool for the openPage target; the
// unified syncClickActionUI now owns visibility.
function toggleClickActionTarget(show) { syncClickActionUI(show ? 'openPage' : (document.getElementById('clickActionType') || {}).value); }
document.addEventListener('change', (e) => {
    if (e.target.id === 'clickActionType') syncClickActionUI(e.target.value);
});
document.getElementById('btnSaveClickAction')?.addEventListener('click', () => {
    const index = parseInt(document.getElementById('clickActionEditIndex').value);
    const val = id => { const el = document.getElementById(id); return el ? el.value : ''; };
    const action = {
        field: val('clickActionField'),
        actionType: val('clickActionType'),
        on: val('clickActionOn') || 'single',
        target: val('clickActionTarget'),
        url: val('clickActionUrl'),
        openIn: val('clickActionOpenIn'),
        confirm: val('clickActionConfirm'),
        onlyWhen: val('clickActionOnlyWhen'),
        refresh: val('clickActionRefresh') || 'none',
        clientBefore: val('clickActionClientBefore'),
        server: val('clickActionServer'),
        clientAfter: val('clickActionClientAfter')
    };
    if (index >= 0) clickActions[index] = action;
    else clickActions.push(action);
    renderClickActionsTable();
    bootstrap.Modal.getInstance(document.getElementById('clickActionModal')).hide();
});


window.openKeyColumnsModal = openKeyColumnsModal;
window.openPageSettingsModal = openPageSettingsModal;
window.openClickActionModal = openClickActionModal;
window.toggleClickActionCode = toggleClickActionCode;
window.toggleClickActionTarget = toggleClickActionTarget;
