// ── Shared State & Core Helpers ─────────────────────────────────────────
let currentTableName = null;
let currentConfig = {
    project: {}, byTable: {}, advanced: {}, email: {}, sms: {},
    languages: []                          // dedicated languages key
};

let isPageUnloading = false; // flag to ignore fetch errors during page unload

const defaultTableConfig = {
    recordsPerPage: 20,
    recordsPerPageOptions: '10,20,50,100',
    rowHighlight: true, nextPrevButtons: true,
    warnLeave: true, loadingBox: false,
    hideUntilSearch: false, defaultSortField: '', defaultSortOrder: 'ASC'
};

async function loadFullConfig() {
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/misc/load`);
        const data = await res.json();
        if (data.success) {
            // If config is an array (empty list), convert to object
            let config = data.config;
            if (Array.isArray(config)) {
                config = {};
            }
            currentConfig = config || {};
            currentConfig.project = currentConfig.project || {};
            currentConfig.advanced = currentConfig.advanced || {};
            currentConfig.email = currentConfig.email || {};
            currentConfig.sms = currentConfig.sms || {};
            currentConfig.byTable = currentConfig.byTable || {};
            currentConfig.languages = currentConfig.languages || [];

            // Restore languages from localStorage if server data is empty
            if (currentConfig.languages.length === 0) {
                const local = localStorage.getItem('pp_misc_languages');
                if (local) {
                    try { currentConfig.languages = JSON.parse(local); } catch (e) { }
                }
            }
        }
    } catch (err) { /* silent */ }
    // console.log('Loaded config:', JSON.stringify(currentConfig));
}

async function saveSection(section, dataOverride = null) {
    if (isPageUnloading) return; // skip during page unload

    const data = dataOverride ? { ...dataOverride } : {};

    if (!dataOverride) {
        if (section === 'project') {
            data.regionalFormat = document.getElementById('projRegional').value;
            data.landingPage = getLandingPageValue();
            data.mapProvider = document.getElementById('projMapProvider').value;
            data.mapApiKey = document.getElementById('projMapKey').value;
            data.errorReporting = document.getElementById('projErrorReporting').value;
            data.customErrorMessage = document.getElementById('projErrorMsg').value;
            data.darkMode = document.getElementById('projDarkMode').checked;
            data.gdprBanner = document.getElementById('projGDPR').checked;
            data.section508 = document.getElementById('proj508').checked;
            data.showLanguageSelector = document.getElementById('projShowLangSelector')?.checked ?? true;
            data.liveTranslations = document.getElementById('projLiveTranslations')?.checked || false;
            Object.assign(currentConfig.project, data);
        } else if (section === 'advanced') {
            data.auditEnabled = document.getElementById('advAudit').checked;
            data.auditTable = document.getElementById('advAuditTable').value;
            data.recordLocking = document.getElementById('advLocking').checked;
            data.lockTable = document.getElementById('advLockTable').value;
            data.lockTimeout = parseInt(document.getElementById('advLockTimeout').value) || 300;
            data.exportWatermark = document.getElementById('advWatermark').value;
            data.notifEnabled = document.getElementById('notifEnableCheck').checked;
            data.notifTableName = document.getElementById('notifTableName').value || 'notifications';
            Object.assign(currentConfig.advanced, data);
        } else if (section === 'email') {
            data.provider = document.getElementById('emailProvider').value;
            data.host = document.getElementById('emailHost').value;
            data.port = document.getElementById('emailPort').value;
            data.encryption = document.getElementById('emailEncryption').value;
            data.username = document.getElementById('emailUser').value;
            data.password = document.getElementById('emailPass').value;
            data.fromAddress = document.getElementById('emailFrom').value;
            data.fromName = document.getElementById('emailFromName').value;
            Object.assign(currentConfig.email, data);
        } else if (section === 'sms') {
            data.provider = document.getElementById('smsProvider').value;
            document.querySelectorAll('#smsFields .sms-setting').forEach(el => {
                data[el.dataset.key] = el.value;
            });
            Object.assign(currentConfig.sms, data);
        } else if (section === 'ai') {
            data.provider = document.getElementById('aiProvider')?.value || 'anthropic';
            data.model = document.getElementById('aiModel')?.value.trim() || '';
            data.base_url = document.getElementById('aiBaseUrl')?.value.trim() || '';
            data.max_tokens = parseInt(document.getElementById('aiMaxTokens')?.value) || '';
            // Only send the key when the user actually typed one — a blank key means
            // "keep the stored key" (the server treats blank as untouched). Never cache
            // the key in currentConfig (it is never sent back to the browser).
            const aiKey = document.getElementById('aiApiKey')?.value || '';
            if (aiKey.trim() !== '') data.api_key = aiKey.trim();
            currentConfig.ai = Object.assign({}, currentConfig.ai, { provider: data.provider, model: data.model, base_url: data.base_url, max_tokens: data.max_tokens });
        }
    }

    // Update local cache for the section
    if (!dataOverride) currentConfig[section] = data;

    await fetch(`${baseUrl}/project/${projectSlug}/misc/save`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ section, data })
    }).catch(() => {
        // Silently ignore fetch errors – they happen during page unload
    });
}

// mobile toggle helper
function initMobileToggle() {
    const btn = document.getElementById('btnToggleMiscList');
    const panel = document.querySelector('.left-panel');
    if (btn && panel) {
        btn.addEventListener('click', () => {
            panel.classList.toggle('collapsed');
            btn.innerHTML = panel.classList.contains('collapsed')
                ? '<i class="bi bi-list"></i> Tables'
                : '<i class="bi bi-x-lg"></i> Hide';
        });
    }
}

// Set unloading flag on page hide (navigation, refresh, close)
window.addEventListener('pagehide', () => {
    isPageUnloading = true;
});
window.addEventListener('beforeunload', () => {
    isPageUnloading = true;
});








// ── Smart Landing Page Helpers (inline two‑column layout) ──────────────────
let tablePageTypesMap = {};

function populateLandingPageTargets() {
    const targetSelect = document.getElementById('projLandingTarget');
    if (!targetSelect) return;
    // Clear existing table options (keep Dashboard and Custom)
    while (targetSelect.options.length > 2) {
        targetSelect.remove(2);
    }
    // Add table options from tablesWithPageTypes (injected by PHP)
    if (typeof tablesWithPageTypes !== 'undefined') {
        tablesWithPageTypes.forEach(item => {
            const opt = document.createElement('option');
            opt.value = item.table;
            opt.textContent = item.table;
            targetSelect.appendChild(opt);
            tablePageTypesMap[item.table] = item.pageTypes;
        });
    }
    targetSelect.addEventListener('change', updateLandingPageUI);
    updateLandingPageUI();
}

function updateLandingPageUI() {
    const targetSelect = document.getElementById('projLandingTarget');
    const pageTypeSelect = document.getElementById('projLandingPageType');
    const customUrlInput = document.getElementById('projLandingCustomUrl');
    if (!targetSelect) return;

    const target = targetSelect.value;
    if (target === 'custom') {
        pageTypeSelect.style.display = 'none';
        customUrlInput.style.display = 'block';
        pageTypeSelect.disabled = true;
    } else if (target === 'dashboard') {
        pageTypeSelect.style.display = 'none';
        customUrlInput.style.display = 'none';
        pageTypeSelect.disabled = true;
    } else {
        // A table is selected
        pageTypeSelect.style.display = 'block';
        customUrlInput.style.display = 'none';
        pageTypeSelect.disabled = false;
        updatePageTypeDropdown(target);
    }
}

function updatePageTypeDropdown(tableName) {
    const pageTypeSelect = document.getElementById('projLandingPageType');
    if (!pageTypeSelect) return;
    const allowed = tablePageTypesMap[tableName] || ['list'];
    for (let i = 0; i < pageTypeSelect.options.length; i++) {
        const opt = pageTypeSelect.options[i];
        opt.disabled = !allowed.includes(opt.value);
        opt.style.display = allowed.includes(opt.value) ? '' : 'none';
    }
    // Select first allowed if current is not allowed
    if (!allowed.includes(pageTypeSelect.value)) {
        pageTypeSelect.value = allowed[0] || 'list';
    }
}

function getLandingPageValue() {
    const targetSelect = document.getElementById('projLandingTarget');
    if (!targetSelect) return null;
    const target = targetSelect.value;
    if (target === 'custom') {
        const customUrl = document.getElementById('projLandingCustomUrl')?.value || '';
        return { type: 'custom', value: customUrl };
    }
    if (target === 'dashboard') {
        return { type: 'dashboard', value: 'dashboard' };
    }
    const pageTypeSelect = document.getElementById('projLandingPageType');
    const pageType = pageTypeSelect ? pageTypeSelect.value : 'list';
    return {
        type: 'page',
        value: { table: target, page: pageType }
    };
}

function setLandingPageValue(savedValue) {
    const targetSelect = document.getElementById('projLandingTarget');
    const pageTypeSelect = document.getElementById('projLandingPageType');
    const customUrlInput = document.getElementById('projLandingCustomUrl');
    if (!targetSelect) return;

    if (savedValue && savedValue.type === 'custom') {
        targetSelect.value = 'custom';
        if (customUrlInput) {
            customUrlInput.value = savedValue.value;
            customUrlInput.style.display = 'block';
        }
        if (pageTypeSelect) {
            pageTypeSelect.style.display = 'none';
            pageTypeSelect.disabled = true;
        }
    } else if (savedValue && savedValue.type === 'page') {
        const { table, page } = savedValue.value;
        targetSelect.value = table;
        if (customUrlInput) customUrlInput.style.display = 'none';
        if (pageTypeSelect) {
            pageTypeSelect.style.display = 'block';
            pageTypeSelect.disabled = false;
            updatePageTypeDropdown(table);
            pageTypeSelect.value = page;
        }
    } else {
        targetSelect.value = 'dashboard';
        if (customUrlInput) customUrlInput.style.display = 'none';
        if (pageTypeSelect) {
            pageTypeSelect.style.display = 'none';
            pageTypeSelect.disabled = true;
        }
    }
}





// ── Central Save Button Listener ─────────────────────────────────────────
document.addEventListener('projectSave', (e) => {
    if (e.detail.module !== 'misc') return;

    // Gather all current settings from the UI
    const projectData = {
        regionalFormat: document.getElementById('projRegional')?.value || 'US',
        landingPage: getLandingPageValue(),
        mapProvider: document.getElementById('projMapProvider')?.value || 'google',
        mapApiKey: document.getElementById('projMapKey')?.value || '',
        errorReporting: document.getElementById('projErrorReporting')?.value || 'detailed',
        customErrorMessage: document.getElementById('projErrorMsg')?.value || '',
        darkMode: document.getElementById('projDarkMode')?.checked || false,
        gdprBanner: document.getElementById('projGDPR')?.checked || false,
        section508: document.getElementById('proj508')?.checked || false,
        showLanguageSelector: document.getElementById('projShowLangSelector')?.checked ?? true,
        liveTranslations: document.getElementById('projLiveTranslations')?.checked || false
    };

    const advancedData = {
        auditEnabled: document.getElementById('advAudit')?.checked || false,
        auditTable: document.getElementById('advAuditTable')?.value || '',
        recordLocking: document.getElementById('advLocking')?.checked || false,
        lockTable: document.getElementById('advLockTable')?.value || '',
        lockTimeout: parseInt(document.getElementById('advLockTimeout')?.value) || 300,
        exportWatermark: document.getElementById('advWatermark')?.value || '',
        notifEnabled: document.getElementById('notifEnableCheck')?.checked || false,
        notifTableName: document.getElementById('notifTableName')?.value || 'notifications'
    };

    const emailData = {
        provider: document.getElementById('emailProvider')?.value || '',
        host: document.getElementById('emailHost')?.value || '',
        port: document.getElementById('emailPort')?.value || 587,
        encryption: document.getElementById('emailEncryption')?.value || 'tls',
        username: document.getElementById('emailUser')?.value || '',
        password: document.getElementById('emailPass')?.value || '',
        fromAddress: document.getElementById('emailFrom')?.value || '',
        fromName: document.getElementById('emailFromName')?.value || ''
    };

    const smsData = { provider: document.getElementById('smsProvider')?.value || '' };
    document.querySelectorAll('#smsFields .sms-setting').forEach(el => {
        smsData[el.dataset.key] = el.value;
    });

    // Build the full misc state object
    const fullState = {
        project: projectData,
        advanced: advancedData,
        email: emailData,
        sms: smsData,
        byTable: currentConfig.byTable || {},
        languages: currentConfig.languages || []
    };

    e.detail.payload = fullState;
});

/* ============================================================
   Field tooltips — a plain-English "what does this do?" for every
   control across the Misc tabs. Keyed by element id; a small ⓘ icon is
   injected into each control's label (or onto the control itself when it
   has no label, e.g. buttons). Table-tab controls carry inline tooltips
   in table.js. Uses Bootstrap tooltips (Bootstrap JS is already loaded).
   ============================================================ */
const MISC_TOOLTIPS = {
    // ── Project ─────────────────────────────────────────────
    btnManageLanguages: "Add or remove the languages your app's labels and content can be translated into.",
    projRegional: "Sets number, date and currency formatting in the generated app to match the chosen country.",
    projLandingTarget: "The first page users see after signing in — the Dashboard, a specific table's page, or a custom URL.",
    projLandingPageType: "Which page of the selected table opens as the landing page (List, Add, View, …).",
    projLandingCustomUrl: "The address to open as the landing page — an external URL or an internal path (e.g. /reports).",
    projMapProvider: "Map engine used by map/location fields. Google needs an API key; Leaflet (OpenStreetMap) is free and keyless.",
    projMapKey: "API key for the chosen map provider. Required by Google Maps; leave blank for Leaflet or None.",
    projErrorReporting: "How errors appear in the built app: Detailed (full messages — development only), Generic (a safe message), or Suppressed.",
    projErrorMsg: "The friendly message shown to users when Error Reporting is set to 'Generic message'.",
    projDarkMode: "Offers a dark colour scheme in the generated app.",
    projGDPR: "Shows a cookie-consent banner in the generated app (EU GDPR).",
    proj508: "Adds accessibility features for Section 508 / WCAG compliance.",
    // ── Advanced ────────────────────────────────────────────
    advAudit: "Records every create / update / delete in the built app into the audit table below — a full activity history.",
    advAuditTable: "Database table that stores the audit trail (created automatically). Default: audit_log.",
    advLocking: "Stops two users editing the same record at once. Requires database authentication to be enabled.",
    advLockTable: "Database table that holds active edit-locks (created automatically). Default: record_locks.",
    advLockTimeout: "How long (in seconds) an edit-lock is held before it expires automatically. The browser renews it at half this interval.",
    advWatermark: "Text stamped onto exported / printed files as a confidentiality marker, e.g. “Confidential”.",
    advTimezone: "The timezone the entire generated app runs on — every date, time and stored timestamp uses it. The badge on the right shows its current UTC offset and local time.",
    notifEnableCheck: "Turns on in-app notifications in the generated app, stored in the table below.",
    notifTableName: "Database table where notifications are stored. Default: notifications.",
    // ── Email (SMTP) ────────────────────────────────────────
    emailProvider: "Pick a common provider to pre-fill the SMTP settings, or choose 'Custom SMTP' to enter your own server.",
    emailHost: "Address of the outgoing mail server, e.g. smtp.gmail.com.",
    emailPort: "SMTP port — usually 587 for TLS or 465 for SSL.",
    emailEncryption: "Connection security. TLS (port 587) is recommended for most providers.",
    emailUser: "The full email address used to log in to the mail server.",
    emailPass: "The SMTP password. For Gmail / Outlook create an 'app password' — do not use your normal login password.",
    emailFrom: "The address your emails appear to come from.",
    emailFromName: "The sender name recipients will see.",
    btnTestEmail: "Sends a test message with the settings above to confirm email is working.",
    // ── SMS ─────────────────────────────────────────────────
    smsProvider: "The SMS gateway used to send text messages from the generated app.",
    btnTestSms: "Sends a test text message using the selected provider's credentials.",
    btnAddCustomProvider: "Define your own SMS gateway by giving its API URL and parameter names.",
    // Custom-provider modal
    cpKey: "A unique internal id for this provider — letters/numbers, no spaces.",
    cpLabel: "The provider name shown in the SMS provider dropdown.",
    cpUrl: "The gateway's send-message API endpoint (URL).",
    cpMethod: "The HTTP method the gateway expects (POST or GET).",
    cpToParam: "The API parameter name the gateway uses for the recipient's phone number.",
    cpMsgParam: "The API parameter name the gateway uses for the message text.",
    cpFromParam: "The API parameter name the gateway uses for the sender id / number.",
    cpExtraParams: "Any fixed extra parameters the gateway needs, comma-separated (e.g. api_key=abc123,type=sms)."
};

// Inject the ⓘ icons + (re)initialise Bootstrap tooltips. Safe to call
// repeatedly (guards against duplicates) and after dynamic content renders.
function initMiscTooltips(root) {
    root = root || document;
    const scope = root.querySelectorAll ? root : document;
    Object.keys(MISC_TOOLTIPS).forEach(id => {
        const el = document.getElementById(id);
        if (!el || el.dataset.ttDone) return;
        el.dataset.ttDone = '1';
        const text = MISC_TOOLTIPS[id];
        const wrap = el.closest('.col-12,.col-md-6,.col-md-4,.col-md-3,.col-md-2,.col-8,.col-6,.mb-2,.mb-3,.form-check,.form-check-inline') || el.parentElement;
        const label = wrap && (wrap.querySelector('.form-label') || wrap.querySelector('.form-check-label') || wrap.querySelector('label'));
        if (label && !label.querySelector('.misc-hint')) {
            const i = document.createElement('i');
            i.className = 'bi bi-info-circle misc-hint';
            i.setAttribute('data-bs-toggle', 'tooltip');
            i.setAttribute('title', text);
            label.appendChild(document.createTextNode(' '));
            label.appendChild(i);
        } else if (!label) {
            el.setAttribute('data-bs-toggle', 'tooltip');
            el.setAttribute('title', text);
        }
    });
    if (window.bootstrap && bootstrap.Tooltip) {
        // Fast-loading: delay 0 + no fade animation so tips appear the instant
        // the pointer lands, matching the rest of the console.
        const TT_OPTS = { container: 'body', delay: 0, animation: false };
        scope.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
            if (!bootstrap.Tooltip.getInstance(el)) new bootstrap.Tooltip(el, TT_OPTS);
        });
        // `data-tt` = attach a tooltip to THIS element by its data-tt text, without
        // touching data-bs-toggle (used for tab pills that already toggle a tab).
        scope.querySelectorAll('[data-tt]').forEach(el => {
            if (!bootstrap.Tooltip.getInstance(el)) new bootstrap.Tooltip(el, Object.assign({ title: el.getAttribute('data-tt') }, TT_OPTS));
        });
    }
}
window.initMiscTooltips = initMiscTooltips;
