/**
 * WPFAQBlock Admin Builder JS – Step 7 (AJAX wired)
 * @package WPFAQBlock
 * @since   2.0.0
 */
(function () {
    'use strict';

    var $ = function (id) { return document.getElementById(id); };
    var data = window.wpfaqblockData || {};
    var ajaxUrl = data.ajaxUrl || '';
    var nonce = data.nonce || '';
    var i18n = data.i18n || {};

    // Panel refs
    var placeholder = $('faqb-panel-placeholder');
    var form = $('faqb-panel-form');
    var panelTitle = $('faqb-panel-title');
    var fieldPostId = $('faqb-edit-post-id');
    var fieldGroup = $('faqb-edit-group');
    var fieldQuestion = $('faqb-edit-question');
    var fieldAnswer = $('faqb-edit-answer');
    var fieldStatus = $('faqb-edit-status');
    var btnSave = $('faqb-edit-save');
    var btnDiscard = $('faqb-edit-discard');
    var btnClose = $('faqb-panel-close');
    var noticesArea = $('faqb-notices');
    var savedStatus = $('faqb-saved-status');

    var activeItem = null;
    var originalValues = {};
    var isDirty = false;

    // ── Init ──────────────────────────────────────────────────────
    document.addEventListener('DOMContentLoaded', function () {
        initGroupToggles();
        initFaqItems();
        initPanelButtons();
        initDirtyTracking();
        initStatusToggles();
        initAddFaqButtons();
        initLiveSearch();
        initRichEditor();
        initImportExport();
    });

    function initRichEditor() {
        // Use p tags for new lines
        document.execCommand('defaultParagraphSeparator', false, 'p');

        document.querySelectorAll('.faqb-editor-btn').forEach(function (btn) {
            btn.addEventListener('click', function (e) {
                e.preventDefault();
                fieldAnswer.focus(); // Focus first to ensure selection is active
                var command = btn.dataset.command;
                if (command === 'createLink') {
                    var url = window.prompt('Enter URL:');
                    if (url) document.execCommand(command, false, url);
                } else {
                    document.execCommand(command, false, null);
                }
                markDirty();
            });
        });
        if (fieldAnswer) {
            fieldAnswer.addEventListener('input', markDirty);
        }

        var headingSel = document.getElementById('faqb-editor-heading');
        if (headingSel) {
            headingSel.addEventListener('change', function () {
                var val = headingSel.value;
                fieldAnswer.focus();
                // Ensure the command is executed on the current selection
                if (val === 'p') {
                    document.execCommand('formatBlock', false, 'div'); // Use div as intermediate if p is tricky
                    document.execCommand('formatBlock', false, 'p');
                } else {
                    document.execCommand('formatBlock', false, val);
                }
                markDirty();
            });
        }

        // Emoji Picker Logic (Simplified Minimal Style)
        var emojiTrigger = document.getElementById('faqb-emoji-trigger');
        var emojiPicker = document.getElementById('faqb-emoji-picker');

        if (emojiTrigger && emojiPicker) {
            emojiTrigger.addEventListener('click', function (e) {
                e.preventDefault();
                e.stopPropagation();
                var isOpen = emojiPicker.style.display === 'flex';

                if (!isOpen) {
                    // Position the picker dynamically
                    var rect = emojiTrigger.getBoundingClientRect();
                    var pickerWidth = 220; // Matches new CSS width

                    // Always open downwards
                    var top = rect.bottom + 8;
                    var left = rect.right - pickerWidth;

                    emojiPicker.style.top = top + 'px';
                    emojiPicker.style.left = left + 'px';
                    emojiPicker.style.display = 'flex';
                } else {
                    emojiPicker.style.display = 'none';
                }
            });

            emojiPicker.addEventListener('click', function (e) {
                var item = e.target.closest('.faqb-emoji-item');
                if (item) {
                    fieldAnswer.focus();
                    document.execCommand('insertText', false, item.textContent);
                    markDirty();
                    emojiPicker.style.display = 'none';
                }
                e.stopPropagation();
            });

            document.addEventListener('click', function () {
                emojiPicker.style.display = 'none';
            });
        }
    }

    // ── 1. Group toggles ─────────────────────────────────────────
    function initGroupToggles() {
        document.querySelectorAll('.faqb-group__header').forEach(function (header) {
            header.addEventListener('click', function (e) {
                if (e.target.closest('.faqb-group__actions')) return;
                var group = header.closest('.faqb-group');
                var isOpen = group.classList.contains('is-open');
                group.classList.toggle('is-open', !isOpen);
                header.setAttribute('aria-expanded', String(!isOpen));
            });
        });
    }

    // ── 2. FAQ item click → populate panel ──────────────────────
    function initFaqItems() {
        document.querySelectorAll('.faqb-item').forEach(attachFaqListener);
    }

    function attachFaqListener(item) {
        item.addEventListener('click', function (e) {
            if (e.target.closest('.faqb-toggle') || e.target.closest('.faqb-item__actions')) return;
            if (isDirty && activeItem !== item) {
                if (!window.confirm('Unsaved changes. Discard?')) return;
            }
            activateItem(item);
        });
    }

    function activateItem(item) {
        document.querySelectorAll('.faqb-item').forEach(function (i) { i.classList.remove('is-active'); });
        item.classList.add('is-active');
        activeItem = item;

        var postId = item.dataset.faqId || '';
        var groupId = item.dataset.groupId || '0';
        var question = item.dataset.question || '';
        var answer = item.dataset.answer || '';
        var status = item.dataset.status === '1';

        fieldPostId.value = postId;
        fieldQuestion.value = question;
        fieldAnswer.innerHTML = answer;
        fieldStatus.checked = status;
        selectByValue(fieldGroup, groupId);
        panelTitle.textContent = truncate(question, 40) || 'Edit FAQ';
        snapshotValues();
        isDirty = false;
        showForm();
    }

    // ── 3. Dirty tracking ────────────────────────────────────────
    function initDirtyTracking() {
        [fieldQuestion, fieldAnswer, fieldGroup].forEach(function (f) {
            if (f) f.addEventListener('input', markDirty);
        });
        if (fieldStatus) fieldStatus.addEventListener('change', markDirty);
    }
    function markDirty() { isDirty = hasChanges(); updateSaveBtn(); }
    function snapshotValues() {
        originalValues = {
            question: fieldQuestion ? fieldQuestion.value : '',
            answer: fieldAnswer ? fieldAnswer.innerHTML : '',
            group: fieldGroup ? fieldGroup.value : '0',
            status: fieldStatus ? fieldStatus.checked : false,
        };
    }
    function hasChanges() {
        return fieldQuestion.value !== originalValues.question ||
            fieldAnswer.innerHTML !== originalValues.answer ||
            fieldGroup.value !== originalValues.group ||
            fieldStatus.checked !== originalValues.status;
    }
    function updateSaveBtn() {
        if (btnSave) btnSave.style.opacity = isDirty ? '1' : '.65';
    }

    // ── 4. Panel buttons ─────────────────────────────────────────
    function initPanelButtons() {
        if (btnClose) btnClose.addEventListener('click', handleClose);
        if (btnDiscard) btnDiscard.addEventListener('click', handleDiscard);
        if (btnSave) btnSave.addEventListener('click', handleSave);
    }

    function handleClose() {
        if (isDirty && !window.confirm('Unsaved changes. Discard?')) return;
        closePanel();
    }
    function handleDiscard() { closePanel(); }

    // ── 5. Save → AJAX wp_update_post / wp_insert_post ──────────
    function handleSave() {
        var question = fieldQuestion ? fieldQuestion.value.trim() : '';
        if (!question) { showNotice('error', i18n.noTitle || 'Question cannot be empty.'); return; }

        var postId = fieldPostId ? fieldPostId.value.trim() : '';
        var answer = fieldAnswer ? fieldAnswer.innerHTML : '';
        var groupId = fieldGroup ? fieldGroup.value : '0';
        var status = fieldStatus ? (fieldStatus.checked ? '1' : '0') : '1';
        var action = postId ? 'wpfaqblock_save_faq' : 'wpfaqblock_create_faq';

        setSaving(true);

        ajax(action, { post_id: postId, question: question, answer: answer, group_id: groupId, status: status },
            function (res) {
                setSaving(false);
                if (!res.success) { showNotice('error', res.data.message); return; }

                var pid = res.data.post_id;

                // Update or insert the item row in the list
                if (postId) {
                    updateItemInList(activeItem, question, status === '1', groupId, answer);
                } else {
                    insertNewItem(pid, question, groupId, answer, status === '1');
                }

                fieldPostId.value = pid;
                snapshotValues();
                isDirty = false;
                updateSaveBtn();
                showSavedFlash();
            },
            function () { setSaving(false); showNotice('error', i18n.error || 'Something went wrong.'); }
        );
    }

    function updateItemInList(item, question, isActive, groupId, answer) {
        if (!item) return;
        var q = item.querySelector('.faqb-item__question');
        if (q) { q.textContent = question; q.style.opacity = isActive ? '1' : '.5'; }
        var t = item.querySelector('.faqb-status-toggle');
        if (t) t.checked = isActive;
        item.dataset.question = question;
        item.dataset.answer = answer;
        item.dataset.status = isActive ? '1' : '0';

        var oldGroupId = item.dataset.groupId || '0';
        item.dataset.groupId = String(groupId);

        // Move the item to the new group container if the group changed
        if (oldGroupId !== String(groupId)) {
            var newGroupEl = document.querySelector('.faqb-group[data-group-id="' + groupId + '"]');
            if (newGroupEl) {
                var newGroupBody = newGroupEl.querySelector('.faqb-group__body');
                var addRow = newGroupEl.querySelector('.faqb-group__add-row');
                if (newGroupBody) {
                    if (addRow) { newGroupBody.insertBefore(item, addRow); }
                    else { newGroupBody.appendChild(item); }
                }
                updateGroupBadge(newGroupEl);
            }
            var oldGroupEl = document.querySelector('.faqb-group[data-group-id="' + oldGroupId + '"]');
            if (oldGroupEl) {
                updateGroupBadge(oldGroupEl);
            }
        }

        item.classList.toggle('faqb-item--inactive', !isActive);
        panelTitle.textContent = truncate(question, 40);
    }

    function insertNewItem(postId, question, groupId, answer, isActive) {
        // Find group body with matching group-id
        var groupEl = document.querySelector('.faqb-group[data-group-id="' + groupId + '"]');
        if (!groupEl) return;

        var addRow = groupEl.querySelector('.faqb-group__add-row');
        var div = document.createElement('div');
        div.className = 'faqb-item' + (isActive ? '' : ' faqb-item--inactive');
        div.dataset.faqId = postId;
        div.dataset.groupId = groupId;
        div.dataset.question = question;
        div.dataset.answer = answer;
        div.dataset.status = isActive ? '1' : '0';
        div.setAttribute('role', 'button');
        div.setAttribute('tabindex', '0');
        div.innerHTML =
            '<span class="faqb-item__drag">⠿</span>' +
            '<span class="faqb-item__question">' + escHtml(question) + '</span>' +
            '<label class="faqb-toggle"><input type="checkbox" class="faqb-status-toggle" data-faq-id="' + postId + '"' + (isActive ? ' checked' : '') + '><span class="faqb-toggle__slider"></span></label>' +
            '<div class="faqb-item__actions"><button type="button" class="faqb-btn faqb-btn--danger faqb-btn--icon-only faqb-item-delete-btn" data-faq-id="' + postId + '"><span class="dashicons dashicons-trash"></span></button></div>';

        if (addRow) { groupEl.querySelector('.faqb-group__body').insertBefore(div, addRow); }
        else { groupEl.querySelector('.faqb-group__body').appendChild(div); }

        // Update badge
        updateGroupBadge(groupEl);

        attachFaqListener(div);
        attachDeleteListener(div.querySelector('.faqb-item-delete-btn'));
        attachToggleListener(div.querySelector('.faqb-status-toggle'));

        activeItem = div;
        div.classList.add('is-active');
        fieldPostId.value = postId;
    }

    // ── 6. Status toggles in list ────────────────────────────────
    function initStatusToggles() {
        document.querySelectorAll('.faqb-status-toggle').forEach(attachToggleListener);
        document.querySelectorAll('.faqb-item-delete-btn').forEach(attachDeleteListener);
        document.querySelectorAll('.faqb-group-status-toggle').forEach(attachGroupToggleListener);
    }

    function attachToggleListener(toggle) {
        if (!toggle) return;
        toggle.addEventListener('change', function () {
            var item = toggle.closest('.faqb-item');
            var isActive = toggle.checked;
            var postId = toggle.dataset.faqId;

            if (item) {
                var q = item.querySelector('.faqb-item__question');
                if (q) q.style.opacity = isActive ? '1' : '.5';
                item.classList.toggle('faqb-item--inactive', !isActive);
                item.dataset.status = isActive ? '1' : '0';
            }
            if (activeItem === item && fieldStatus) {
                fieldStatus.checked = isActive;
                isDirty = hasChanges(); updateSaveBtn();
            }

            ajax('wpfaqblock_toggle_faq', { post_id: postId, status: isActive ? '1' : '0' }, null, null);
        });
    }

    function attachGroupToggleListener(toggle) {
        if (!toggle) return;
        toggle.addEventListener('change', function () {
            var isActive = toggle.checked;
            var termId = toggle.dataset.groupId;
            ajax('wpfaqblock_toggle_group', { term_id: termId, status: isActive ? '1' : '0' }, null, null);
        });

        // Prevent toggle click from opening/closing the group
        var label = toggle.closest('.faqb-toggle');
        if (label) {
            label.addEventListener('click', function (e) {
                e.stopPropagation();
            });
        }
    }

    function attachDeleteListener(btn) {
        if (!btn) return;
        btn.addEventListener('click', function (e) {
            e.stopPropagation();
            if (!window.confirm(i18n.confirmDelete || 'Delete this FAQ?')) return;
            var postId = btn.dataset.faqId;
            ajax('wpfaqblock_delete_faq', { post_id: postId },
                function (res) {
                    if (!res.success) { showNotice('error', res.data.message); return; }
                    var item = btn.closest('.faqb-item');
                    var grp = item ? item.closest('.faqb-group') : null;
                    if (item) item.remove();
                    if (grp) updateGroupBadge(grp);
                    if (activeItem === item) closePanel();
                },
                function () { showNotice('error', i18n.error || 'Error.'); }
            );
        });
    }

    // ── 7. Add FAQ buttons ───────────────────────────────────────
    function initAddFaqButtons() {
        document.querySelectorAll('.faqb-add-faq-btn').forEach(function (btn) {
            btn.addEventListener('click', function () {
                var groupId = btn.dataset.groupId || '0';
                if (fieldPostId) fieldPostId.value = '';
                if (fieldQuestion) fieldQuestion.value = '';
                if (fieldAnswer) fieldAnswer.innerHTML = '';
                if (fieldStatus) fieldStatus.checked = true;
                selectByValue(fieldGroup, groupId);
                activeItem = null;
                document.querySelectorAll('.faqb-item').forEach(function (i) { i.classList.remove('is-active'); });
                panelTitle.textContent = 'New FAQ';
                snapshotValues(); isDirty = false; updateSaveBtn();
                showForm();
                if (fieldQuestion) fieldQuestion.focus();
            });
        });
    }

    // ── 8. Live Search ──────────────────────────────────────────
    function initLiveSearch() {
        var searchInput = $('faqb-builder-search');
        if (!searchInput) return;

        searchInput.addEventListener('input', function () {
            var query = searchInput.value.toLowerCase().trim();
            var groups = document.querySelectorAll('.faqb-group');

            groups.forEach(function (group) {
                var groupName = group.querySelector('.faqb-group__name').textContent.toLowerCase();
                var items = group.querySelectorAll('.faqb-item');
                var hasMatch = false;

                // If group name matches, show all items in it
                if (query && groupName.indexOf(query) !== -1) {
                    items.forEach(function (item) { item.style.display = ''; });
                    hasMatch = true;
                } else {
                    // Filter items individually
                    items.forEach(function (item) {
                        var question = item.dataset.question.toLowerCase();
                        if (!query || question.indexOf(query) !== -1) {
                            item.style.display = '';
                            hasMatch = true;
                        } else {
                            item.style.display = 'none';
                        }
                    });
                }

                // Show/Hide the entire group based on matches
                group.style.display = hasMatch ? '' : 'none';

                // Automatically expand groups that have matches when searching
                if (query && hasMatch) {
                    group.classList.add('is-open');
                }
            });
        });
    }

    // ── 9. Import / Export ───────────────────────────────────────
    function initImportExport() {
        var exportBtn = $('faqb-btn-export');
        var importBtn = $('faqb-btn-import');

        initExportModal(exportBtn);
        initImportModal(importBtn);
    }

    function initExportModal(openBtn) {
        var modal = $('faqb-export-modal');
        var overlay = $('faqb-export-overlay');
        var closeBtn = $('faqb-export-close');
        var cancelBtn = $('faqb-export-cancel');
        var downloadBtn = $('faqb-export-download');
        var categoryField = $('faqb-export-category-field');
        var selectionField = $('faqb-export-selection-field');
        var categoryList = $('faqb-export-category-list');
        var selectionList = $('faqb-export-selection-list');
        var notices = $('faqb-export-notices');

        if (!modal || !openBtn) return;

        function openModal() {
            clearModalNotice(notices);
            renderExportSelectionList(selectionList);
            modal.style.display = 'flex';
            if (overlay) overlay.style.display = 'block';
        }

        function closeModal() {
            modal.style.display = 'none';
            if (overlay) overlay.style.display = 'none';
        }

        function updateMode() {
            var mode = getCheckedValue('faqb_export_mode') || 'all';
            if (categoryField) categoryField.style.display = mode === 'category' ? '' : 'none';
            if (selectionField) selectionField.style.display = mode === 'selected' ? '' : 'none';
        }

        openBtn.addEventListener('click', openModal);
        if (closeBtn) closeBtn.addEventListener('click', closeModal);
        if (cancelBtn) cancelBtn.addEventListener('click', closeModal);
        if (overlay) overlay.addEventListener('click', closeModal);
        document.querySelectorAll('input[name="faqb_export_mode"]').forEach(function (radio) {
            radio.addEventListener('change', updateMode);
        });
        updateMode();

        if (downloadBtn) {
            downloadBtn.addEventListener('click', function () {
                var mode = getCheckedValue('faqb_export_mode') || 'all';
                var payload = { mode: mode };

                if (mode === 'selected') {
                    var ids = getCheckedExportIds(selectionList);
                    if (!ids.length) {
                        showModalNotice(notices, 'error', 'Please select at least one FAQ to export.');
                        return;
                    }
                    payload.faq_ids = ids.join(',');
                } else if (mode === 'category') {
                    var groupIds = getCheckedExportIds(categoryList);
                    if (!groupIds.length) {
                        showModalNotice(notices, 'error', 'Please select at least one category to export.');
                        return;
                    }
                    payload.group_ids = groupIds.join(',');
                }

                downloadBtn.disabled = true;
                ajax('wpfaqblock_export_faqs', payload, function (res) {
                    downloadBtn.disabled = false;
                    if (!res.success) {
                        showModalNotice(notices, 'error', res.data && res.data.message ? res.data.message : 'Export failed.');
                        return;
                    }
                    downloadJson(res.data.export, res.data.filename || 'wpfaqblock-faqs.json');
                    closeModal();
                    showNotice('success', res.data.message || 'FAQs exported.');
                }, function () {
                    downloadBtn.disabled = false;
                    showModalNotice(notices, 'error', 'Export failed.');
                });
            });
        }
    }

    function initImportModal(openBtn) {
        var modal = $('faqb-import-modal');
        var overlay = $('faqb-import-overlay');
        var closeBtn = $('faqb-import-close');
        var cancelBtn = $('faqb-import-cancel');
        var submitBtn = $('faqb-import-submit');
        var fileInput = $('faqb-import-file');
        var targetGroup = $('faqb-import-target-group');
        var notices = $('faqb-import-notices');

        if (!modal || !openBtn) return;

        function openModal() {
            clearModalNotice(notices);
            if (fileInput) fileInput.value = '';
            modal.style.display = 'flex';
            if (overlay) overlay.style.display = 'block';
        }

        function closeModal() {
            modal.style.display = 'none';
            if (overlay) overlay.style.display = 'none';
        }

        openBtn.addEventListener('click', openModal);
        if (closeBtn) closeBtn.addEventListener('click', closeModal);
        if (cancelBtn) cancelBtn.addEventListener('click', closeModal);
        if (overlay) overlay.addEventListener('click', closeModal);

        if (submitBtn) {
            submitBtn.addEventListener('click', function () {
                var file = fileInput && fileInput.files ? fileInput.files[0] : null;
                if (!file) {
                    showModalNotice(notices, 'error', 'Please choose a JSON file to import.');
                    return;
                }

                var reader = new FileReader();
                reader.onload = function () {
                    var text = String(reader.result || '');
                    try {
                        JSON.parse(text);
                    } catch (e) {
                        showModalNotice(notices, 'error', 'Invalid JSON file.');
                        return;
                    }

                    submitBtn.disabled = true;
                    ajax('wpfaqblock_import_faqs', {
                        payload: text,
                        target_group_id: targetGroup ? targetGroup.value : 'preserve'
                    }, function (res) {
                        submitBtn.disabled = false;
                        if (!res.success) {
                            showModalNotice(notices, 'error', res.data && res.data.message ? res.data.message : 'Import failed.');
                            return;
                        }
                        showModalNotice(notices, 'success', res.data.message || 'FAQs imported.');
                        setTimeout(function () { window.location.reload(); }, 900);
                    }, function () {
                        submitBtn.disabled = false;
                        showModalNotice(notices, 'error', 'Import failed.');
                    });
                };
                reader.readAsText(file);
            });
        }
    }

    function renderExportSelectionList(container) {
        if (!container) return;
        var items = Array.prototype.slice.call(document.querySelectorAll('.faqb-item'));
        if (!items.length) {
            container.innerHTML = '<p class="faqb-import-export-empty">No FAQs found.</p>';
            return;
        }

        container.innerHTML = items.map(function (item) {
            var id = item.dataset.faqId || '';
            var question = item.dataset.question || ('FAQ #' + id);
            var group = item.closest('.faqb-group');
            var groupName = group && group.querySelector('.faqb-group__name')
                ? group.querySelector('.faqb-group__name').textContent.trim()
                : 'Uncategorized';
            return '<label class="faqb-import-export-item">' +
                '<input type="checkbox" value="' + escHtml(id) + '">' +
                '<span><strong>' + escHtml(question) + '</strong><small>' + escHtml(groupName) + '</small></span>' +
                '</label>';
        }).join('');
    }

    function getCheckedExportIds(container) {
        if (!container) return [];
        return Array.prototype.slice.call(container.querySelectorAll('input[type="checkbox"]:checked'))
            .map(function (input) { return input.value; })
            .filter(Boolean);
    }

    function getCheckedValue(name) {
        var checked = document.querySelector('input[name="' + name + '"]:checked');
        return checked ? checked.value : '';
    }

    function downloadJson(payload, filename) {
        var blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' });
        var url = window.URL.createObjectURL(blob);
        var link = document.createElement('a');
        link.href = url;
        link.download = filename;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(url);
    }

    function showModalNotice(container, type, msg) {
        if (!container) return;
        container.innerHTML = '<div class="faqb-notice faqb-notice--' + type + '">' + escHtml(msg) + '</div>';
        container.style.display = 'block';
    }

    function clearModalNotice(container) {
        if (!container) return;
        container.innerHTML = '';
        container.style.display = 'none';
    }

    // ── Utilities ────────────────────────────────────────────────
    function ajax(action, postData, onSuccess, onError) {
        var fd = new FormData();
        fd.append('action', action);
        fd.append('nonce', nonce);
        Object.keys(postData).forEach(function (k) { fd.append(k, postData[k]); });

        fetch(ajaxUrl, { method: 'POST', body: fd })
            .then(function (r) { return r.json(); })
            .then(function (res) { if (onSuccess) onSuccess(res); })
            .catch(function () { if (onError) onError(); });
    }

    function showForm() {
        if (placeholder) placeholder.style.display = 'none';
        if (form) form.style.display = 'flex';
    }

    function closePanel() {
        if (placeholder) placeholder.style.display = '';
        if (form) form.style.display = 'none';
        if (activeItem) activeItem.classList.remove('is-active');
        activeItem = null; isDirty = false; updateSaveBtn();
    }

    function setSaving(saving) {
        if (!btnSave) return;
        btnSave.disabled = saving;
        btnSave.textContent = saving ? (i18n.saving || 'Saving…') : ('✓ ' + (i18n.save || 'Update FAQ'));
    }

    function selectByValue(sel, val) {
        if (!sel) return;
        for (var i = 0; i < sel.options.length; i++) {
            if (sel.options[i].value === String(val)) { sel.selectedIndex = i; return; }
        }
        sel.selectedIndex = 0;
    }

    function updateGroupBadge(groupEl) {
        var badge = groupEl.querySelector('.faqb-group__badge');
        var items = groupEl.querySelectorAll('.faqb-item');
        if (badge) badge.textContent = items.length;

        // Toggle empty state message
        var emptyMsg = groupEl.querySelector('.faqb-empty-state');
        if (emptyMsg) {
            emptyMsg.style.display = items.length > 0 ? 'none' : 'block';
        }
    }

    function truncate(s, n) { return s && s.length > n ? s.substring(0, n) + '…' : s; }
    function escHtml(s) {
        return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
    }

    function showNotice(type, msg) {
        if (!noticesArea) return;
        var d = document.createElement('div');
        d.className = 'faqb-notice faqb-notice--' + type;
        d.textContent = msg;
        noticesArea.innerHTML = '';
        noticesArea.appendChild(d);
        setTimeout(function () { d.remove(); }, 3500);
    }

    function showSavedFlash() {
        if (!savedStatus) return;
        savedStatus.style.display = 'inline-flex';
        setTimeout(function () { savedStatus.style.display = 'none'; }, 2500);
    }

    // ── Expose for Step 8 & 9 extensions ────────────────────────
    window.wpfaqblockBuilder = {
        ajax: ajax,
        showNotice: showNotice,
        attachFaqListener: attachFaqListener,
        updateGroupBadge: updateGroupBadge,
        insertNewItem: insertNewItem,
        closePanel: closePanel,
        attachGroupToggleListener: attachGroupToggleListener,
    };

})();
