// ── Settings (core engine) ─────────────────────────────────────────
(function () {
    'use strict';

    const $ = (id) => document.getElementById(id);

    async function post(path, payload) {
        const res = await fetch(`${baseUrl}/settings/${path}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            credentials: 'same-origin',
            body: JSON.stringify(payload),
        });
        return res.json();
    }

    function toast(json) {
        Swal.fire({
            toast: true, position: 'top-end', timer: 2600, showConfirmButton: false,
            icon: json && json.success ? 'success' : 'error',
            title: (json && json.message) || 'Something went wrong.',
        });
    }

    // ── Tabs ───────────────────────────────────────────────────────
    document.querySelectorAll('.set-tab').forEach((tab) => {
        tab.addEventListener('click', () => {
            const name = tab.dataset.tab;
            // Link tabs (e.g. Storage) navigate to their own page — let the browser follow the href.
            if (!name) return;
            document.querySelectorAll('.set-tab').forEach((t) => t.classList.toggle('active', t === tab));
            document.querySelectorAll('.set-pane').forEach((p) => { p.hidden = p.dataset.pane !== name; });
            // Keep the tab in the URL so a refresh stays put.
            const url = new URL(window.location.href);
            url.searchParams.set('tab', name);
            history.replaceState(null, '', url);
        });
    });

    // ── Email: provider presets drive host/port/encryption + the modern
    //    auth story (app password / API key), setup link and cautions ──
    function applyPreset(showHelpOnly) {
        const key = $('emProvider').value;
        const p = presets[key];
        if (!p) return;

        $('emProviderHelp').textContent = p.help || '';

        const docs = $('emProviderDocs');
        if (docs) {
            if (p.docsUrl) { docs.href = p.docsUrl; docs.textContent = '↗ ' + (p.docsLabel || 'Setup guide'); docs.hidden = false; }
            else docs.hidden = true;
        }
        const warn = $('emProviderWarn');
        if (warn) {
            if (p.warn) { warn.textContent = p.warn; warn.hidden = false; }
            else warn.hidden = true;
        }

        // Labels reflect what the provider actually wants in each field.
        if ($('emPassLabel')) $('emPassLabel').textContent = p.passwordLabel || 'Password';
        if ($('emUserLabel')) $('emUserLabel').textContent = p.usernameLabel || 'Username';
        if ($('emUserHint')) $('emUserHint').textContent = p.usernameHint || '';
        if ($('emPassHint')) {
            const noun = p.auth === 'api_key' ? 'API key' : (p.auth === 'app_password' ? 'app password' : 'password');
            $('emPassHint').textContent = 'Leave blank to keep the saved ' + noun + '.';
        }

        // Providers that mandate a literal username (SendGrid “apikey”, Resend “resend”).
        if (p.usernameFixed) { $('emUser').value = p.usernameFixed; $('emUser').readOnly = true; }
        else { $('emUser').readOnly = false; }

        // OAuth 2.0 capability (Gmail → Google, Outlook/365 → Microsoft).
        const provOauth = p.oauth || '';
        window._emOauthProvider = provOauth;
        const wrap = $('emAuthMethodWrap');
        if (wrap) wrap.hidden = !provOauth;
        if ($('emOauthProviderName')) $('emOauthProviderName').textContent =
            provOauth === 'google' ? 'Google' : (provOauth === 'microsoft' ? 'Microsoft' : 'your provider');
        if (!provOauth && $('emAuthBasic')) $('emAuthBasic').checked = true;  // no OAuth here → force basic
        updateAuthMode();

        if (showHelpOnly) return;         // on load: update guidance, keep saved host/port
        if (key === 'custom') return;
        $('emHost').value = p.host || '';
        $('emPort').value = p.port || 587;
        $('emEncryption').value = p.encryption || 'tls';
    }
    // Toggle the basic-auth fields vs the OAuth panel based on the chosen method.
    function updateAuthMode() {
        const oauthRadio = document.getElementById('emAuthOauth');
        const wrap = $('emAuthMethodWrap');
        const useOauth = !!(oauthRadio && oauthRadio.checked && wrap && !wrap.hidden);
        // Scope to the PRIMARY card so the fallback cards' [data-basic-auth] fields aren't touched.
        const primary = document.querySelector('.mail-server[data-slot="0"]') || document;
        primary.querySelectorAll('[data-basic-auth]').forEach((el) => { el.hidden = useOauth; });
        if ($('emOauthPanel')) $('emOauthPanel').hidden = !useOauth;
    }
    document.querySelectorAll('input[name="emAuthType"]').forEach((r) => r.addEventListener('change', updateAuthMode));
    $('emOauthCopy')?.addEventListener('click', () => {
        const inp = $('emOauthRedirect');
        if (inp) { inp.select(); try { navigator.clipboard.writeText(inp.value); } catch (x) {} }
    });
    $('emOauthConnect')?.addEventListener('click', (e) => {
        if (!($('emOauthClientId')?.value.trim())) {
            e.preventDefault();
            Swal.fire('Add your Client ID', 'Enter the OAuth Client ID and click Save before connecting the mailbox.', 'info');
        }
    });
    $('emProvider')?.addEventListener('change', () => applyPreset(false));
    applyPreset(true); // on load: show the provider's guidance, don't clobber saved values

    // Toast the OAuth callback result (?oauth=connected|error|norefresh|needsetup).
    (function () {
        const o = new URLSearchParams(location.search).get('oauth');
        const map = {
            connected: ['success', 'Mailbox connected', 'Your mailbox is connected via OAuth and ready to send.'],
            error: ['error', 'Connection failed', 'The sign-in was cancelled or expired — please try again.'],
            norefresh: ['error', 'No refresh token', 'The provider did not return a refresh token. Re-try and grant offline access (you may need to remove the app’s previous consent first).'],
            needsetup: ['info', 'Save first', 'Enter and save your OAuth Client ID and secret before connecting.'],
        };
        if (o && map[o]) Swal.fire({ icon: map[o][0], title: map[o][1], text: map[o][2] });
    })();

    // ── Collect + save the whole email config (primary + fallbacks) ──
    function cardVerified(slot) {
        const c = document.querySelector(`.mail-server[data-slot="${slot}"]`);
        return !!(c && c.dataset.verified === '1');
    }
    function collectFallback(i) {
        const card = document.querySelector(`.mail-server[data-slot="${i + 1}"]`);
        const g = (key) => document.querySelector(`[data-fb="${i}"][data-fb-key="${key}"]`);
        const authRadio = card ? card.querySelector('.mail-auth:checked') : null;
        const authType = authRadio ? authRadio.value : 'basic';
        const prov = g('provider')?.value || 'custom';
        const preset = presets[prov] || {};
        return {
            provider: prov,
            host: g('host')?.value.trim() || '',
            port: g('port')?.value || '587',
            encryption: g('encryption')?.value || 'tls',
            username: g('username')?.value.trim() || '',
            password: g('password')?.value || '',
            fromAddress: g('fromAddress')?.value.trim() || '',
            authType,
            oauthProvider: authType === 'xoauth2' ? (preset.oauth || '') : '',
            oauthClientId: g('oauthClientId')?.value.trim() || '',
            oauthClientSecret: g('oauthClientSecret')?.value || '',
            verified: cardVerified(i + 1),
        };
    }
    function collectEmailData() {
        const data = {
            provider: $('emProvider').value,
            host: $('emHost').value.trim(),
            port: $('emPort').value,
            encryption: $('emEncryption').value,
            username: $('emUser').value.trim(),
            password: $('emPass').value,
            fromAddress: $('emFrom').value.trim(),
            fromName: $('emFromName').value.trim(),
            appName: $('emAppName').value.trim(),
            ownerEmail: $('emOwner').value.trim(),
            verified: cardVerified(0),
        };
        data.fallbacks = [collectFallback(0), collectFallback(1)];
        const authOauth = document.getElementById('emAuthOauth');
        const useOauth = !!(authOauth && authOauth.checked && !$('emAuthMethodWrap').hidden);
        data.authType = useOauth ? 'xoauth2' : 'basic';
        if (useOauth) {
            data.oauthProvider = window._emOauthProvider || '';
            data.oauthClientId = $('emOauthClientId')?.value.trim() || '';
            data.oauthClientSecret = $('emOauthSecret')?.value || '';
        }
        return { data, useOauth };
    }
    async function saveEmail(showToast) {
        const { data, useOauth } = collectEmailData();
        if (!useOauth && (!data.host || !data.fromAddress)) {
            Swal.fire('Almost there', 'The primary server needs an SMTP host and a From address (or switch it to OAuth).', 'warning');
            return false;
        }
        const json = await post('save', { section: 'email', data });
        if (showToast) toast(json);
        return !!(json && json.success);
    }
    $('btnSaveEmail')?.addEventListener('click', async () => {
        if (await saveEmail(true)) setTimeout(() => window.location.reload(), 900);
    });

    $('btnTestEmail')?.addEventListener('click', async () => {
        const { value: to } = await Swal.fire({
            title: 'Send a test email',
            input: 'email',
            inputLabel: 'Where should we send it?',
            inputPlaceholder: 'you@example.com',
            showCancelButton: true,
            confirmButtonText: 'Send test',
            reverseButtons: true,
        });
        if (!to) return;
        Swal.fire({ title: 'Sending…', allowOutsideClick: false, didOpen: () => Swal.showLoading() });
        const json = await post('test-email', { to });
        Swal.fire({
            icon: json.success ? 'success' : 'error',
            title: json.success ? 'Test sent' : 'Could not send',
            text: json.message,
        });
    });

    // ── Mail server cards: fold, edit/unlock, per-server test & lock ──
    function setBadge(card, kind, icon, text) {
        const b = card.querySelector('.mail-badge');
        if (b) b.className = 'badge text-bg-' + kind + ' mail-badge', b.innerHTML = '<i class="bi bi-' + icon + ' me-1"></i><span class="mail-badge-text">' + text + '</span>';
    }
    function setFolded(card, folded) {
        const body = card.querySelector('.mail-server-body');
        const chev = card.querySelector('.mail-chevron');
        if (body) body.hidden = folded;
        if (chev) chev.className = 'bi bi-chevron-' + (folded ? 'down' : 'up') + ' mail-chevron';
    }
    function setLocked(card, locked) {
        card.dataset.verified = locked ? '1' : '0';
        const fs = card.querySelector('.mail-fields'); if (fs) fs.disabled = locked;
        const edit = card.querySelector('.mail-edit'); if (edit) edit.hidden = !locked;
        setFolded(card, locked);
        if (locked) setBadge(card, 'success', 'check-circle-fill', 'Verified');
        else setBadge(card, 'warning', 'exclamation-circle', 'Not tested');
    }
    document.querySelectorAll('.mail-server').forEach((card) => {
        card.querySelector('.mail-server-head')?.addEventListener('click', (e) => {
            if (e.target.closest('.mail-edit')) return;   // handled below
            const body = card.querySelector('.mail-server-body');
            if (body) setFolded(card, !body.hidden);
        });
        card.querySelector('.mail-edit')?.addEventListener('click', (e) => {
            e.stopPropagation();
            setLocked(card, false);   // unlock + mark "Not tested"
            setFolded(card, false);
        });
        card.querySelector('.mail-test')?.addEventListener('click', async () => {
            const slot = parseInt(card.dataset.slot, 10) || 0;
            const { value: to } = await Swal.fire({
                title: 'Test & lock this server', input: 'email', inputLabel: 'Send a test email to',
                inputPlaceholder: 'you@example.com', showCancelButton: true, confirmButtonText: 'Save, test & lock', reverseButtons: true,
            });
            if (!to) return;
            Swal.fire({ title: 'Saving & testing…', allowOutsideClick: false, didOpen: () => Swal.showLoading() });
            if (!(await saveEmail(false))) { Swal.fire('Could not save', 'Please fix the highlighted fields and try again.', 'error'); return; }
            const json = await post('test-server', { slot, to });
            if (json && json.success) { setLocked(card, true); Swal.fire({ icon: 'success', title: 'Verified & locked', text: json.message }); }
            else Swal.fire({ icon: 'error', title: 'Test failed', text: (json && json.message) || 'Could not send.' });
        });
    });

    // ── Fallback cards: provider preset + OAuth toggle (scoped per card) ──
    function updateFallbackAuthMode(card) {
        const oauth = card.querySelector('.mail-auth[value="xoauth2"]');
        const wrap = card.querySelector('.mail-authmethod');
        const useOauth = !!(oauth && oauth.checked && wrap && !wrap.hidden);
        card.querySelectorAll('[data-basic-auth]').forEach((el) => { el.hidden = useOauth; });
        const panel = card.querySelector('.mail-oauth-panel'); if (panel) panel.hidden = !useOauth;
    }
    function applyFallbackPreset(card) {
        const sel = card.querySelector('[data-fb-key="provider"]');
        if (!sel) return;
        const p = presets[sel.value] || {};
        const q = (s) => card.querySelector(s);
        if (q('.mail-help')) q('.mail-help').textContent = p.help || '';
        const docs = q('.mail-docs');
        if (docs) { if (p.docsUrl) { docs.href = p.docsUrl; docs.textContent = '↗ ' + (p.docsLabel || 'Setup guide'); docs.hidden = false; } else docs.hidden = true; }
        const authWrap = q('.mail-authmethod');
        if (authWrap) authWrap.hidden = !p.oauth;
        if (q('.mail-oauth-name')) q('.mail-oauth-name').textContent = p.oauth === 'google' ? 'Google' : (p.oauth === 'microsoft' ? 'Microsoft' : 'OAuth');
        if (!p.oauth) { const b = card.querySelector('.mail-auth[value="basic"]'); if (b) b.checked = true; }
        const userInput = q('[data-fb-key="username"]');
        if (userInput) { if (p.usernameFixed) { userInput.value = p.usernameFixed; userInput.readOnly = true; } else userInput.readOnly = false; }
        updateFallbackAuthMode(card);
    }
    document.querySelectorAll('.mail-server[data-slot]:not([data-slot="0"])').forEach((card) => {
        const sel = card.querySelector('[data-fb-key="provider"]');
        sel?.addEventListener('change', () => {
            const p = presets[sel.value] || {};
            if (sel.value !== 'custom' && p.host) {
                const set = (k, val) => { const el = card.querySelector(`[data-fb-key="${k}"]`); if (el) el.value = val; };
                set('host', p.host); set('port', p.port || 587); set('encryption', p.encryption || 'tls');
            }
            applyFallbackPreset(card);
        });
        card.querySelectorAll('.mail-auth').forEach((r) => r.addEventListener('change', () => updateFallbackAuthMode(card)));
        card.querySelector('.mail-copy')?.addEventListener('click', () => {
            const inp = card.querySelector('.mail-redirect'); if (inp) { inp.select(); try { navigator.clipboard.writeText(inp.value); } catch (x) {} }
        });
        card.querySelector('.mail-connect')?.addEventListener('click', (e) => {
            if (!(card.querySelector('[data-fb-key="oauthClientId"]')?.value.trim())) {
                e.preventDefault();
                Swal.fire('Add your Client ID', 'Enter the OAuth Client ID and Save before connecting this fallback.', 'info');
            }
        });
        applyFallbackPreset(card);   // on load
    });

    // ── Retry queue ────────────────────────────────────────────────
    async function runQueue(body, label) {
        Swal.fire({ title: label, allowOutsideClick: false, didOpen: () => Swal.showLoading() });
        const json = await post('mail-queue', body);
        if (json && typeof json.pending !== 'undefined') $('mqPending').textContent = json.pending;
        if (json && typeof json.failed !== 'undefined') $('mqFailed').textContent = json.failed;
        Swal.fire({ icon: json.success ? 'success' : 'error', title: json.success ? 'Queue processed' : 'Could not process', text: json.message });
    }
    $('btnProcessQueue')?.addEventListener('click', () => runQueue({}, 'Processing…'));
    $('btnRetryFailed')?.addEventListener('click', () => runQueue({ action: 'retry-failed' }, 'Re-queuing failed…'));

    // ── Templates ──────────────────────────────────────────────────
    let lastFocused = null;
    document.querySelectorAll('.tmpl-subject, .tmpl-body').forEach((el) => {
        el.addEventListener('focus', () => { lastFocused = el; });
    });
    document.querySelectorAll('.ph-chip').forEach((chip) => {
        chip.addEventListener('click', () => {
            const ph = chip.dataset.ph;
            if (!lastFocused) {
                Swal.fire({ toast: true, position: 'top-end', timer: 2000, showConfirmButton: false, icon: 'info', title: 'Click into a field first, then pick a placeholder.' });
                return;
            }
            const start = lastFocused.selectionStart ?? lastFocused.value.length;
            const end = lastFocused.selectionEnd ?? lastFocused.value.length;
            lastFocused.value = lastFocused.value.slice(0, start) + ph + lastFocused.value.slice(end);
            lastFocused.focus();
            lastFocused.selectionStart = lastFocused.selectionEnd = start + ph.length;
        });
    });

    $('btnSaveTemplates')?.addEventListener('click', async () => {
        const data = {};
        document.querySelectorAll('[data-tmpl]').forEach((card) => {
            data[card.dataset.tmpl] = {
                subject: card.querySelector('.tmpl-subject').value,
                body: card.querySelector('.tmpl-body').value,
                enabled: card.querySelector('.tmpl-enabled').checked,
            };
        });
        toast(await post('save', { section: 'templates', data }));
    });

    // Reflect a card's on/off state in the UI.
    function paintSwitch(card) {
        const on = card.querySelector('.tmpl-enabled').checked;
        card.classList.toggle('is-off', !on);
        card.dataset.enabled = on ? '1' : '0';
        const lbl = card.querySelector('.tmpl-switch-lbl');
        if (lbl) lbl.textContent = on ? 'On' : 'Off';
    }

    // Switch: enable/disable a single template immediately (independent of edits).
    document.querySelectorAll('.tmpl-enabled').forEach((sw) => {
        sw.addEventListener('change', async () => {
            const card = sw.closest('[data-tmpl]');
            const key = card.dataset.tmpl;
            const enabled = sw.checked;
            paintSwitch(card);
            const json = await post('toggle-template', { key, enabled });
            toast(json);
            if (!json || !json.success) { sw.checked = !enabled; paintSwitch(card); } // revert on failure
        });
    });

    // Mark a card "edited" as soon as its content diverges from the saved default.
    document.querySelectorAll('.tmpl-subject, .tmpl-body').forEach((el) => {
        el.addEventListener('input', () => {
            const tag = el.closest('[data-tmpl]')?.querySelector('[data-role="edited"]');
            if (tag) tag.hidden = false;
        });
    });

    // Reset a single template to its shipped default (content + switched back on).
    document.querySelectorAll('.btn-reset').forEach((btn) => {
        btn.addEventListener('click', async () => {
            const card = btn.closest('[data-tmpl]');
            const key = btn.dataset.key;
            const label = card.querySelector('.tmpl-titles h6')?.childNodes[0]?.textContent.trim() || 'this template';
            const res = await Swal.fire({
                title: 'Reset to default?',
                html: `<b>${label}</b> will be restored to its original subject and message.<br>Your current edits to it will be discarded.`,
                icon: 'warning',
                showCancelButton: true,
                confirmButtonText: 'Yes, reset it',
                confirmButtonColor: '#dc3545',
                reverseButtons: true,
            });
            if (!res.isConfirmed) return;
            const json = await post('reset-template', { key });
            if (json && json.success) {
                card.querySelector('.tmpl-subject').value = json.subject || '';
                card.querySelector('.tmpl-body').value = json.body || '';
                const en = card.querySelector('.tmpl-enabled');
                en.checked = true; paintSwitch(card);
                const tag = card.querySelector('[data-role="edited"]');
                if (tag) tag.hidden = true;
            }
            toast(json);
        });
    });

    // Preview shows the SAVED template, so save first if there are edits pending.
    document.querySelectorAll('.btn-preview').forEach((btn) => {
        btn.addEventListener('click', () => {
            const key = btn.dataset.key;
            Swal.fire({
                title: 'Email preview',
                width: 680,
                html: `<iframe src="${baseUrl}/settings/preview/${encodeURIComponent(key)}"
                              sandbox="" title="Email preview"
                              style="width:100%;height:60vh;border:1px solid rgba(128,128,128,.3);border-radius:10px;background:#fff"></iframe>
                       <p style="margin:10px 0 0;font-size:12px;opacity:.7">Preview uses sample data and shows the last <strong>saved</strong> version.</p>`,
                showConfirmButton: true,
                confirmButtonText: 'Close',
            });
        });
    });

    // ── SMS ────────────────────────────────────────────────────────
    $('btnSaveSms')?.addEventListener('click', async () => {
        const json = await post('save', {
            section: 'sms',
            data: { provider: $('smProvider').value.trim(), api_token: $('smToken').value, from: $('smFrom').value.trim() },
        });
        toast(json);
        if (json.success) { $('smToken').value = ''; $('smToken').placeholder = '•••••••• (saved)'; }
    });
}());
