{{define "webmail_settings_style"}}
<style>
    .settings-card { width: 96vw; max-width: 1600px; height: 92vh; margin: 4vh auto; background-color: #2d2d2d; border: 1px solid #404040; border-radius: 12px; box-shadow: 0 1rem 3rem rgba(0,0,0,.5); overflow: hidden; display: flex; flex-direction: column; }
    .settings-card-header { flex: 0 0 auto; padding: 1rem 1.25rem; border-bottom: 1px solid #404040; display: flex; align-items: center; justify-content: space-between; }
    .settings-card-body { flex: 1 1 auto; display: flex; align-items: stretch; min-height: 0; }
    .settings-nav { width: 210px; flex: 0 0 210px; border-right: 1px solid #404040; padding: .75rem; overflow-y: auto; }
    .settings-nav .nav-link { color: #c8c8c8; border-radius: 6px; padding: .5rem .75rem; margin-bottom: .15rem; font-size: .9rem; }
    .settings-nav .nav-link:hover { background-color: #383838; color: #fff; }
    .settings-nav .nav-link.active { background-color: #0d6efd; color: #fff; }
    .settings-body { flex: 1 1 auto; padding: 1.25rem 1.5rem; overflow-y: auto; min-width: 0; }
    .settings-body h5, .settings-body h6 { font-size: .95rem; }
    .settings-body .card { background-color: #262626; border: 1px solid #404040; }
    .settings-body .card-header { padding: .5rem .9rem; }
    .settings-body .card-body { padding: .75rem .9rem; }
    .settings-body .mb-4 { margin-bottom: .9rem !important; }
    .settings-body .mb-3 { margin-bottom: .6rem !important; }
    .sig-preview { background-color: #fff; color: #000; border-radius: 6px; padding: .75rem; max-height: 140px; overflow: hidden; }
    #sigEditor { height: 160px; background-color: #fff; color: #000; }
    .ql-toolbar.ql-snow { background-color: #333; border-color: #404040; border-top-left-radius: .375rem; border-top-right-radius: .375rem; }
    .ql-container.ql-snow { border-color: #404040; border-bottom-left-radius: .375rem; border-bottom-right-radius: .375rem; }
    .ql-snow .ql-stroke { stroke: #c8c8c8; }
    .ql-snow .ql-fill, .ql-snow .ql-stroke.ql-fill { fill: #c8c8c8; }
    .ql-snow .ql-picker { color: #c8c8c8; }
    .ql-snow .ql-picker-options { background-color: #2d2d2d; border-color: #404040; }
    .ql-snow .ql-picker-item { color: #c8c8c8; }
</style>
{{end}}

{{define "webmail_settings_nav"}}
<div class="settings-nav">
    <div class="nav flex-column nav-pills" id="settingsNav">
        <a class="nav-link{{if eq .active_section "account"}} active{{end}}" href="/webmail/account" data-settings-nav><i class="bi bi-gear me-2"></i>Account</a>
        <a class="nav-link{{if eq .active_section "rules"}} active{{end}}" href="/webmail/rules" data-settings-nav><i class="bi bi-funnel me-2"></i>Rules</a>
        <a class="nav-link{{if eq .active_section "signatures"}} active{{end}}" href="/webmail/signatures" data-settings-nav><i class="bi bi-pen me-2"></i>Signatures</a>
        <a class="nav-link{{if eq .active_section "contacts"}} active{{end}}" href="/webmail/contacts" data-settings-nav><i class="bi bi-person-lines-fill me-2"></i>Contacts</a>
        <a class="nav-link{{if eq .active_section "blocklist"}} active{{end}}" href="/webmail/blocklist" data-settings-nav><i class="bi bi-slash-circle me-2"></i>Blocklist</a>
        <a class="nav-link{{if eq .active_section "certs"}} active{{end}}" href="/webmail/certs" data-settings-nav><i class="bi bi-shield-lock me-2"></i>Certificates</a>
    </div>
</div>
{{end}}

{{define "webmail_settings_script"}}
<script>
    function closeSettings() { window.location = '/webmail/mail/INBOX'; }

    // --- Section switching -------------------------------------------------
    // Each nav link is a real <a href> (direct links / reload / no-JS all still
    // work — the destination is a normal server-rendered page), but a click
    // instead fetches that page and swaps in just its #settingsPanel (nav+body
    // together, so the destination page's own active-state highlighting comes
    // along for free) rather than navigating away. Delegated on
    // #settingsPanelRoot so it keeps working after the panel itself gets
    // replaced.
    document.addEventListener('DOMContentLoaded', function() {
        var root = document.getElementById('settingsPanelRoot');
        if (!root) return;
        root.addEventListener('click', function(e) {
            var link = e.target.closest('[data-settings-nav]');
            if (!link) return;
            e.preventDefault();
            if (link.classList.contains('active')) return;
            fetch(link.href)
                .then(function(resp) { return resp.text(); })
                .then(function(html) {
                    var doc = new DOMParser().parseFromString(html, 'text/html');
                    var panel = doc.getElementById('settingsPanel');
                    if (!panel) { window.location = link.href; return; }
                    root.innerHTML = panel.outerHTML;
                    window.history.pushState(null, '', link.href);
                    window.__applyCsrfToForms && window.__applyCsrfToForms(root);
                    initSettingsSection();
                })
                .catch(function() { window.location = link.href; });
        });
        window.addEventListener('popstate', function() { window.location.reload(); });
    });
    document.addEventListener('keydown', function(e) { if (e.key === 'Escape') closeSettings(); });

    // --- Toasts + confirm dialogs (delegated — survive section swaps) ------
    document.addEventListener('DOMContentLoaded', function() {
        document.querySelectorAll('.toast').forEach(function(el) { new bootstrap.Toast(el, {delay: 5000}).show(); });
    });
    function showConfirmation(message) {
        return new Promise((resolve) => {
            var modal = document.getElementById('confirmationModal');
            document.getElementById('confirmationModalBody').textContent = message;
            var confirmButton = document.getElementById('confirmationModalConfirm');
            var handleConfirm = () => { resolve(true); bootstrap.Modal.getInstance(modal).hide(); cleanup(); };
            var handleCancel = () => { resolve(false); cleanup(); };
            var cleanup = () => {
                confirmButton.removeEventListener('click', handleConfirm);
                modal.removeEventListener('hidden.bs.modal', handleCancel);
            };
            confirmButton.addEventListener('click', handleConfirm);
            modal.addEventListener('hidden.bs.modal', handleCancel, { once: true });
            new bootstrap.Modal(modal).show();
        });
    }
    document.addEventListener('click', function(e) {
        var button = e.target.closest('[data-confirm]');
        if (!button) return;
        e.preventDefault();
        showConfirmation(button.getAttribute('data-confirm')).then(function(ok) {
            if (ok) { var form = button.closest('form'); if (form) form.submit(); }
        });
    });

    // --- Section-specific init, re-run after every swap ---------------------
    function initSettingsSection() {
        initRulesSection();
        initSignaturesSection();
        initAccountSection();
        initContactsSection();
    }

    // Fixed-choice condition fields don't take free text — has_attachment is a
    // yes/no question, recipient_type mirrors Outlook's "I'm on the Cc line" (this
    // delivery's own to/cc/bcc-ness, computed server-side per recipient — see
    // smtpserver's deliverLocally). Both always match via "equals".
    var RULE_FIXED_FIELD_OPTIONS = {
        has_attachment: [['yes', 'Yes'], ['no', 'No']],
        recipient_type: [['to', 'To'], ['cc', 'Cc'], ['bcc', 'Bcc']],
    };

    // A minimal tag/chip input: type a value, press Enter or comma to commit it as a
    // chip. Several chips in one condition mean "matches any of these" (an OR within
    // that single condition) — see mailstore.matchCondition, which reads the "\n"-
    // joined hidden value this maintains.
    function createChipInput(container, hiddenInput, initialValues) {
        container.innerHTML = '';
        var entry = document.createElement('input');
        entry.type = 'text';
        entry.style.cssText = 'border:0; outline:none; background:transparent; flex:1 1 80px; min-width:80px; color:inherit;';
        entry.placeholder = 'Type a value, press Enter';

        function sync() {
            var chips = Array.prototype.slice.call(container.querySelectorAll('.chip-item')).map(function(c) { return c.dataset.value; });
            hiddenInput.value = chips.join('\n');
        }
        function addChip(value) {
            value = value.trim();
            if (!value) return;
            var chip = document.createElement('span');
            chip.className = 'badge text-bg-secondary d-inline-flex align-items-center gap-1 chip-item';
            chip.dataset.value = value;
            var label = document.createElement('span');
            label.textContent = value;
            var x = document.createElement('i');
            x.className = 'bi bi-x';
            x.addEventListener('click', function() { chip.remove(); sync(); });
            chip.appendChild(label);
            chip.appendChild(x);
            container.insertBefore(chip, entry);
            sync();
        }
        entry.addEventListener('keydown', function(e) {
            if (e.key === 'Enter' || e.key === ',') {
                e.preventDefault();
                addChip(entry.value);
                entry.value = '';
            } else if (e.key === 'Backspace' && entry.value === '') {
                var last = container.querySelector('.chip-item:last-of-type');
                if (last) { last.remove(); sync(); }
            }
        });
        entry.addEventListener('blur', function() {
            if (entry.value.trim()) { addChip(entry.value); entry.value = ''; }
        });
        container.appendChild(entry);
        (initialValues || []).forEach(addChip);
    }

    // Swaps a condition row's value UI between the chip input (free-text fields) and
    // a fixed select (has_attachment/recipient_type), keeping the row's single
    // .cond-value-hidden input authoritative either way — the server only ever sees
    // one condition_value per row regardless of which widget produced it.
    function updateConditionRowUI(row, initialValue) {
        var field = row.querySelector('.cond-field').value;
        var opWrap = row.querySelector('.cond-op-wrap');
        var opSelect = row.querySelector('.cond-op');
        var chipWrap = row.querySelector('.chip-input');
        var fixedSelect = row.querySelector('.cond-fixed-select');
        var hidden = row.querySelector('.cond-value-hidden');
        var fixedOptions = RULE_FIXED_FIELD_OPTIONS[field];
        if (fixedOptions) {
            opSelect.value = 'equals';
            opWrap.classList.add('d-none');
            chipWrap.classList.add('d-none');
            fixedSelect.classList.remove('d-none');
            fixedSelect.innerHTML = '';
            fixedOptions.forEach(function(pair) {
                var o = document.createElement('option');
                o.value = pair[0]; o.textContent = pair[1];
                fixedSelect.appendChild(o);
            });
            if (initialValue) fixedSelect.value = initialValue;
            hidden.value = fixedSelect.value;
            fixedSelect.onchange = function() { hidden.value = fixedSelect.value; };
        } else {
            opWrap.classList.remove('d-none');
            chipWrap.classList.remove('d-none');
            fixedSelect.classList.add('d-none');
            createChipInput(chipWrap, hidden, initialValue ? initialValue.split('\n') : []);
        }
    }

    function initRulesSection() {
        var addBtn = document.getElementById('add_condition');
        if (!addBtn || addBtn.dataset.wired) return;
        addBtn.dataset.wired = '1';
        var container = document.getElementById('conditions_container');

        function addConditionRow(condition) {
            var tpl = document.getElementById('condition_row_template');
            var clone = document.importNode(tpl.content, true);
            var row = clone.querySelector('.condition-row');
            row.querySelector('.remove-condition').addEventListener('click', function() {
                if (container.children.length > 1) row.remove();
            });
            container.appendChild(clone);
            if (condition) {
                row.querySelector('.cond-field').value = condition.field;
                row.querySelector('.cond-op').value = condition.op;
            }
            updateConditionRowUI(row, condition ? condition.value : null);
            row.querySelector('.cond-field').addEventListener('change', function() { updateConditionRowUI(row, null); });
        }
        addBtn.addEventListener('click', function() { addConditionRow(null); });

        var seedData = [];
        var seedEl = document.getElementById('editingConditionsData');
        if (seedEl) {
            try { seedData = JSON.parse(seedEl.textContent) || []; } catch (e) { seedData = []; }
        }
        if (seedData.length) {
            seedData.forEach(addConditionRow);
        } else {
            addConditionRow(null);
        }

        var actionSelect = document.getElementById('rule_action');
        var folderInput = document.getElementById('rule_action_value_folder');
        var forwardInput = document.getElementById('rule_action_value_forward');
        function updateActionFields() {
            var action = actionSelect.value;
            document.querySelectorAll('.action-extra-fields > div').forEach(function(el) { el.style.display = 'none'; });
            var shown = document.querySelector('.action-field-' + action);
            if (shown) shown.style.display = 'block';
            folderInput.disabled = action !== 'move_to_folder';
            forwardInput.disabled = action !== 'forward';
        }
        if (actionSelect) {
            actionSelect.addEventListener('change', updateActionFields);
            updateActionFields();
        }
    }

    function initSignaturesSection() {
        var editorEl = document.getElementById('sigEditor');
        var modalEl = document.getElementById('sigModal');
        if (!editorEl || !modalEl) return;
        var sigQuill = new Quill('#sigEditor', {
            theme: 'snow',
            modules: { toolbar: [['bold', 'italic', 'underline'], [{ color: [] }], ['link', 'image'], ['clean']] },
        });
        document.getElementById('sigForm').addEventListener('submit', function() {
            document.querySelector('[name="content_html"]').value = sigQuill.root.innerHTML;
        });

        function resetAliasDefaultFields() {
            var emailSel = modalEl.querySelector('[name="default_for_email"]');
            var newChk = document.getElementById('sigDefaultNewAlias');
            var replyChk = document.getElementById('sigDefaultReplyAlias');
            if (emailSel) emailSel.value = '';
            if (newChk) newChk.checked = false;
            if (replyChk) replyChk.checked = false;
        }

        var addBtn = document.getElementById('sigAddBtn');
        if (addBtn) {
            addBtn.addEventListener('click', function() {
                document.getElementById('sigModalTitle').textContent = 'New signature';
                document.getElementById('sigFormId').value = '';
                document.getElementById('sigFormName').value = '';
                sigQuill.setText('');
                resetAliasDefaultFields();
                new bootstrap.Modal(modalEl).show();
            });
        }

        document.querySelectorAll('.sig-edit-btn').forEach(function(btn) {
            btn.addEventListener('click', function() {
                var card = btn.closest('.sig-card');
                document.getElementById('sigModalTitle').textContent = 'Edit signature';
                document.getElementById('sigFormId').value = card.dataset.sigId;
                document.getElementById('sigFormName').value = card.dataset.sigName;
                var content = card.querySelector('.sig-content-data');
                sigQuill.root.innerHTML = content ? content.innerHTML : '';
                resetAliasDefaultFields();
                new bootstrap.Modal(modalEl).show();
            });
        });
    }

    function initContactsSection() {
        var modalEl = document.getElementById('contactModal');
        if (!modalEl) return;

        var addBtn = document.getElementById('contactAddBtn');
        if (addBtn) {
            addBtn.addEventListener('click', function() {
                document.getElementById('contactModalTitle').textContent = 'New contact';
                document.getElementById('contactFormId').value = '';
                document.getElementById('contactFormName').value = '';
                document.getElementById('contactFormEmail').value = '';
                document.getElementById('contactFormPhone').value = '';
                new bootstrap.Modal(modalEl).show();
            });
        }

        document.querySelectorAll('.contact-edit-btn').forEach(function(btn) {
            btn.addEventListener('click', function() {
                var row = btn.closest('.contact-row');
                document.getElementById('contactModalTitle').textContent = 'Edit contact';
                document.getElementById('contactFormId').value = row.dataset.contactId;
                document.getElementById('contactFormName').value = row.dataset.contactName;
                document.getElementById('contactFormEmail').value = row.dataset.contactEmail;
                document.getElementById('contactFormPhone').value = row.dataset.contactPhone;
                new bootstrap.Modal(modalEl).show();
            });
        });
    }

    function b64urlToBuf(s) {
        s = s.replace(/-/g, '+').replace(/_/g, '/');
        while (s.length % 4) s += '=';
        var bin = atob(s);
        var buf = new Uint8Array(bin.length);
        for (var i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i);
        return buf.buffer;
    }
    function bufToB64url(buf) {
        var bytes = new Uint8Array(buf);
        var bin = '';
        bytes.forEach(b => bin += String.fromCharCode(b));
        return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
    }
    function initAccountSection() {
        var passkeyAddBtn = document.getElementById('passkey-add-btn');
        if (!passkeyAddBtn) return;
        passkeyAddBtn.addEventListener('click', async function() {
            var errEl = document.getElementById('passkey-error');
            errEl.classList.add('d-none');
            try {
                var beginResp = await fetch('/webmail/account/passkey/begin', { method: 'POST' });
                if (!beginResp.ok) throw new Error((await beginResp.json()).error || 'Could not start passkey registration');
                var options = await beginResp.json();
                var publicKey = options.publicKey;
                publicKey.challenge = b64urlToBuf(publicKey.challenge);
                publicKey.user.id = b64urlToBuf(publicKey.user.id);
                if (publicKey.excludeCredentials) {
                    publicKey.excludeCredentials = publicKey.excludeCredentials.map(c => ({ ...c, id: b64urlToBuf(c.id) }));
                }
                var cred = await navigator.credentials.create({ publicKey });
                var body = {
                    id: cred.id,
                    rawId: bufToB64url(cred.rawId),
                    type: cred.type,
                    response: {
                        attestationObject: bufToB64url(cred.response.attestationObject),
                        clientDataJSON: bufToB64url(cred.response.clientDataJSON),
                    },
                };
                var finishResp = await fetch('/webmail/account/passkey/finish', {
                    method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),
                });
                if (!finishResp.ok) throw new Error((await finishResp.json()).error || 'Could not save passkey');
                window.location.reload();
            } catch (e) {
                errEl.textContent = e.message || 'Passkey registration failed';
                errEl.classList.remove('d-none');
            }
        });
    }

    document.addEventListener('DOMContentLoaded', initSettingsSection);
</script>
{{end}}
