// ── Labels Tab ─────────────────────────────────────────────────────────
let tableLabelsData = {};
let placeholdersData = {};
let pageTitlesData = {};
let cachedPageTitlesHtml = '';
let currentPageTitlesLang = '';

function initLabelsTab() {
    const sel = document.getElementById('labelsLangSelect');
    if (!sel) return;
    sel.innerHTML = '<option value="">— select language —</option>';
    const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
    langs.forEach(l => sel.innerHTML += `<option value="${l.code}">${l.name}</option>`);
}

// ── Table Labels Grid ─────────────────────────────────────────────────
async function renderTableLabelsGrid(langCode) {
    const container = document.getElementById('tableLabelsGrid');
    if (!container || !langCode) { container.innerHTML = '<div class="text-muted small py-2">Select a language to edit labels.</div>'; return; }
    container.innerHTML = '<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>';
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${langCode}`);
        const data = await res.json();
        tableLabelsData[langCode] = (data.success && data.labels && data.labels.tables) ? data.labels.tables : {};
        const tables = await getSelectedTables();
        const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
        const langName = langs.find(l => l.code === langCode)?.name || langCode;
        let html = '<table class="table table-sm table-bordered small"><thead><tr><th style="width:30%;">Table</th><th>Label (Caption) – ' + langName + '</th></tr></thead><tbody>';
        tables.forEach(t => {
            const tableName = t.name || t;
            const key = `${tableName}.caption`;
            const val = tableLabelsData[langCode][key] || tableName;
            html += `<tr><td class="fw-bold align-middle">${tableName}</td><td><input type="text" class="form-control form-control-sm label-input" data-key="${key}" data-lang="${langCode}" data-section="tables" value="${pp.util.escapeHtml(val)}"></td></tr>`;
        });
        html += '</tbody></table>';
        container.innerHTML = html;
        cachedTableLabelsHtml = html;  // store for filtering
        currentTableLabelsLang = langCode;
        container.querySelectorAll('.label-input').forEach(input => input.addEventListener('blur', () => saveLabel(input)));
        applyTableLabelsFilter(); // apply current filter
    } catch (err) { container.innerHTML = '<div class="alert alert-danger small">Failed to load labels.</div>'; }
}

// ── Placeholders Grid ──────────────────────────────────────────────────
async function renderPlaceholdersGrid(langCode) {
    const container = document.getElementById('placeholdersGrid');
    if (!container || !langCode) { container.innerHTML = '<div class="text-muted small py-2">Select a language to edit placeholders.</div>'; return; }
    container.innerHTML = '<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>';
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${langCode}`);
        const data = await res.json();
        placeholdersData[langCode] = (data.success && data.labels && data.labels.placeholders) ? data.labels.placeholders : {};
        const tables = await getSelectedTables();
        const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
        const langName = langs.find(l => l.code === langCode)?.name || langCode;
        let html = '<table class="table table-sm table-bordered small"><thead><tr><th style="width:20%;">Table</th><th style="width:30%;">Field</th><th>Placeholder – ' + langName + '</th></tr></thead><tbody>';
        for (const table of tables) {
            const tableName = table.name || table;
            if (!window.tableFieldCache) window.tableFieldCache = {};
            if (!window.tableFieldCache[tableName]) {
                try { const fres = await fetch(`${baseUrl}/project/${projectSlug}/tables/details/${tableName}`); const fdata = await fres.json(); window.tableFieldCache[tableName] = fdata.success ? fdata.columns : []; }
                catch (err) { window.tableFieldCache[tableName] = []; }
            }
            const fields = window.tableFieldCache[tableName] || [];
            fields.forEach(f => {
                const key = `${tableName}.${f.COLUMN_NAME}`;
                const val = placeholdersData[langCode][key] || '';
                html += `<tr><td class="fw-bold align-middle">${tableName}</td><td class="align-middle">${f.COLUMN_NAME}</td><td><input type="text" class="form-control form-control-sm placeholder-input" data-key="${key}" data-lang="${langCode}" data-section="placeholders" value="${pp.util.escapeHtml(val)}"></td></tr>`;
            });
        }
        html += '</tbody></table>';
        container.innerHTML = html;
        cachedPlaceholdersHtml = html; // store for filtering
        currentPlaceholdersLang = langCode;
        container.querySelectorAll('.placeholder-input').forEach(input => input.addEventListener('blur', () => saveLabel(input)));
        container.style.maxHeight = '50vh'; container.style.overflowY = 'auto';
        container.querySelector('thead').style.position = 'sticky'; container.querySelector('thead').style.top = '0'; container.querySelector('thead').style.zIndex = '2';
        applyPlaceholdersFilter(); // apply current filter
    } catch (err) { container.innerHTML = '<div class="alert alert-danger small">Failed to load placeholders.</div>'; }
}


// ── Filter helpers for Table Labels and Placeholders ─────────────────
let cachedTableLabelsHtml = '';
let cachedPlaceholdersHtml = '';
let currentTableLabelsLang = '';
let currentPlaceholdersLang = '';

function applyTableLabelsFilter() {
    const filter = document.getElementById('filterTableLabels')?.value.toLowerCase() || '';
    const container = document.getElementById('tableLabelsGrid');
    if (!container || !cachedTableLabelsHtml) return;
    container.innerHTML = cachedTableLabelsHtml;
    const rows = container.querySelectorAll('tbody tr');
    rows.forEach(row => {
        const tableCell = row.querySelector('td:first-child');
        const tableName = tableCell ? tableCell.textContent.toLowerCase() : '';
        row.style.display = tableName.includes(filter) ? '' : 'none';
    });
    // Reattach blur listeners (they were replaced)
    container.querySelectorAll('.label-input').forEach(input => {
        input.addEventListener('blur', () => saveLabel(input));
    });
}

function applyPlaceholdersFilter() {
    const filter = document.getElementById('filterPlaceholders')?.value.toLowerCase() || '';
    const container = document.getElementById('placeholdersGrid');
    if (!container || !cachedPlaceholdersHtml) return;
    container.innerHTML = cachedPlaceholdersHtml;
    const rows = container.querySelectorAll('tbody tr');
    rows.forEach(row => {
        const tableCell = row.querySelector('td:first-child');
        const fieldCell = row.querySelector('td:nth-child(2)');
        const tableName = tableCell ? tableCell.textContent.toLowerCase() : '';
        const fieldName = fieldCell ? fieldCell.textContent.toLowerCase() : '';
        const show = tableName.includes(filter) || fieldName.includes(filter);
        row.style.display = show ? '' : 'none';
    });
    container.querySelectorAll('.placeholder-input').forEach(input => {
        input.addEventListener('blur', () => saveLabel(input));
    });
}

// ── Field Labels Grid ──────────────────────────────────────────────────
let fieldLabelsData = {};
let cachedFieldLabelsHtml = '';
let currentFieldLabelsLang = '';
async function renderFieldLabelsGrid(langCode) {
    const container = document.getElementById('fieldLabelsGrid');
    if (!container || !langCode) { if (container) container.innerHTML = '<div class="text-muted small py-2">Select a language to edit field labels.</div>'; return; }
    container.innerHTML = '<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>';
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${langCode}`);
        const data = await res.json();
        fieldLabelsData[langCode] = (data.success && data.labels && data.labels.labels) ? data.labels.labels : {};
        const tables = await getSelectedTables();
        const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
        const langName = langs.find(l => l.code === langCode)?.name || langCode;
        let html = '<table class="table table-sm table-bordered small"><thead><tr><th style="width:20%;">Table</th><th style="width:30%;">Field</th><th>Label – ' + langName + '</th></tr></thead><tbody>';
        for (const table of tables) {
            const tableName = table.name || table;
            if (!window.tableFieldCache) window.tableFieldCache = {};
            if (!window.tableFieldCache[tableName]) {
                try { const fres = await fetch(`${baseUrl}/project/${projectSlug}/tables/details/${tableName}`); const fdata = await fres.json(); window.tableFieldCache[tableName] = fdata.success ? fdata.columns : []; }
                catch (err) { window.tableFieldCache[tableName] = []; }
            }
            const fields = window.tableFieldCache[tableName] || [];
            fields.forEach(f => {
                const key = `${tableName}.${f.COLUMN_NAME}`;
                const val = fieldLabelsData[langCode][key] || '';
                const hint = f.COLUMN_NAME.replace(/[_-]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
                html += `<tr><td class="fw-bold align-middle">${tableName}</td><td class="align-middle">${f.COLUMN_NAME}</td><td><input type="text" class="form-control form-control-sm field-label-input" data-key="${key}" data-lang="${langCode}" data-section="labels" placeholder="${pp.util.escapeHtml(hint)}" value="${pp.util.escapeHtml(val)}"></td></tr>`;
            });
        }
        html += '</tbody></table>';
        container.innerHTML = html;
        cachedFieldLabelsHtml = html;
        currentFieldLabelsLang = langCode;
        container.querySelectorAll('.field-label-input').forEach(input => input.addEventListener('blur', () => saveLabel(input)));
        container.style.maxHeight = '50vh'; container.style.overflowY = 'auto';
        const thead = container.querySelector('thead'); if (thead) { thead.style.position = 'sticky'; thead.style.top = '0'; thead.style.zIndex = '2'; }
        applyFieldLabelsFilter();
    } catch (err) { container.innerHTML = '<div class="alert alert-danger small">Failed to load field labels.</div>'; }
}
function applyFieldLabelsFilter() {
    const filter = document.getElementById('filterFieldLabels')?.value.toLowerCase() || '';
    const container = document.getElementById('fieldLabelsGrid');
    if (!container || !cachedFieldLabelsHtml) return;
    container.innerHTML = cachedFieldLabelsHtml;
    container.querySelectorAll('tbody tr').forEach(row => {
        const t = row.querySelector('td:first-child')?.textContent.toLowerCase() || '';
        const f = row.querySelector('td:nth-child(2)')?.textContent.toLowerCase() || '';
        row.style.display = (t.includes(filter) || f.includes(filter)) ? '' : 'none';
    });
    container.querySelectorAll('.field-label-input').forEach(input => input.addEventListener('blur', () => saveLabel(input)));
}


// ── Page Titles Grid (with search/filter) ─────────────────────────────
async function renderPageTitlesGrid(langCode) {
    const container = document.getElementById('pageTitlesGrid');
    if (!container || !langCode) {
        if (container) container.innerHTML = '<div class="text-muted small py-2">Select a language to edit page titles.</div>';
        return;
    }
    currentPageTitlesLang = langCode;
    container.innerHTML = '<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>';

    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${langCode}`);
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        const data = await res.json();
        if (!data.success) throw new Error(data.message || 'Failed to load labels');

        pageTitlesData[langCode] = (data.labels && data.labels.pageTitles) ? data.labels.pageTitles : {};

        const tables = await getSelectedTables();
        const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
        const langName = langs.find(l => l.code === langCode)?.name || langCode;

        // Build rows for each table and its enabled page types (from Pages module)
        let html = '<table class="table table-sm table-bordered small" id="pageTitlesTable">';
        html += '<thead><tr><th style="width:25%;">Table</th><th style="width:25%;">Page Type</th>';
        html += `<th>Page Title – ${pp.util.escapeHtml(langName)}</th>`;
        html += '</thead><tbody>';

        for (const table of tables) {
            const tableName = table.name || table;
            let enabledPageTypes = [];

            // Get enabled page types from Pages module (injected as pagesConfig)
            if (typeof pagesConfig !== 'undefined' && pagesConfig[tableName] && pagesConfig[tableName].pageTypes) {
                enabledPageTypes = pagesConfig[tableName].pageTypes;
            } else {
                // Fallback to default page types
                enabledPageTypes = ['list', 'add', 'edit', 'view'];
            }

            const pageLabels = {
                list: 'List', add: 'Add', edit: 'Edit', view: 'View',
                print: 'Print', export: 'Export', import: 'Import', cards: 'Cards'
            };

            enabledPageTypes.forEach(page => {
                const key = `${tableName}.${page}`;
                const currentValue = pageTitlesData[langCode][key] || '';
                const pageLabel = pageLabels[page] || page;
                html += `<tr data-table="${pp.util.escapeHtml(tableName)}" data-page="${page}">
                    <td class="fw-bold align-middle table-name-cell">${pp.util.escapeHtml(tableName)}</td>
                    <td class="align-middle page-type-cell">${pageLabel}</td>
                    <td><input type="text" class="form-control form-control-sm page-title-input" data-key="${key}" data-lang="${langCode}" data-section="pageTitles" value="${pp.util.escapeHtml(currentValue)}"></td>
                </tr>`;
            });
        }
        html += '</tbody></table>';
        container.innerHTML = html;
        cachedPageTitlesHtml = html;

        container.querySelectorAll('.page-title-input').forEach(input => {
            input.addEventListener('blur', () => saveLabel(input));
        });

        // Re-apply filters if any
        applyPageTitlesFilters();
    } catch (err) {
        console.error('renderPageTitlesGrid error:', err);
        container.innerHTML = '<div class="alert alert-danger small">Failed to load page titles.</div>';
    }
}

function applyPageTitlesFilters() {
    const filterTable = document.getElementById('filterTableName')?.value.toLowerCase() || '';
    const filterPage = document.getElementById('filterPageType')?.value;
    const container = document.getElementById('pageTitlesGrid');
    // If the grid was regenerated, we need to get the table rows from the current DOM
    if (!container) return;
    const table = container.querySelector('#pageTitlesTable');
    if (!table) return;
    const rows = table.querySelectorAll('tbody tr');
    rows.forEach(row => {
        const tableName = row.querySelector('.table-name-cell')?.textContent.toLowerCase() || '';
        const pageType = row.querySelector('.page-type-cell')?.textContent.toLowerCase() || '';
        let show = true;
        if (filterTable && !tableName.includes(filterTable)) show = false;
        if (filterPage && pageType !== filterPage.toLowerCase()) show = false;
        row.style.display = show ? '' : 'none';
    });
}


// ── Tooltips Grid ────────────────────────────────────────────────────
let tooltipsData = {};
let cachedTooltipsHtml = '';
let currentTooltipsLang = '';

async function renderTooltipsGrid(langCode) {
    const container = document.getElementById('tooltipsGrid');
    if (!container || !langCode) {
        if (container) container.innerHTML = '<div class="text-muted small py-2">Select a language to edit tooltips.</div>';
        return;
    }
    container.innerHTML = '<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>';
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${langCode}`);
        const data = await res.json();
        tooltipsData[langCode] = (data.success && data.labels && data.labels.tooltips) ? data.labels.tooltips : {};

        const tables = await getSelectedTables();
        const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
        const langName = langs.find(l => l.code === langCode)?.name || langCode;

        let html = '<table class="table table-sm table-bordered small"><thead><tr>';
        html += '<th style="width:20%;">Table</th><th style="width:30%;">Field</th>';
        html += `<th>Tooltip – ${langName}</th>`;
        html += '</thead><tbody>';

        for (const table of tables) {
            const tableName = table.name || table;
            if (!window.tableFieldCache) window.tableFieldCache = {};
            if (!window.tableFieldCache[tableName]) {
                try {
                    const fres = await fetch(`${baseUrl}/project/${projectSlug}/tables/details/${tableName}`);
                    const fdata = await fres.json();
                    window.tableFieldCache[tableName] = fdata.success ? fdata.columns : [];
                } catch (err) {
                    window.tableFieldCache[tableName] = [];
                }
            }
            const fields = window.tableFieldCache[tableName] || [];
            fields.forEach(f => {
                const key = `${tableName}.${f.COLUMN_NAME}`;
                const val = tooltipsData[langCode][key] || '';
                html += `<tr>
                    <td class="fw-bold align-middle">${tableName}</td>
                    <td class="align-middle">${f.COLUMN_NAME}</td>
                    <td><input type="text" class="form-control form-control-sm tooltip-input" data-key="${key}" data-lang="${langCode}" data-section="tooltips" value="${pp.util.escapeHtml(val)}"></td>
                </tr>`;
            });
        }
        html += '</tbody></table>';
        container.innerHTML = html;
        cachedTooltipsHtml = html;
        currentTooltipsLang = langCode;

        // Attach auto‑save on blur
        container.querySelectorAll('.tooltip-input').forEach(input => {
            input.addEventListener('blur', () => saveLabel(input));
        });

        // Apply current filter if any
        applyTooltipsFilter();
    } catch (err) {
        console.error('renderTooltipsGrid error:', err);
        container.innerHTML = '<div class="alert alert-danger small">Failed to load tooltips.</div>';
    }
}

function applyTooltipsFilter() {
    const filter = document.getElementById('filterTooltips')?.value.toLowerCase() || '';
    const container = document.getElementById('tooltipsGrid');
    if (!container || !cachedTooltipsHtml) return;
    container.innerHTML = cachedTooltipsHtml;
    const rows = container.querySelectorAll('tbody tr');
    rows.forEach(row => {
        const tableCell = row.querySelector('td:first-child');
        const fieldCell = row.querySelector('td:nth-child(2)');
        const tableName = tableCell ? tableCell.textContent.toLowerCase() : '';
        const fieldName = fieldCell ? fieldCell.textContent.toLowerCase() : '';
        const show = tableName.includes(filter) || fieldName.includes(filter);
        row.style.display = show ? '' : 'none';
    });
    // Reattach blur listeners
    container.querySelectorAll('.tooltip-input').forEach(input => {
        input.addEventListener('blur', () => saveLabel(input));
    });
}

// ── Common save function for all label inputs ─────────────────────────
// ── App Strings Grid (UI chrome, grouped) ─────────────────────────────
async function renderAppStringsGrid(langCode) {
    const container = document.getElementById('appStringsGrid');
    if (!container || !langCode) {
        if (container) container.innerHTML = '<div class="text-muted small py-2">Select a language to translate the interface text.</div>';
        return;
    }
    container.innerHTML = '<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>';
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${langCode}`);
        const data = await res.json();
        const saved = (data.success && data.labels && data.labels.ui) ? data.labels.ui : {};
        const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
        const langName = langs.find(l => l.code === langCode)?.name || langCode;
        const groups = (typeof uiStringGroups !== 'undefined' && uiStringGroups) ? uiStringGroups : {};
        let html = '<table class="table table-sm table-bordered small" id="appStringsTable"><thead><tr>'
            + '<th style="width:40%;">Interface text (English)</th><th>' + pp.util.escapeHtml(langName) + '</th></tr></thead><tbody>';
        Object.keys(groups).forEach(group => {
            html += '<tr class="table-light"><td colspan="2" class="fw-bold text-uppercase text-muted" style="font-size:.7rem;letter-spacing:.03em;">' + pp.util.escapeHtml(group) + '</td></tr>';
            const keys = groups[group] || {};
            Object.keys(keys).forEach(k => {
                const en = keys[k], cur = saved[k] || '';
                html += '<tr data-key="' + pp.util.escapeHtml(k) + '"><td class="align-middle">' + pp.util.escapeHtml(en) + '</td>'
                    + '<td><input type="text" class="form-control form-control-sm app-string-input" data-key="' + pp.util.escapeHtml(k) + '" data-lang="' + pp.util.escapeHtml(langCode) + '" data-section="ui" placeholder="' + pp.util.escapeHtml(en) + '" value="' + pp.util.escapeHtml(cur) + '"></td></tr>';
            });
        });
        html += '</tbody></table>';
        container.innerHTML = html;
        container.querySelectorAll('.app-string-input').forEach(i => i.addEventListener('blur', () => saveLabel(i)));
        applyAppStringsFilter();
    } catch (e) {
        console.error('renderAppStringsGrid error:', e);
        container.innerHTML = '<div class="alert alert-danger small">Failed to load app strings.</div>';
    }
}
function applyAppStringsFilter() {
    const q = (document.getElementById('filterAppStrings')?.value || '').toLowerCase();
    document.querySelectorAll('#appStringsTable tbody tr[data-key]').forEach(tr => {
        tr.style.display = (!q || tr.textContent.toLowerCase().indexOf(q) > -1) ? '' : 'none';
    });
}

// ── Menu Labels Grid ──────────────────────────────────────────────────
async function renderMenuLabelsGrid(langCode) {
    const container = document.getElementById('menuLabelsGrid');
    if (!container || !langCode) {
        if (container) container.innerHTML = '<div class="text-muted small py-2">Select a language to translate menu labels.</div>';
        return;
    }
    container.innerHTML = '<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>';
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${langCode}`);
        const data = await res.json();
        const saved = (data.success && data.labels && data.labels.menu) ? data.labels.menu : {};
        const items = (typeof menuItems !== 'undefined' && menuItems) ? menuItems : {};
        const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
        const langName = langs.find(l => l.code === langCode)?.name || langCode;
        const keys = Object.keys(items);
        if (!keys.length) {
            container.innerHTML = '<div class="text-muted small py-2">No menu items yet — define your app menu in the <strong>Style</strong> module, then translate the labels here.</div>';
            return;
        }
        let html = '<table class="table table-sm table-bordered small" id="menuLabelsTable"><thead><tr>'
            + '<th style="width:40%;">Menu item</th><th>' + pp.util.escapeHtml(langName) + '</th></tr></thead><tbody>';
        keys.forEach(k => {
            const def = items[k], cur = saved[k] || '';
            html += '<tr data-key="' + pp.util.escapeHtml(k) + '"><td class="align-middle fw-bold">' + pp.util.escapeHtml(def) + '</td>'
                + '<td><input type="text" class="form-control form-control-sm menu-label-input" data-key="' + pp.util.escapeHtml(k) + '" data-lang="' + pp.util.escapeHtml(langCode) + '" data-section="menu" placeholder="' + pp.util.escapeHtml(def) + '" value="' + pp.util.escapeHtml(cur) + '"></td></tr>';
        });
        html += '</tbody></table>';
        container.innerHTML = html;
        container.querySelectorAll('.menu-label-input').forEach(i => i.addEventListener('blur', () => saveLabel(i)));
        applyMenuLabelsFilter();
    } catch (e) {
        console.error('renderMenuLabelsGrid error:', e);
        container.innerHTML = '<div class="alert alert-danger small">Failed to load menu labels.</div>';
    }
}
function applyMenuLabelsFilter() {
    const q = (document.getElementById('filterMenuLabels')?.value || '').toLowerCase();
    document.querySelectorAll('#menuLabelsTable tbody tr[data-key]').forEach(tr => {
        tr.style.display = (!q || tr.textContent.toLowerCase().indexOf(q) > -1) ? '' : 'none';
    });
}

async function saveLabel(input) {
    if (typeof isPageUnloading !== 'undefined' && isPageUnloading) return;
    const langCode = input.dataset.lang;
    const key = input.dataset.key;
    const section = input.dataset.section || 'tables';
    const value = input.value;
    if (!langCode || !key) return;

    // Update local cache
    if (section === 'tables') {
        if (!tableLabelsData[langCode]) tableLabelsData[langCode] = {};
        tableLabelsData[langCode][key] = value;
    } else if (section === 'labels') {
        if (!fieldLabelsData[langCode]) fieldLabelsData[langCode] = {};
        fieldLabelsData[langCode][key] = value;
    } else if (section === 'placeholders') {
        if (!placeholdersData[langCode]) placeholdersData[langCode] = {};
        placeholdersData[langCode][key] = value;
    } else if (section === 'pageTitles') {
        if (!pageTitlesData[langCode]) pageTitlesData[langCode] = {};
        pageTitlesData[langCode][key] = value;
    } else if (section === 'tooltips') {
        if (!tooltipsData[langCode]) tooltipsData[langCode] = {};
        tooltipsData[langCode][key] = value;
    }

    await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/save`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ langCode, section, key, value })
    }).catch(() => { });
}

// ── Helper: get selected tables ────────────────────────────────────────
async function getSelectedTables() {
    if (typeof dbTables !== 'undefined' && Array.isArray(dbTables) && dbTables.length > 0) return dbTables;
    try { const res = await fetch(`${baseUrl}/project/${projectSlug}/tables/details/all`); const data = await res.json(); return data.success ? data.columns : []; }
    catch (err) { return []; }
}

// ── Save all labels on page hide (fallback) ────────────────────────────
window.addEventListener('pagehide', () => {
    const inputs = document.querySelectorAll('.label-input, .placeholder-input, .page-title-input, .tooltip-input');
    inputs.forEach(input => {
        const langCode = input.dataset.lang;
        const key = input.dataset.key;
        const section = input.dataset.section || 'tables';
        const value = input.value;
        if (langCode && key) {
            navigator.sendBeacon(
                `${baseUrl}/project/${projectSlug}/misc/labels/save`,
                JSON.stringify({ langCode, section, key, value })
            );
        }
    });
});

// ── Event Listeners (DOMContentLoaded) ─────────────────────────────────
document.addEventListener('DOMContentLoaded', () => {
    // Re-populate language dropdown when labels tab is shown
    document.querySelector('[data-bs-target="#labelsPane"]')?.addEventListener('shown.bs.tab', () => {
        const sel = document.getElementById('labelsLangSelect');
        if (sel) {
            sel.innerHTML = '<option value="">— select language —</option>';
            const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
            langs.forEach(l => sel.innerHTML += `<option value="${l.code}">${l.name}</option>`);
        }
    });

    // Reset filters when TableLabels are shown
    document.querySelector('[data-bs-target="#subTableLabels"]')?.addEventListener('shown.bs.tab', () => {
        const filterInput = document.getElementById('filterTableLabels');
        if (filterInput) filterInput.value = '';
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (lang) renderTableLabelsGrid(lang);
    });

    // Reset filters when Field Labels are shown
    document.querySelector('[data-bs-target="#subFieldLabels"]')?.addEventListener('shown.bs.tab', () => {
        const filterInput = document.getElementById('filterFieldLabels');
        if (filterInput) filterInput.value = '';
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (lang) renderFieldLabelsGrid(lang);
    });

    // Reset filters when Placeholders are shown
    document.querySelector('[data-bs-target="#subPlaceholders"]')?.addEventListener('shown.bs.tab', () => {
        const filterInput = document.getElementById('filterPlaceholders');
        if (filterInput) filterInput.value = '';
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (lang) renderPlaceholdersGrid(lang);
    });

    // Field-labels filter
    document.getElementById('filterFieldLabels')?.addEventListener('input', applyFieldLabelsFilter);

    // Language change → reload the active sub‑tab
    document.getElementById('labelsLangSelect')?.addEventListener('change', (e) => {
        const lang = e.target.value;
        if (!lang) return;
        const active = document.querySelector('#labelsSubContent .tab-pane.active');
        if (active?.id === 'subTableLabels') renderTableLabelsGrid(lang);
        else if (active?.id === 'subFieldLabels') renderFieldLabelsGrid(lang);
        else if (active?.id === 'subPlaceholders') renderPlaceholdersGrid(lang);
        else if (active?.id === 'subPageTitles') renderPageTitlesGrid(lang);
        else if (active?.id === 'subTooltips') renderTooltipsGrid(lang);
        else if (active?.id === 'subAppStrings') renderAppStringsGrid(lang);
        else if (active?.id === 'subMenuLabels') renderMenuLabelsGrid(lang);
    });

    // App Strings + Menu tabs: render on show + wire their filters.
    document.querySelector('[data-bs-target="#subAppStrings"]')?.addEventListener('shown.bs.tab', () => {
        const f = document.getElementById('filterAppStrings'); if (f) f.value = '';
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (lang) renderAppStringsGrid(lang);
    });
    document.querySelector('[data-bs-target="#subMenuLabels"]')?.addEventListener('shown.bs.tab', () => {
        const f = document.getElementById('filterMenuLabels'); if (f) f.value = '';
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (lang) renderMenuLabelsGrid(lang);
    });
    document.getElementById('filterAppStrings')?.addEventListener('input', applyAppStringsFilter);
    document.getElementById('filterMenuLabels')?.addEventListener('input', applyMenuLabelsFilter);

    // Copy labels button
    document.getElementById('btnCopyLabels')?.addEventListener('click', async () => {
        const sel = document.getElementById('labelsLangSelect');
        const currentLang = sel?.value;
        if (!currentLang) { pp.dialog.toast('error', 'Select the target language first.'); return; }
        const langs = currentConfig.languages || [{ code: 'en', name: 'English' }];
        const options = {};
        langs.forEach(l => { if (l.code !== currentLang) options[l.code] = l.name; });
        if (Object.keys(options).length === 0) { pp.dialog.toast('info', 'No other languages available to copy from.'); return; }
        const { value: fromLang } = await Swal.fire({
            title: 'Copy labels from…', input: 'select', inputOptions: options,
            inputPlaceholder: 'Select source language', showCancelButton: true, confirmButtonText: 'Copy',
        });
        if (!fromLang) return;
        Swal.fire({ title: 'Copying labels…', allowOutsideClick: false, didOpen: () => Swal.showLoading() });
        try {
            const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/copy`, {
                method: 'POST', headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ fromLang, toLang: currentLang })
            });
            const data = await res.json();
            Swal.close();
            if (data.success) {
                pp.dialog.toast('success', 'Labels copied!');
                const active = document.querySelector('#labelsSubContent .tab-pane.active');
                if (active?.id === 'subTableLabels') renderTableLabelsGrid(currentLang);
                else if (active?.id === 'subFieldLabels') renderFieldLabelsGrid(currentLang);
                else if (active?.id === 'subPlaceholders') renderPlaceholdersGrid(currentLang);
                else if (active?.id === 'subPageTitles') renderPageTitlesGrid(currentLang);
                else if (active?.id === 'subTooltips') renderTooltipsGrid(currentLang);
            } else pp.dialog.alert('Failed', data.message, 'error');
        } catch (err) { Swal.close(); pp.dialog.toast('error', 'Network error.'); }
    });

    // Filter events for Page Titles
    const filterTableInput = document.getElementById('filterTableName');
    const filterPageSelect = document.getElementById('filterPageType');
    if (filterTableInput) filterTableInput.addEventListener('input', () => {
        if (currentPageTitlesLang) applyPageTitlesFilters();
    });
    if (filterPageSelect) filterPageSelect.addEventListener('change', () => {
        if (currentPageTitlesLang) applyPageTitlesFilters();
    });

    // When Page Titles tab is shown, reset filters and render
    document.querySelector('[data-bs-target="#subPageTitles"]')?.addEventListener('shown.bs.tab', () => {
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (lang) {
            if (filterTableInput) filterTableInput.value = '';
            if (filterPageSelect) filterPageSelect.value = '';
            renderPageTitlesGrid(lang);
        }
    });


    // Table Labels filter
    document.getElementById('filterTableLabels')?.addEventListener('input', () => {
        if (currentTableLabelsLang) applyTableLabelsFilter();
    });
    // Placeholders filter
    document.getElementById('filterPlaceholders')?.addEventListener('input', () => {
        if (currentPlaceholdersLang) applyPlaceholdersFilter();
    });


    // Tooltips filter
    document.getElementById('filterTooltips')?.addEventListener('input', () => {
        if (currentTooltipsLang) applyTooltipsFilter();
    });

    // When Tooltips tab is shown, reset filter and render
    document.querySelector('[data-bs-target="#subTooltips"]')?.addEventListener('shown.bs.tab', () => {
        const filterInput = document.getElementById('filterTooltips');
        if (filterInput) filterInput.value = '';
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (lang) renderTooltipsGrid(lang);
    });


    // ── Custom Labels ─────────────────────────────────────────────────────
    async function loadCustomLabels(langCode) {
        try {
            const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${langCode}`);
            const data = await res.json();
            const labels = (data.success && data.labels && data.labels.custom) ? data.labels.custom : {};
            const list = document.getElementById('customLabelsList');
            if (!list) return;
            list.innerHTML = '';
            for (const [key, value] of Object.entries(labels)) {
                list.innerHTML += `<div class="d-flex justify-content-between align-items-center py-1 border-bottom small">
                <span><strong>${key}</strong>: ${value}</span>
                <button class="btn btn-sm btn-outline-danger remove-custom-label" data-key="${key}"><i class="bi bi-x"></i></button>
            </div>`;
            }
            list.querySelectorAll('.remove-custom-label').forEach(btn => {
                btn.addEventListener('click', async () => {
                    const key = btn.dataset.key;
                    await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/save`, {
                        method: 'POST', headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ langCode, section: 'custom', key, value: '' })
                    });
                    loadCustomLabels(langCode);
                });
            });
        } catch (err) { /* silent */ }
    }

    document.getElementById('btnSaveCustomLabel')?.addEventListener('click', async () => {
        const lang = document.getElementById('labelsLangSelect')?.value;
        const key = document.getElementById('customLabelKey').value.trim();
        const value = document.getElementById('customLabelValue').value;
        if (!lang || !key) { pp.dialog.toast('error', 'Language and key required.'); return; }
        await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/save`, {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ langCode: lang, section: 'custom', key, value })
        });
        document.getElementById('customLabelKey').value = '';
        document.getElementById('customLabelValue').value = '';
        loadCustomLabels(lang);
    });

    document.querySelector('[data-bs-target="#subCustomLabels"]')?.addEventListener('shown.bs.tab', () => {
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (lang) loadCustomLabels(lang);
    });

    // ── Project Logo ──────────────────────────────────────────────────────
    document.getElementById('btnSaveLogo')?.addEventListener('click', async () => {
        const lang = document.getElementById('labelsLangSelect')?.value;
        const value = document.getElementById('logoText').value;
        if (!lang) { pp.dialog.toast('error', 'Select a language.'); return; }
        await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/save`, {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ langCode: lang, section: 'logo', key: 'projectLogo', value })
        });
        pp.dialog.toast('success', 'Logo saved.');
    });

    document.querySelector('[data-bs-target="#subLogo"]')?.addEventListener('shown.bs.tab', async () => {
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (!lang) return;
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${lang}`);
        const data = await res.json();
        if (data.success) {
            document.getElementById('logoText').value = (data.labels && data.labels.logo && data.labels.logo.projectLogo) || '';
        }
    });

    // ── Cookie Consent ────────────────────────────────────────────────────
    document.getElementById('btnSaveCookie')?.addEventListener('click', async () => {
        const lang = document.getElementById('labelsLangSelect')?.value;
        const value = document.getElementById('cookieText').value;
        if (!lang) { pp.dialog.toast('error', 'Select a language.'); return; }
        await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/save`, {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ langCode: lang, section: 'cookie', key: 'cookieBannerText', value })
        });
        pp.dialog.toast('success', 'Cookie banner saved.');
    });

    document.querySelector('[data-bs-target="#subCookie"]')?.addEventListener('shown.bs.tab', async () => {
        const lang = document.getElementById('labelsLangSelect')?.value;
        if (!lang) return;
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/labels/load/${lang}`);
        const data = await res.json();
        if (data.success) {
            document.getElementById('cookieText').value = (data.labels && data.labels.cookie && data.labels.cookie.cookieBannerText) || '';
        }
    });

});