function togglePreview() {
    let container = document.getElementById('previewContainer');
    let icon = document.getElementById('previewToggleIcon');
    if (container.style.display === 'none') {
        container.style.display = 'block';
        icon.className = 'fa fa-chevron-down';
    } else {
        container.style.display = 'none';
        icon.className = 'fa fa-chevron-right';
    }
}

function refreshPreview() {
    let iframe = document.getElementById('previewIframe');
    if (iframe) {
        iframe.src = iframe.src;
    }
}

function resizePreviewIframe() {
    let iframe = document.getElementById('previewIframe');
    if (iframe && iframe.contentWindow) {
        try {
            let height = iframe.contentWindow.document.body.scrollHeight;
            iframe.style.height = Math.max(height + 20, 200) + 'px';
        } catch (e) {
            // Cross-origin issues - use default height
            iframe.style.height = '400px';
        }
    }
}

function confirmDelete() {
    if (confirm('Are you sure you want to remove this block from the page?')) {
        document.getElementById('deleteBlockForm').submit();
    }
}

// Repeater field functions
let repeaterRowCounts = {};

function initRepeaterCounts() {
    document.querySelectorAll('.repeater-field').forEach(function(repeater) {
        let fieldName = repeater.dataset.fieldName;
        let rows = repeater.querySelectorAll('.repeater-row');
        repeaterRowCounts[fieldName] = rows.length;
    });
}

function addRepeaterRow(fieldName) {
    let repeater = document.querySelector('.repeater-field[data-field-name="' + fieldName + '"]');
    if (!repeater) return;

    let maxRows = parseInt(repeater.dataset.maxRows) || 100;
    let container = document.getElementById('repeater_' + fieldName + '_rows');
    let currentRows = container.querySelectorAll('.repeater-row').length;

    if (currentRows >= maxRows) {
        alert('Maximum ' + maxRows + ' rows allowed.');
        return;
    }

    let template = document.getElementById('repeater_' + fieldName + '_template');
    if (!template) return;

    let rowIndex = repeaterRowCounts[fieldName] || 0;
    repeaterRowCounts[fieldName] = rowIndex + 1;

    let html = template.innerHTML;
    html = html.replace(/__ROW_INDEX__/g, rowIndex);
    html = html.replace(/__ROW_NUM__/g, currentRows + 1);

    let div = document.createElement('div');
    div.innerHTML = html;
    let newRow = div.firstElementChild;
    newRow.setAttribute('draggable', 'true');
    container.appendChild(newRow);

    updateRepeaterState(fieldName);

    // Wire up conditional visibility for the new row's controlling select
    // (attaches change listener + evaluates current state)
    initFieldVisibility();

    // Re-initialize TinyMCE for any new textarea fields with simpletinymce class
    if (typeof init_tinymce === 'function') {
        setTimeout(init_tinymce, 100);
    }

    // Initialize icon field live preview for new row
    newRow.querySelectorAll('.icon-field-input').forEach(function(input) {
        input.addEventListener('input', function() {
            updateIconPreview(this.dataset.fieldId);
        });
    });

}

function removeRepeaterRow(btn) {
    let row = btn.closest('.repeater-row');
    let repeater = btn.closest('.repeater-field');
    let fieldName = repeater.dataset.fieldName;
    let minRows = parseInt(repeater.dataset.minRows) || 0;
    let container = repeater.querySelector('.repeater-rows');
    let currentRows = container.querySelectorAll('.repeater-row').length;

    if (currentRows <= minRows) {
        alert('Minimum ' + minRows + ' rows required.');
        return;
    }

    row.remove();
    reindexRepeaterRows(fieldName);
    updateRepeaterState(fieldName);
}

function reindexRepeaterRows(fieldName) {
    let container = document.getElementById('repeater_' + fieldName + '_rows');
    let rows = container.querySelectorAll('.repeater-row');

    rows.forEach(function(row, index) {
        row.querySelector('.repeater-row-number').textContent = 'Row ' + (index + 1);
    });
}

function updateRepeaterState(fieldName) {
    let repeater = document.querySelector('.repeater-field[data-field-name="' + fieldName + '"]');
    if (!repeater) return;

    let maxRows = parseInt(repeater.dataset.maxRows) || 100;
    let container = repeater.querySelector('.repeater-rows');
    let currentRows = container.querySelectorAll('.repeater-row').length;
    let addBtn = repeater.querySelector('.btn-add-row');

    if (addBtn) {
        addBtn.disabled = currentRows >= maxRows;
    }
}

// --- Conditional field visibility ---

function findControllerInput(el, controllerName) {
    // For sub-fields inside a repeater row, resolve relative to the row
    let row = el.closest('.repeater-row');
    if (row) {
        let subfield = row.querySelector('.repeater-subfield[data-subfield-name="' + controllerName + '"]');
        if (subfield) {
            return subfield.querySelector('select, input:not([type="hidden"])');
        }
    }
    // Fall back to top-level field
    return document.getElementById('field_' + controllerName);
}

function applyFieldVisibility() {
    let controlled = document.querySelectorAll('[data-visibility-field]');
    controlled.forEach(function(el) {
        let controllerName = el.getAttribute('data-visibility-field');
        let controllerInput = findControllerInput(el, controllerName);
        if (!controllerInput) return;

        let allowedValues = el.getAttribute('data-visibility-values').split(',');
        el.style.display = allowedValues.indexOf(controllerInput.value) !== -1 ? '' : 'none';
    });
}

// Tracks controller inputs we've already wired up, so initFieldVisibility()
// can be safely re-run after addRepeaterRow() without double-binding existing rows.
const visibilityAttached = new WeakSet();

function initFieldVisibility() {
    let controlled = document.querySelectorAll('[data-visibility-field]');
    if (!controlled.length) return;

    controlled.forEach(function(el) {
        let controllerName = el.getAttribute('data-visibility-field');
        let controllerInput = findControllerInput(el, controllerName);
        if (controllerInput && !visibilityAttached.has(controllerInput)) {
            controllerInput.addEventListener('change', applyFieldVisibility);
            visibilityAttached.add(controllerInput);
        }
    });

    applyFieldVisibility();
}

// Product selector — resolve product names for pre-existing values on page load
let productNameCache = {};

function initProductSelectors() {
    let hiddenFields = document.querySelectorAll('.product-selector-wrapper input[type="hidden"]');
    let idsToResolve = [];

    hiddenFields.forEach(function(field) {
        if (field.value && !productNameCache[field.value]) {
            idsToResolve.push(field.value);
        } else if (field.value && productNameCache[field.value]) {
            let nameField = document.getElementById(field.id + '_name');
            if (nameField) nameField.value = productNameCache[field.value];
        }
    });

    if (idsToResolve.length === 0) return;

    fetch('/admin/blocks/ajax/products', { credentials: 'same-origin' })
        .then(function(r) { return r.json(); })
        .then(function(products) {
            products.forEach(function(p) { productNameCache[p.id] = p.name; });
            hiddenFields.forEach(function(field) {
                if (field.value && productNameCache[field.value]) {
                    let nameField = document.getElementById(field.id + '_name');
                    if (nameField) nameField.value = productNameCache[field.value];
                }
            });
        });
}

// Initialize repeater counts on page load
document.addEventListener('DOMContentLoaded', function() {
    initRepeaterCounts();
    document.querySelectorAll('.repeater-field').forEach(function(repeater) {
        updateRepeaterState(repeater.dataset.fieldName);
        initRepeaterDragDrop(repeater);
    });

    // Initialize conditional field visibility
    initFieldVisibility();

    // Initialize product selectors
    initProductSelectors();

    // Populate container picker dropdowns for auto-mode page selectors
    initContainerPickers();

    // Ensure TinyMCE content is synced to textareas before form submission
    let form = document.querySelector('.block-data-form');
    if (form) {
        form.addEventListener('submit', function() {
            if (typeof tinymce !== 'undefined') {
                tinymce.triggerSave();
            }
        });
    }
});

// Drag and drop functionality for repeater rows (uses shared handler from block-registry-drag.js)
let repeaterDragDrop = createDragDropHandler('.repeater-row', function(container) {
    let fieldName = container.closest('.repeater-field').dataset.fieldName;
    reindexRepeaterRows(fieldName);
});

function initRepeaterDragDrop(repeater) {
    let container = repeater.querySelector('.repeater-rows');
    if (!container) return;

    repeaterDragDrop.init(container);

    // Set grab cursor on drag handles
    container.querySelectorAll('.repeater-row .repeater-row-drag').forEach(function(handle) {
        handle.style.cursor = 'grab';
    });
}

// Initialize WYSIWYG editors if available
document.addEventListener('DOMContentLoaded', function() {
    let wysiwygFields = document.querySelectorAll('.wysiwyg');
    wysiwygFields.forEach(function(field) {
        if (typeof CKEDITOR !== 'undefined') {
            CKEDITOR.replace(field.id);
        } else if (typeof tinymce !== 'undefined') {
            tinymce.init({
                selector: '#' + field.id,
                height: 300
            });
        }
    });
});

// Media picker - opens media manager in popup
let currentMediaFieldId = null;

function openMediaPicker(fieldId) {
    currentMediaFieldId = fieldId;
    window.open('/admin/media-manager/tinymce', 'Media Manager', 'width=950,height=650');
}

// Callback function for media manager
window.insertMediaToTinyMCE = function(url) {
    try {
        if (currentMediaFieldId) {
            let inputField = document.getElementById(currentMediaFieldId);
            if (inputField) {
                inputField.value = url;
                // Trigger change event
                inputField.dispatchEvent(new Event('change'));

                // Auto-populate alt text from filename if alt field exists and is empty
                let altFieldId = currentMediaFieldId.replace('_url', '_alt');
                let altField = document.getElementById(altFieldId);
                if (altField && !altField.value) {
                    let altText = generateAltTextFromUrl(url);
                    altField.value = altText;
                }

                // Update preview if it's an image field
                try {
                    updateImagePreview(currentMediaFieldId, url);
                } catch (previewError) {
                    console.warn('Preview update failed:', previewError);
                }
            }
            currentMediaFieldId = null;
        }
    } catch (e) {
        console.error('Media insert error:', e);
    }
};

// Generate alt text from filename
function generateAltTextFromUrl(url) {
    try {
        // Get filename from URL
        let filename = url.split('/').pop();
        // Remove extension
        filename = filename.replace(/\.[^/.]+$/, '');
        // Replace dashes and underscores with spaces
        filename = filename.replace(/[-_]/g, ' ');
        // Capitalize first letter of each word
        filename = filename.replace(/\b\w/g, function(c) { return c.toUpperCase(); });
        return filename;
    } catch (e) {
        return '';
    }
}

// Update image preview when URL changes
function updateImagePreview(fieldId, url) {
    try {
        let inputElement = document.getElementById(fieldId);
        if (!inputElement) return;

        let row = inputElement.closest('.row');
        if (!row) return;

        let previewContainer = row.querySelector('.image-preview');

        if (url && isImageUrl(url)) {
            if (previewContainer) {
                let img = previewContainer.querySelector('img');
                if (img) {
                    img.src = url;
                } else {
                    let newImg = document.createElement('img');
                    newImg.src = url;
                    newImg.alt = 'Preview';
                    newImg.style.cssText = 'max-width: 200px; max-height: 150px; margin-top: 10px;';
                    previewContainer.innerHTML = '';
                    previewContainer.appendChild(newImg);
                }
            } else {
                // Create preview if it doesn't exist
                let preview = document.createElement('div');
                preview.className = 'image-preview';
                let newImg = document.createElement('img');
                newImg.src = url;
                newImg.alt = 'Preview';
                newImg.style.cssText = 'max-width: 200px; max-height: 150px; margin-top: 10px;';
                preview.appendChild(newImg);
                row.appendChild(preview);
            }
        } else if (previewContainer) {
            previewContainer.remove();
        }
    } catch (e) {
        console.warn('Image preview update error:', e);
    }
}

function isImageUrl(url) {
    return /\.(jpg|jpeg|png|gif|webp|svg)$/i.test(url);
}

// Also update preview on manual input change
document.addEventListener('DOMContentLoaded', function() {
    document.querySelectorAll('.field-image input[type="text"], .field-file input[type="text"]').forEach(function(input) {
        input.addEventListener('change', function() {
            updateImagePreview(this.id, this.value);
        });
    });
});

// Cropper.js instances
let croppers = {};

// Initialize all croppers on page load
document.addEventListener('DOMContentLoaded', function() {
    document.querySelectorAll('.crop-target').forEach(function(img) {
        let fieldName = img.dataset.fieldName;
        if (img.src && img.src !== window.location.href) {
            initCropper(fieldName);
        }
    });

    // Watch for changes on image URL inputs
    document.querySelectorAll('.image-url-input').forEach(function(input) {
        input.addEventListener('change', function() {
            let fieldName = this.dataset.fieldName;
            let cropEnabled = this.dataset.cropEnabled === '1';

            if (cropEnabled && this.value) {
                let cropContainer = document.getElementById('crop_' + fieldName + '_container');
                let cropImage = document.getElementById('crop_' + fieldName + '_image');

                if (cropContainer && cropImage) {
                    cropImage.src = this.value;
                    cropContainer.style.display = '';
                    // Wait for image to load before initializing cropper
                    cropImage.onload = function() {
                        initCropper(fieldName);
                    };
                }
            }
        });
    });
});

function initCropper(fieldName) {
    // Destroy existing cropper
    destroyCropper(fieldName);

    let img = document.getElementById('crop_' + fieldName + '_image');
    if (!img || !img.src) return;

    let aspectRatio = img.dataset.aspectRatio;
    let minWidth = parseInt(img.dataset.minWidth) || 0;
    let maxWidth = parseInt(img.dataset.maxWidth) || 0;
    let ratio = NaN; // Free crop by default

    if (aspectRatio && aspectRatio.includes(':')) {
        let parts = aspectRatio.split(':');
        ratio = parseFloat(parts[0]) / parseFloat(parts[1]);
    }

    // Get existing crop coordinates
    let x = parseFloat(document.getElementById('field_' + fieldName + '_crop_x').value) || 0;
    let y = parseFloat(document.getElementById('field_' + fieldName + '_crop_y').value) || 0;
    let width = parseFloat(document.getElementById('field_' + fieldName + '_crop_width').value) || 0;
    let height = parseFloat(document.getElementById('field_' + fieldName + '_crop_height').value) || 0;

    let cropperOptions = {
        aspectRatio: ratio,
        viewMode: 2,
        autoCropArea: 1,
        zoomable: false,
        zoomOnWheel: false,
        responsive: true,
        crop: function(event) {
            // Update hidden inputs with crop coordinates
            document.getElementById('field_' + fieldName + '_crop_x').value = Math.round(event.detail.x);
            document.getElementById('field_' + fieldName + '_crop_y').value = Math.round(event.detail.y);
            document.getElementById('field_' + fieldName + '_crop_width').value = Math.round(event.detail.width);
            document.getElementById('field_' + fieldName + '_crop_height').value = Math.round(event.detail.height);

            // Warn if crop is too small for srcset sizes
            let warning = document.getElementById('crop_' + fieldName + '_warning');
            let cropWidth = Math.round(event.detail.width);
            if (minWidth > 0 && cropWidth < minWidth) {
                if (warning) {
                    warning.textContent = 'Crop is too small (' + cropWidth + 'px). Minimum width: ' + minWidth + 'px for responsive images.';
                    warning.style.color = '#c0392b';
                    warning.style.display = '';
                }
            } else if (maxWidth > 0 && cropWidth < maxWidth) {
                if (warning) {
                    warning.textContent = 'Image may appear soft on large screens (' + cropWidth + 'px). Recommended minimum width: ' + maxWidth + 'px.';
                    warning.style.color = '#856404';
                    warning.style.display = '';
                }
            } else if (warning) {
                warning.style.display = 'none';
            }
        }
    };

    // If we have existing crop data, use it
    if (width > 0 && height > 0) {
        cropperOptions.data = { x: x, y: y, width: width, height: height };
    }

    croppers[fieldName] = new Cropper(img, cropperOptions);
}

function destroyCropper(fieldName) {
    if (croppers[fieldName]) {
        croppers[fieldName].destroy();
        delete croppers[fieldName];
    }
}

function resetCrop(fieldName) {
    if (croppers[fieldName]) {
        croppers[fieldName].reset();
    }
    document.getElementById('field_' + fieldName + '_crop_x').value = 0;
    document.getElementById('field_' + fieldName + '_crop_y').value = 0;
    document.getElementById('field_' + fieldName + '_crop_width').value = 0;
    document.getElementById('field_' + fieldName + '_crop_height').value = 0;
}

// ============================================================
// Link Picker Modal
// ============================================================
let currentLinkFieldId = null;
let linkSearchTimeout = null;
let currentLinkTab = 'custom';

const linkTabDefs = [
    { id: 'custom', label: 'Custom URL', icon: 'fa-link' },
    { id: 'page', label: 'Pages', icon: 'fa-file-text-o' },
    { id: 'item', label: 'Products', icon: 'fa-shopping-bag' },
    { id: 'category', label: 'Categories', icon: 'fa-folder-o' },
    { id: 'assessment', label: 'Assessments', icon: 'fa-stethoscope' },
];

// Inject modal HTML on load
document.addEventListener('DOMContentLoaded', function() {
    let tabsHtml = linkTabDefs.map(function(tab) {
        return '<button type="button" class="link-picker-tab' + (tab.id === 'custom' ? ' is-active' : '') +
            '" data-tab="' + tab.id + '" onclick="switchLinkTab(\'' + tab.id + '\')">' +
            '<i class="fa ' + tab.icon + '"></i> ' + escapeHtml(tab.label) + '</button>';
    }).join('');

    let modal = document.createElement('div');
    modal.id = 'linkPickerModal';
    modal.className = 'link-picker-overlay';
    modal.style.display = 'none';
    modal.innerHTML = `
        <div class="link-picker-modal">
            <div class="link-picker-header">
                <h3>Insert/edit link</h3>
                <button type="button" class="link-picker-close" onclick="closeLinkPicker()">&times;</button>
            </div>
            <div class="link-picker-tabs">${tabsHtml}</div>
            <div class="link-picker-body">
                <div class="link-picker-pane" id="linkPane_custom">
                    <div class="link-picker-field">
                        <label>URL</label>
                        <input type="text" id="linkPickerUrl" placeholder="https:// or /page-slug">
                    </div>
                    <div class="link-picker-field">
                        <label>Link Text</label>
                        <input type="text" id="linkPickerTitle" placeholder="Link text">
                    </div>
                    <div class="link-picker-field link-picker-checkbox">
                        <label>
                            <input type="checkbox" id="linkPickerTarget">
                            Open link in a new tab
                        </label>
                    </div>
                </div>
                <div class="link-picker-pane" id="linkPane_search" style="display:none">
                    <div class="link-picker-field">
                        <input type="text" id="linkPickerSearch" placeholder="Search..." oninput="onLinkSearchInput(this.value)">
                    </div>
                    <div class="link-picker-results" id="linkPickerResults"></div>
                </div>
            </div>
            <div class="link-picker-footer">
                <button type="button" class="btn" onclick="closeLinkPicker()">Cancel</button>
                <button type="button" class="btn btn-primary" onclick="saveLinkPicker()">Update</button>
            </div>
        </div>
    `;
    document.body.appendChild(modal);

    // Close on overlay click
    modal.addEventListener('click', function(e) {
        if (e.target === modal) closeLinkPicker();
    });
});

function switchLinkTab(tabId) {
    currentLinkTab = tabId;

    // Update active tab button
    let tabs = document.querySelectorAll('.link-picker-tab');
    tabs.forEach(function(tab) {
        tab.classList.toggle('is-active', tab.dataset.tab === tabId);
    });

    let customPane = document.getElementById('linkPane_custom');
    let searchPane = document.getElementById('linkPane_search');

    if (tabId === 'custom') {
        customPane.style.display = '';
        searchPane.style.display = 'none';
    } else {
        customPane.style.display = 'none';
        searchPane.style.display = '';
        // Reset search and load results for this tab
        document.getElementById('linkPickerSearch').value = '';
        searchInternalLinks('', tabId);
    }
}

function openLinkPicker(fieldId) {
    currentLinkFieldId = fieldId;
    let modal = document.getElementById('linkPickerModal');

    // Pre-fill with current values
    let urlField = document.getElementById('field_' + fieldId + '_url');
    let titleField = document.getElementById('field_' + fieldId + '_title');
    let targetField = document.getElementById('field_' + fieldId + '_target');

    document.getElementById('linkPickerUrl').value = urlField ? urlField.value : '';
    document.getElementById('linkPickerTitle').value = titleField ? titleField.value : '';
    document.getElementById('linkPickerTarget').checked = targetField && targetField.value === '_blank';
    document.getElementById('linkPickerSearch').value = '';
    document.getElementById('linkPickerResults').innerHTML = '';

    // Reset to custom URL tab
    switchLinkTab('custom');

    modal.style.display = 'flex';
}

function closeLinkPicker() {
    let modal = document.getElementById('linkPickerModal');
    modal.style.display = 'none';
    currentLinkFieldId = null;
}

function saveLinkPicker() {
    if (!currentLinkFieldId) return;

    let url = document.getElementById('linkPickerUrl').value.trim();
    let title = document.getElementById('linkPickerTitle').value.trim();
    let target = document.getElementById('linkPickerTarget').checked ? '_blank' : '';

    let urlField = document.getElementById('field_' + currentLinkFieldId + '_url');
    let titleField = document.getElementById('field_' + currentLinkFieldId + '_title');
    let targetField = document.getElementById('field_' + currentLinkFieldId + '_target');

    if (urlField) urlField.value = url;
    if (titleField) titleField.value = title;
    if (targetField) targetField.value = target;

    updateLinkDisplay(currentLinkFieldId, url, title);
    closeLinkPicker();
}

function clearLink(fieldId) {
    document.getElementById('field_' + fieldId + '_url').value = '';
    document.getElementById('field_' + fieldId + '_title').value = '';
    document.getElementById('field_' + fieldId + '_target').value = '';
    updateLinkDisplay(fieldId, '', '');
}

function updateLinkDisplay(fieldId, url, title) {
    let display = document.getElementById('link_' + fieldId + '_display');
    let selectBtn = document.getElementById('link_' + fieldId + '_select_btn');
    let displayTitle = document.getElementById('link_' + fieldId + '_display_title');
    let displayUrl = document.getElementById('link_' + fieldId + '_display_url');

    if (url) {
        if (displayTitle) displayTitle.textContent = title || url;
        if (displayUrl) {
            displayUrl.textContent = url;
            displayUrl.href = url;
        }
        // Update the open-link anchor href
        let openLink = display ? display.querySelector('a.link-action[target="_blank"]') : null;
        if (openLink) openLink.href = url;

        if (display) display.style.display = '';
        if (selectBtn) selectBtn.style.display = 'none';
    } else {
        if (display) display.style.display = 'none';
        if (selectBtn) selectBtn.style.display = '';
    }
}

function onLinkSearchInput(value) {
    clearTimeout(linkSearchTimeout);
    linkSearchTimeout = setTimeout(function() {
        searchInternalLinks(value.trim(), currentLinkTab);
    }, 300);
}

function searchInternalLinks(query, type) {
    let url = '/admin/blocks/ajax/link-search?q=' + encodeURIComponent(query) + '&type=' + encodeURIComponent(type || '');
    fetch(url, { credentials: 'same-origin' })
        .then(function(r) { return r.json(); })
        .then(function(results) {
            renderLinkSearchResults(results);
        })
        .catch(function(err) {
            console.error('Link search error:', err);
        });
}

function renderLinkSearchResults(results) {
    let container = document.getElementById('linkPickerResults');
    if (!results || results.length === 0) {
        container.innerHTML = '<p class="link-picker-no-results">No results found.</p>';
        return;
    }

    let table = document.createElement('table');
    table.className = 'link-picker-table';
    let tbody = document.createElement('tbody');
    results.forEach(function(item) {
        let tr = document.createElement('tr');
        tr.className = 'link-picker-result';
        tr.dataset.url = item.url;
        tr.dataset.title = item.title;
        tr.addEventListener('click', function() {
            selectLinkResult(this.dataset.url, this.dataset.title);
        });
        let tdTitle = document.createElement('td');
        tdTitle.className = 'link-picker-result-title';
        tdTitle.textContent = item.title;
        let tdUrl = document.createElement('td');
        tdUrl.className = 'link-picker-result-url';
        tdUrl.textContent = item.url;
        tr.appendChild(tdTitle);
        tr.appendChild(tdUrl);
        tbody.appendChild(tr);
    });
    table.appendChild(tbody);
    container.innerHTML = '';
    container.appendChild(table);
}

function selectLinkResult(url, title) {
    document.getElementById('linkPickerUrl').value = url;
    document.getElementById('linkPickerTitle').value = title;
    // Switch to custom tab so user can see/edit the selection
    switchLinkTab('custom');
}

function escapeHtml(text) {
    let div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

// ============================================================
// Page Selector / Page Picker Modal
// ============================================================
let currentPageFieldId = null;
let pageSearchTimeout = null;
let pageNameCache = {};

function initPageSelectors() {
    let hiddenFields = document.querySelectorAll('.page-selector-wrapper input[type="hidden"]');
    let idsToResolve = [];

    hiddenFields.forEach(function(field) {
        if (field.value && !pageNameCache[field.value]) {
            idsToResolve.push(field.value);
        } else if (field.value && pageNameCache[field.value]) {
            let displayField = document.getElementById(field.id + '_display');
            if (displayField) displayField.value = pageNameCache[field.value];
        }
    });

    if (idsToResolve.length === 0) return;

    // Batch resolve page names — fetch all pages and match
    fetch('/admin/blocks/ajax/page-search?q=&published_only=0', { credentials: 'same-origin' })
        .then(function(r) { return r.json(); })
        .then(function(pages) {
            pages.forEach(function(p) { pageNameCache[p.id] = p.title; });
            hiddenFields.forEach(function(field) {
                if (field.value && pageNameCache[field.value]) {
                    let displayField = document.getElementById(field.id + '_display');
                    if (displayField) displayField.value = pageNameCache[field.value];
                }
            });
        });
}

// Inject page picker modal on load
document.addEventListener('DOMContentLoaded', function() {
    let modal = document.createElement('div');
    modal.id = 'pagePickerModal';
    modal.className = 'link-picker-overlay';
    modal.style.display = 'none';
    modal.innerHTML = `
        <div class="link-picker-modal">
            <div class="link-picker-header">
                <h3>Select Page</h3>
                <button type="button" class="link-picker-close" onclick="closePagePicker()">&times;</button>
            </div>
            <div class="link-picker-body">
                <div class="link-picker-field">
                    <label>Search</label>
                    <input type="text" id="pagePickerSearch" placeholder="Search pages..." oninput="onPageSearchInput(this.value)">
                </div>
                <div class="link-picker-results" id="pagePickerResults"></div>
            </div>
            <div class="link-picker-footer">
                <button type="button" class="btn" onclick="closePagePicker()">Cancel</button>
            </div>
        </div>
    `;
    document.body.appendChild(modal);

    modal.addEventListener('click', function(e) {
        if (e.target === modal) closePagePicker();
    });

    // Initialize page selectors
    initPageSelectors();
});

function openPagePicker(fieldId, containerId) {
    currentPageFieldId = fieldId;
    let modal = document.getElementById('pagePickerModal');

    document.getElementById('pagePickerSearch').value = '';
    document.getElementById('pagePickerResults').innerHTML = '';

    modal.dataset.containerId = containerId || '';
    modal.style.display = 'flex';

    // Load initial results
    searchPages('', containerId);
}

function closePagePicker() {
    let modal = document.getElementById('pagePickerModal');
    modal.style.display = 'none';
    currentPageFieldId = null;
}

function onPageSearchInput(value) {
    clearTimeout(pageSearchTimeout);
    pageSearchTimeout = setTimeout(function() {
        let containerId = document.getElementById('pagePickerModal').dataset.containerId || '';
        searchPages(value.trim(), containerId);
    }, 300);
}

function searchPages(query, containerId) {
    let url = '/admin/blocks/ajax/page-search?q=' + encodeURIComponent(query);
    if (containerId) url += '&container_id=' + containerId;

    fetch(url, { credentials: 'same-origin' })
        .then(function(r) { return r.json(); })
        .then(function(results) {
            renderPageSearchResults(results);
        })
        .catch(function(err) {
            console.error('Page search error:', err);
        });
}

function renderPageSearchResults(results) {
    let container = document.getElementById('pagePickerResults');
    if (!results || results.length === 0) {
        container.innerHTML = '<p class="link-picker-no-results">No pages found.</p>';
        return;
    }

    let table = document.createElement('table');
    table.className = 'link-picker-table';
    let tbody = document.createElement('tbody');
    results.forEach(function(item) {
        let tr = document.createElement('tr');
        tr.className = 'link-picker-result';
        tr.dataset.id = item.id;
        tr.dataset.title = item.title;
        tr.addEventListener('click', function() {
            selectPageResult(parseInt(this.dataset.id, 10), this.dataset.title);
        });
        let tdTitle = document.createElement('td');
        tdTitle.className = 'link-picker-result-title';
        tdTitle.textContent = item.title;
        let tdUrl = document.createElement('td');
        tdUrl.className = 'link-picker-result-type';
        tdUrl.textContent = item.url;
        tr.appendChild(tdTitle);
        tr.appendChild(tdUrl);
        tbody.appendChild(tr);
    });
    table.appendChild(tbody);
    container.innerHTML = '';
    container.appendChild(table);
}

function selectPageResult(id, title) {
    if (!currentPageFieldId) return;

    let hiddenInput = document.getElementById(currentPageFieldId);
    let displayInput = document.getElementById(currentPageFieldId + '_display');

    if (hiddenInput) hiddenInput.value = id;
    if (displayInput) displayInput.value = title;
    pageNameCache[id] = title;

    closePagePicker();
}

function initContainerPickers() {
    let selects = document.querySelectorAll('.page-selector-container-picker');
    if (selects.length === 0) return;

    fetch('/admin/blocks/ajax/listing-containers', { credentials: 'same-origin' })
        .then(function(r) { return r.json(); })
        .then(function(containers) {
            selects.forEach(function(select) {
                let currentValue = select.dataset.value || '';
                containers.forEach(function(c) {
                    let option = document.createElement('option');
                    option.value = c.id;
                    option.textContent = c.title;
                    if (String(c.id) === String(currentValue)) {
                        option.selected = true;
                    }
                    select.appendChild(option);
                });
            });
        });
}

function clearPageSelector(fieldId) {
    let hiddenInput = document.getElementById(fieldId);
    let displayInput = document.getElementById(fieldId + '_display');
    if (hiddenInput) hiddenInput.value = '';
    if (displayInput) displayInput.value = '';
}

// Override media manager callback to reinitialize cropper
let originalInsertMediaToTinyMCE = window.insertMediaToTinyMCE;
window.insertMediaToTinyMCE = function(url) {
    // Capture field ID before original function nulls it
    let fieldId = currentMediaFieldId;

    // Call the original function
    if (originalInsertMediaToTinyMCE) {
        originalInsertMediaToTinyMCE(url);
    }

    // Handle cropper reinitialization
    if (fieldId) {
        let fieldName = fieldId.replace('field_', '').replace('_url', '');
        let input = document.getElementById(fieldId);

        if (input && input.dataset.cropEnabled === '1') {
            let cropContainer = document.getElementById('crop_' + fieldName + '_container');
            let cropControls = document.getElementById('crop_' + fieldName + '_controls');
            let cropImage = document.getElementById('crop_' + fieldName + '_image');

            if (cropContainer && cropImage) {
                cropImage.src = url;
                cropContainer.style.display = '';
                if (cropControls) {
                    cropControls.style.display = '';
                }
                let cropResetBtn = document.getElementById('crop_' + fieldName + '_reset');
                if (cropResetBtn) {
                    cropResetBtn.style.display = '';
                }

                // Wait a moment for the image to load, then initialize cropper
                setTimeout(function() {
                    initCropper(fieldName);
                }, 200);
            }
        }
    }
};

/* ==========================================================================
   Icon Picker
   ========================================================================== */

let iconPickerFieldId = null;
let iconManifest = null;
let iconCurrentStyle = 'fal';
let iconSearchTimeout = null;

const POPULAR_ICONS = [
    'users', 'user', 'heart', 'star', 'check', 'times', 'search', 'home',
    'cog', 'envelope', 'phone', 'map-marker-alt', 'clock', 'calendar',
    'camera', 'image', 'file', 'folder', 'lock', 'unlock', 'eye',
    'comment', 'comments', 'bell', 'bookmark', 'tag', 'tags', 'link',
    'paperclip', 'thumbs-up', 'thumbs-down', 'share', 'download', 'upload',
    'cloud', 'bolt', 'fire', 'leaf', 'sun', 'moon', 'sparkles',
    'shield-alt', 'trophy', 'medal', 'award', 'gift', 'cart-plus',
    'shopping-cart', 'credit-card', 'truck', 'box', 'shipping-fast',
    'pills', 'prescription-bottle', 'stethoscope', 'heartbeat', 'allergies',
    'hand-holding-heart', 'mortar-pestle', 'capsules', 'first-aid',
    'chevron-right', 'chevron-left', 'arrow-right', 'arrow-left',
    'plus', 'minus', 'info-circle', 'question-circle', 'exclamation-circle'
];

// Inject icon picker modal on load
document.addEventListener('DOMContentLoaded', function() {
    let modal = document.createElement('div');
    modal.id = 'iconPickerModal';
    modal.className = 'icon-picker-overlay';
    modal.style.display = 'none';
    modal.innerHTML = `
        <div class="icon-picker-modal">
            <div class="icon-picker-header">
                <h3>Select Icon</h3>
                <button type="button" class="icon-picker-close" onclick="closeIconPicker()">&times;</button>
            </div>
            <div class="icon-picker-search">
                <input type="text" id="iconPickerSearch" placeholder="Search icons..." oninput="onIconSearchInput(this.value)">
            </div>
            <div class="icon-picker-styles">
                <button type="button" class="icon-picker-style-btn is-active" data-style="fal" onclick="switchIconStyle('fal')">
                    <i class="fal fa-font-awesome"></i> Light
                </button>
                <button type="button" class="icon-picker-style-btn" data-style="far" onclick="switchIconStyle('far')">
                    <i class="far fa-font-awesome"></i> Regular
                </button>
                <button type="button" class="icon-picker-style-btn" data-style="fas" onclick="switchIconStyle('fas')">
                    <i class="fas fa-font-awesome"></i> Solid
                </button>
                <button type="button" class="icon-picker-style-btn" data-style="fab" onclick="switchIconStyle('fab')">
                    <i class="fab fa-font-awesome-flag"></i> Brands
                </button>
                <button type="button" class="icon-picker-style-btn" data-style="custom" onclick="switchIconStyle('custom')">
                    <i class="fas fa-palette"></i> Site
                </button>
            </div>
            <div class="icon-picker-grid" id="iconPickerGrid"></div>
            <div class="icon-picker-footer">
                <span class="icon-picker-count" id="iconPickerCount"></span>
                <button type="button" class="btn" onclick="closeIconPicker()">Cancel</button>
            </div>
        </div>
    `;
    document.body.appendChild(modal);

    // Close on overlay click
    modal.addEventListener('click', function(e) {
        if (e.target === modal) closeIconPicker();
    });

    // Live preview on manual typing for all icon inputs
    document.querySelectorAll('.icon-field-input').forEach(function(input) {
        input.addEventListener('input', function() {
            updateIconPreview(this.dataset.fieldId);
        });
    });
});

function loadIconManifest() {
    if (iconManifest) return Promise.resolve(iconManifest);
    return fetch('/admin/blocks/ajax/icon-manifest')
        .then(function(res) { return res.json(); })
        .then(function(data) {
            iconManifest = data;
            iconManifest.brandSet = new Set(data.brands);
            return data;
        });
}

function openIconPicker(fieldId) {
    iconPickerFieldId = fieldId;
    let modal = document.getElementById('iconPickerModal');
    let searchInput = document.getElementById('iconPickerSearch');
    searchInput.value = '';

    // Reset to light style
    iconCurrentStyle = 'fal';
    document.querySelectorAll('.icon-picker-style-btn').forEach(function(btn) {
        btn.classList.toggle('is-active', btn.dataset.style === 'fal');
    });

    modal.style.display = 'flex';
    searchInput.focus();

    loadIconManifest().then(function() {
        renderIconGrid('');
    });
}

function closeIconPicker() {
    let modal = document.getElementById('iconPickerModal');
    modal.style.display = 'none';
    iconPickerFieldId = null;
}

function switchIconStyle(style) {
    iconCurrentStyle = style;
    document.querySelectorAll('.icon-picker-style-btn').forEach(function(btn) {
        btn.classList.toggle('is-active', btn.dataset.style === style);
    });
    let query = document.getElementById('iconPickerSearch').value;
    renderIconGrid(query);
}

function onIconSearchInput(query) {
    clearTimeout(iconSearchTimeout);
    iconSearchTimeout = setTimeout(function() {
        renderIconGrid(query);
    }, 200);
}

function renderIconGrid(query) {
    let grid = document.getElementById('iconPickerGrid');
    let countEl = document.getElementById('iconPickerCount');
    if (!iconManifest) return;

    let isBrands = iconCurrentStyle === 'fab';
    let isCustom = iconCurrentStyle === 'custom';
    let filtered;

    if (isCustom) {
        // Custom site icons
        let customIcons = iconManifest.custom || [];
        if (query.trim() === '') {
            filtered = customIcons;
        } else {
            let q = query.toLowerCase().trim();
            let terms = q.split(/\s+/);
            filtered = customIcons.filter(function(icon) {
                let searchStr = (icon.n + ' ' + icon.l).toLowerCase();
                return terms.every(function(term) {
                    return searchStr.indexOf(term) !== -1;
                });
            });
        }

        let fragment = document.createDocumentFragment();
        filtered.forEach(function(icon) {
            let cls = 'icon icon--' + icon.n;
            let cell = document.createElement('div');
            cell.className = 'icon-picker-cell icon-picker-cell--custom';
            cell.title = icon.l;
            cell.dataset.icon = cls;
            cell.addEventListener('click', function() {
                selectIcon(this.dataset.icon);
            });
            let i = document.createElement('i');
            i.className = cls;
            let span = document.createElement('span');
            span.textContent = icon.l;
            cell.appendChild(i);
            cell.appendChild(span);
            fragment.appendChild(cell);
        });

        if (filtered.length === 0) {
            let empty = document.createElement('div');
            empty.className = 'icon-picker-empty';
            empty.textContent = 'No icons found';
            fragment.appendChild(empty);
        }

        grid.innerHTML = '';
        grid.appendChild(fragment);
        countEl.textContent = filtered.length + ' site icon' + (filtered.length !== 1 ? 's' : '');
        return;
    }

    if (query.trim() === '') {
        // No search: show popular icons (or all brands if brands tab)
        if (isBrands) {
            filtered = iconManifest.icons.filter(function(icon) {
                return iconManifest.brandSet.has(icon.n);
            });
        } else {
            let popularSet = new Set(POPULAR_ICONS);
            filtered = iconManifest.icons.filter(function(icon) {
                return popularSet.has(icon.n) && !iconManifest.brandSet.has(icon.n);
            });
            // Sort by popular order
            let popularOrder = {};
            POPULAR_ICONS.forEach(function(name, i) { popularOrder[name] = i; });
            filtered.sort(function(a, b) {
                return (popularOrder[a.n] ?? 999) - (popularOrder[b.n] ?? 999);
            });
        }
    } else {
        let q = query.toLowerCase().trim();
        let terms = q.split(/\s+/);
        filtered = iconManifest.icons.filter(function(icon) {
            if (isBrands && !iconManifest.brandSet.has(icon.n)) return false;
            if (!isBrands && iconManifest.brandSet.has(icon.n)) return false;
            return terms.every(function(term) {
                return icon.n.indexOf(term) !== -1;
            });
        });
    }

    // Limit to 200 results
    let total = filtered.length;
    let limited = filtered.slice(0, 200);

    let fragment = document.createDocumentFragment();
    limited.forEach(function(icon) {
        let cls = iconCurrentStyle + ' fa-' + icon.n;
        let cell = document.createElement('div');
        cell.className = 'icon-picker-cell';
        cell.title = icon.n;
        cell.dataset.icon = cls;
        cell.addEventListener('click', function() {
            selectIcon(this.dataset.icon);
        });
        let i = document.createElement('i');
        i.className = cls;
        let span = document.createElement('span');
        span.textContent = icon.n;
        cell.appendChild(i);
        cell.appendChild(span);
        fragment.appendChild(cell);
    });

    if (total === 0) {
        let empty = document.createElement('div');
        empty.className = 'icon-picker-empty';
        empty.textContent = 'No icons found';
        fragment.appendChild(empty);
    }

    grid.innerHTML = '';
    grid.appendChild(fragment);
    countEl.textContent = query.trim() === '' && !isBrands
        ? 'Popular icons — type to search all ' + iconManifest.icons.length
        : total + ' icon' + (total !== 1 ? 's' : '') + (total > 200 ? ' (showing first 200)' : '');
}

function selectIcon(iconClass) {
    if (!iconPickerFieldId) return;
    let input = document.getElementById(iconPickerFieldId);
    if (input) {
        input.value = iconClass;
        updateIconPreview(iconPickerFieldId);
    }
    closeIconPicker();
}

function clearIconField(fieldId) {
    let input = document.getElementById(fieldId);
    if (input) {
        input.value = '';
        updateIconPreview(fieldId);
    }
}

function updateIconPreview(fieldId) {
    let input = document.getElementById(fieldId);
    let preview = document.getElementById('icon_' + fieldId + '_preview');
    if (!input || !preview) return;

    let val = input.value.trim();
    if (val) {
        preview.innerHTML = '<i class="' + escapeHtml(val) + '"></i>';
    } else {
        preview.innerHTML = '<i class="fal fa-icons" style="opacity: 0.3;"></i>';
    }
}

// Save as Global Block modal
document.addEventListener('DOMContentLoaded', function() {
    let openBtn = document.getElementById('saveAsGlobalBtn');
    let modal = document.getElementById('saveAsGlobalModal');
    if (!openBtn || !modal) return;

    let closeBtn = document.getElementById('saveAsGlobalClose');
    let cancelBtn = document.getElementById('saveAsGlobalCancel');
    let nameField = document.getElementById('global_name');

    function openModal() {
        modal.style.display = 'flex';
        if (nameField) {
            nameField.focus();
            nameField.select();
        }
    }

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

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

    modal.addEventListener('click', function(e) {
        if (e.target === modal) closeModal();
    });

    document.addEventListener('keydown', function(e) {
        if (e.key === 'Escape' && modal.style.display !== 'none') closeModal();
    });
});
