/**
 * ITSWEBER CMS – Admin JavaScript
 */

document.addEventListener('DOMContentLoaded', function () {
    // ── Sidebar toggle for mobile ─────────────────────────────────────────
    var toggle   = document.getElementById('sidebarToggle');
    var sidebar  = document.getElementById('adminSidebar');
    var backdrop = document.getElementById('sidebarBackdrop');

    function openSidebar() {
        sidebar.classList.add('open');
        if (backdrop) backdrop.classList.add('open');
        if (toggle)   toggle.setAttribute('aria-expanded', 'true');
    }

    function closeSidebar() {
        sidebar.classList.remove('open');
        if (backdrop) backdrop.classList.remove('open');
        if (toggle)   toggle.setAttribute('aria-expanded', 'false');
    }

    if (toggle && sidebar) {
        toggle.addEventListener('click', function () {
            sidebar.classList.contains('open') ? closeSidebar() : openSidebar();
        });
    }

    if (backdrop) {
        backdrop.addEventListener('click', closeSidebar);
    }

    // Close sidebar on Escape key
    document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape' && sidebar && sidebar.classList.contains('open')) {
            closeSidebar();
        }
    });

    // ── Collapsible nav-groups ─────────────────────────────────────────────
    document.querySelectorAll('.nav-group-toggle').forEach(function (toggle) {
        toggle.addEventListener('click', function () {
            var group = this.closest('.nav-group');
            if (group) {
                group.classList.toggle('open');
            }
        });
    });

    // ── Auto-dismiss alerts after 5 seconds ───────────────────────────────
    document.querySelectorAll('.alert').forEach(function (alert) {
        setTimeout(function () {
            alert.style.transition = 'opacity 0.3s';
            alert.style.opacity    = '0';
            setTimeout(function () { alert.remove(); }, 300);
        }, 5000);
    });

    // ── Auto-generate slug from title ─────────────────────────────────────
    var titleInput = document.getElementById('title');
    var slugInput  = document.getElementById('slug');

    if (titleInput && slugInput && !slugInput.value) {
        titleInput.addEventListener('input', function () {
            slugInput.value = this.value
                .toLowerCase()
                .replace(/[^a-z0-9äöüß]+/g, '-')
                .replace(/^-|-$/g, '');
        });
    }

    // ── Media Picker wiring ───────────────────────────────────────────────
    // Looks for [data-media-picker] buttons anywhere in the page and wires
    // them to the #mediaPickerOverlay modal (present on pages/form and
    // blog/form). Images are loaded from /admin/media/picker-images (JSON).
    initMediaPicker();
});

/**
 * Initialise the media picker modal.
 *
 * The picker button carries:
 *   data-media-picker          – marks the button
 *   data-editor-target="id"    – id of the <textarea> whose Jodit instance
 *                                should receive the inserted HTML
 */
function initMediaPicker() {
    var btn     = document.querySelector('[data-media-picker]');
    var overlay = document.getElementById('mediaPickerOverlay');

    if (!btn || !overlay) return;

    var body         = document.getElementById('mediaPickerBody');
    var closeBtn     = document.getElementById('mediaPickerClose');
    var editorTarget = btn.dataset.editorTarget || 'content';
    var loaded       = false;

    // ── Open ──────────────────────────────────────────────────────────────
    btn.addEventListener('click', function () {
        overlay.style.display = 'flex';
        if (!loaded) {
            renderPickerShell(body);
            loadPickerImages(body, '', '');
            loaded = true;
        }
    });

    // ── Close ─────────────────────────────────────────────────────────────
    function closePicker() { overlay.style.display = 'none'; }

    closeBtn && closeBtn.addEventListener('click', closePicker);
    overlay.addEventListener('click', function (e) {
        if (e.target === overlay) closePicker();
    });
    document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape' && overlay.style.display !== 'none') closePicker();
    });

    // ── Render shell (toolbar + grid container) ───────────────────────────
    function renderPickerShell(container) {
        var t = window.iwT || {};
        container.innerHTML =
            '<div class="media-picker-toolbar">' +
                '<input type="text" class="media-picker-search" id="pickerSearch" placeholder="' + (t.search_images || 'Search images…') + '" autocomplete="off">' +
                '<span class="media-picker-toolbar-label">' + (t.folder_label || 'Folder:') + '</span>' +
                '<select class="media-picker-folder" id="pickerFolder">' +
                    '<option value="">' + (t.all_media || 'All media') + '</option>' +
                    '<option value="0">' + (t.unassigned || 'Unassigned') + '</option>' +
                '</select>' +
            '</div>' +
            '<div class="media-picker-body" id="pickerGrid">' +
                '<p style="text-align:center;color:var(--gray-400);padding-top:3rem;">' + (t.loading || 'Loading…') + '</p>' +
            '</div>';

        var searchInput  = container.querySelector('#pickerSearch');
        var folderSelect = container.querySelector('#pickerFolder');

        // Debounced search
        var searchTimer;
        searchInput.addEventListener('input', function () {
            clearTimeout(searchTimer);
            var q      = searchInput.value;
            var folder = folderSelect.value;
            searchTimer = setTimeout(function () {
                loadPickerImages(container, q, folder);
            }, 350);
        });

        folderSelect.addEventListener('change', function () {
            loadPickerImages(container, searchInput.value, folderSelect.value);
        });
    }

    // ── Fetch images from JSON endpoint ───────────────────────────────────
    function loadPickerImages(container, q, folder) {
        var grid = container.querySelector('#pickerGrid');
        if (!grid) return;

        grid.innerHTML = '<p style="text-align:center;color:var(--gray-400);padding-top:2rem;">' + ((window.iwT||{}).loading || 'Loading…') + '</p>';

        var url = window.IW_ADMIN + '/media/picker-images?q=' + encodeURIComponent(q) +
                  '&folder=' + encodeURIComponent(folder);

        fetch(url, { credentials: 'same-origin' })
            .then(function (r) { return r.json(); })
            .then(function (data) {
                // Populate named folder options (once, after "All media" + "Unassigned")
                var folderSelect = container.querySelector('#pickerFolder');
                if (folderSelect && folderSelect.options.length <= 2 && data.folders && data.folders.length) {
                    data.folders.forEach(function (f) {
                        var opt = document.createElement('option');
                        opt.value       = f.id;
                        opt.textContent = f.name;
                        folderSelect.appendChild(opt);
                    });
                }

                if (!data.images || data.images.length === 0) {
                    grid.innerHTML = '<p style="text-align:center;color:var(--gray-400);padding-top:3rem;font-size:0.9375rem;">' + ((window.iwT||{}).no_images || 'No images found.') + '</p>';
                    return;
                }

                var html = '<div class="media-picker-grid">';
                data.images.forEach(function (img) {
                    var fullUrl = img.url.indexOf('/') === 0 ? img.url : '/uploads/' + img.url;
                    html += '<div class="media-picker-item" data-url="' + escHtml(fullUrl) + '" data-alt="' + escHtml(img.alt || img.name) + '" title="' + escHtml(img.name) + '">' +
                                '<img src="' + escHtml(img.thumb_url || img.url) + '" alt="' + escHtml(img.name) + '" loading="lazy">' +
                                '<div class="media-picker-item-name">' + escHtml(img.name) + '</div>' +
                            '</div>';
                });
                html += '</div>';
                grid.innerHTML = html;

                // Click handler: insert into editor
                grid.querySelectorAll('.media-picker-item').forEach(function (item) {
                    item.addEventListener('click', function () {
                        var url = item.dataset.url;
                        var alt = item.dataset.alt || '';
                        insertImageIntoEditor(editorTarget, url, alt);
                        closePicker();
                    });
                });
            })
            .catch(function () {
                grid.innerHTML = '<p style="text-align:center;color:var(--admin-danger);padding-top:3rem;font-size:0.9375rem;">' + ((window.iwT||{}).load_failed || 'Failed to load images.') + '</p>';
            });
    }

    // ── Insert <img> tag into the Jodit editor ────────────────────────────
    function insertImageIntoEditor(targetId, url, alt) {
        var textarea = document.getElementById(targetId);
        if (!textarea) return;

        var imgTag = '<img src="' + url + '" alt="' + escAttr(alt) + '">';

        // Try Jodit instance stored on the textarea element
        if (textarea._joditEditor) {
            textarea._joditEditor.selection.insertHTML(imgTag);
            return;
        }

        // Fallback: append to plain textarea value
        textarea.value += '\n' + imgTag;
    }

    // ── HTML helpers ──────────────────────────────────────────────────────
    function escHtml(str) {
        return String(str)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;');
    }
    function escAttr(str) {
        return String(str)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;');
    }
}

// ═══════════════════════════════════════════════════════════════════════════════
// Generic Section Media Field – reusable image picker for any form field
// ═══════════════════════════════════════════════════════════════════════════════
//
// Usage: Call initSectionMediaFields() or attach to elements with
// class "section-media-field-wrap". Each wrap contains:
//   <input type="text" name="..." class="section-media-input">
//   <button type="button" class="section-media-browse">Browse Media</button>
//   <button type="button" class="section-media-remove">×</button>
//   <div class="section-media-preview"><img></div>
//
// The browse button opens a shared modal. On image select, the input gets
// the image URL and the preview updates. Works for multiple fields on the
// same page (each opens the same modal but writes to its own input).
//
(function () {
    'use strict';

    var _smfModal       = null;   // Shared modal element
    var _smfLoaded      = false;  // Whether images have been fetched
    var _smfActiveField = null;   // Which input should receive the selected image

    // ── Public initialiser – call after DOM ready or after dynamic content ──
    window.initSectionMediaFields = function (root) {
        root = root || document;
        root.querySelectorAll('.section-media-field-wrap').forEach(function (wrap) {
            if (wrap._smfInitialised) return;
            wrap._smfInitialised = true;

            var input   = wrap.querySelector('.section-media-input');
            var browse  = wrap.querySelector('.section-media-browse');
            var remove  = wrap.querySelector('.section-media-remove');
            var preview = wrap.querySelector('.section-media-preview');
            var prevImg = preview ? preview.querySelector('img') : null;

            // Update preview visibility
            function refreshPreview() {
                if (!preview || !prevImg) return;
                var val = (input ? input.value : '').trim();
                if (val) {
                    prevImg.src = val.indexOf('/') === 0 ? val : '/uploads/' + val;
                    prevImg.alt = '';
                    preview.style.display = '';
                } else {
                    preview.style.display = 'none';
                    prevImg.src = '';
                }
            }

            // Initial state
            refreshPreview();

            // Browse button → open modal
            if (browse && input) {
                browse.addEventListener('click', function (e) {
                    e.preventDefault();
                    _smfActiveField = { input: input, refreshPreview: refreshPreview };
                    openSMFModal();
                });
            }

            // Remove button → clear field
            if (remove && input) {
                remove.addEventListener('click', function (e) {
                    e.preventDefault();
                    input.value = '';
                    refreshPreview();
                });
            }

            // Manual edit → refresh preview
            if (input) {
                input.addEventListener('change', refreshPreview);
            }
        });
    };

    // ── Upload helper inside modal ──────────────────────────────────────────
    function handleSMFUpload(file) {
        if (!file) { return; }

        var grid = _smfModal ? _smfModal.querySelector('.smf-grid') : null;

        // Pre-flight: client-side file size check (5 MB images / 200 MB videos)
        var t = window.iwT || {};
        var isVideoFile = file.type.indexOf('video/') === 0;
        var maxBytes = isVideoFile ? 200 * 1024 * 1024 : 5 * 1024 * 1024;
        var maxLabel = isVideoFile ? '200 MB' : '5 MB';
        if (file.size > maxBytes) {
            var sizeMsg = 'File too large (max. ' + maxLabel + '). Current size: ' + (file.size / 1024 / 1024).toFixed(1) + ' MB';
            if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + sizeMsg + '</p>';
            return;
        }

        // Pre-flight: check CSRF token exists
        var csrfInput = document.querySelector('input[name="_csrf_token"]');
        if (!csrfInput || !csrfInput.value) {
            if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + (t.csrf_missing || 'CSRF token missing.') + '</p>';
            return;
        }

        var formData = new FormData();
        formData.append('media_file', file);
        formData.append('_csrf_token', csrfInput.value);

        var uploadingMsg = (t.uploading || 'Uploading… (:size KB)').replace(':size', (file.size / 1024).toFixed(0));
        if (grid) grid.innerHTML = '<p style="text-align:center;padding:2rem;color:#6b7280;">' + uploadingMsg + '</p>';

        // Use XMLHttpRequest for better compatibility and progress tracking
        var xhr = new XMLHttpRequest();
        xhr.open('POST', window.IW_ADMIN + '/media/upload', true);
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

        xhr.onload = function () {
            var data;
            try {
                data = JSON.parse(xhr.responseText);
            } catch (e) {
                // Server returned non-JSON (e.g. plain text error, HTML error page)
                var msg = xhr.responseText || ('HTTP ' + xhr.status);
                var httpErrMsg = (t.upload_http_err || 'Upload failed (HTTP :status): :body').replace(':status', xhr.status).replace(':body', msg.replace(/</g, '&lt;').substring(0, 200));
                if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + httpErrMsg + '</p>';
                return;
            }

            if (data.success && data.url) {
                if (_smfActiveField) {
                    _smfActiveField.input.value = data.url;
                    _smfActiveField.refreshPreview();
                }
                closeSMFModal();
            } else if (data.error) {
                var failMsg = (t.upload_failed || 'Upload failed: :error').replace(':error', (data.error || '').replace(/</g, '&lt;'));
                if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + failMsg + '</p>';
            } else {
                // Upload succeeded but no URL returned – refresh grid
                _smfLoaded = false;
                loadSMFImages();
            }
        };

        xhr.onerror = function () {
            if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + (t.network_error || 'Network error.') + '</p>';
        };

        xhr.ontimeout = function () {
            if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + (t.upload_timeout || 'Upload timeout.') + '</p>';
        };

        xhr.timeout = 60000; // 60 seconds
        xhr.send(formData);
    }

    // ── Build & open the shared modal ───────────────────────────────────────
    function openSMFModal() {
        if (!_smfModal) {
            _smfModal = document.createElement('div');
            _smfModal.id = 'sectionMediaPickerOverlay';
            _smfModal.className = 'media-picker-overlay';
            _smfModal.setAttribute('role', 'dialog');
            _smfModal.setAttribute('aria-modal', 'true');
            var t = window.iwT || {};
            _smfModal.setAttribute('aria-label', t.select_image || 'Select image');
            _smfModal.innerHTML =
                '<div class="media-picker-modal" style="max-width:860px;">' +
                    '<div class="media-picker-header">' +
                        '<h3>' + (t.select_image || 'Select image') + '</h3>' +
                        '<button type="button" class="media-picker-close smf-close" aria-label="Close">&times;</button>' +
                    '</div>' +
                    '<div class="smf-toolbar" style="display:flex;gap:0.75rem;padding:0.75rem 1.25rem;border-bottom:1px solid #e5e7eb;align-items:center;">' +
                        '<input type="text" class="form-control smf-search" placeholder="' + (t.search || 'Search…') + '" style="flex:1;">' +
                        '<label class="btn btn-secondary btn-sm" style="cursor:pointer;margin:0;">' +
                            (t.upload_btn || '⬆ Upload') + ' <input type="file" class="smf-upload-input" accept="image/*,video/mp4,video/webm,video/ogg,video/quicktime,.mp4,.webm,.ogv,.mov" style="display:none;">' +
                        '</label>' +
                    '</div>' +
                    '<div class="smf-grid" style="padding:1rem;max-height:420px;overflow-y:auto;">' +
                        '<p style="text-align:center;color:#6b7280;padding:2rem;">' + (t.loading || 'Loading…') + '</p>' +
                    '</div>' +
                '</div>';
            document.body.appendChild(_smfModal);

            // Close button
            _smfModal.querySelector('.smf-close').addEventListener('click', closeSMFModal);

            // Backdrop click
            _smfModal.addEventListener('click', function (e) {
                if (e.target === _smfModal) closeSMFModal();
            });

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

            // Search
            var searchInput = _smfModal.querySelector('.smf-search');
            if (searchInput) {
                searchInput.addEventListener('input', function () {
                    var q = this.value.toLowerCase();
                    _smfModal.querySelectorAll('.smf-item').forEach(function (item) {
                        var name = (item.dataset.name || '').toLowerCase();
                        item.style.display = (!q || name.indexOf(q) !== -1) ? '' : 'none';
                    });
                });
            }

            // Upload input
            var uploadInput = _smfModal.querySelector('.smf-upload-input');
            if (uploadInput) {
                uploadInput.addEventListener('change', function () {
                    if (this.files && this.files[0]) handleSMFUpload(this.files[0]);
                    this.value = '';
                });
            }
        }

        _smfModal.style.display = '';
        document.body.classList.add('iw-modal-open');

        if (!_smfLoaded) loadSMFImages();
    }

    function closeSMFModal() {
        if (_smfModal) _smfModal.style.display = 'none';
        document.body.classList.remove('iw-modal-open');
        _smfActiveField = null;
    }

    // ── Fetch images from /admin/media/picker-images ────────────────────────
    function loadSMFImages() {
        var grid = _smfModal ? _smfModal.querySelector('.smf-grid') : null;
        if (!grid) return;

        var t = window.iwT || {};
        grid.innerHTML = '<p style="text-align:center;color:#6b7280;padding:2rem;">' + (t.loading || 'Loading…') + '</p>';

        fetch(window.IW_ADMIN + '/media/picker-images')
            .then(function (r) { return r.json(); })
            .then(function (data) {
                _smfLoaded = true;
                var images = data.images || data || [];
                if (!images.length) {
                    grid.innerHTML = '<p style="text-align:center;color:#6b7280;padding:2rem;">' + (t.no_images || 'No images found.') + '</p>';
                    return;
                }

                var html = '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:0.5rem;">';
                images.forEach(function (img) {
                    var url  = _escH(img.url || '');
                    var thumb = _escH(img.thumb_url || img.url || '');
                    var name = _escH(img.name || img.title || '');
                    html += '<div class="smf-item" data-url="' + url + '" data-name="' + name + '" ' +
                            'style="cursor:pointer;border:2px solid transparent;border-radius:6px;overflow:hidden;aspect-ratio:1;background:#f3f4f6;" ' +
                            'title="' + name + '">' +
                            '<img src="' + thumb + '" alt="' + name + '" loading="lazy" ' +
                            'style="width:100%;height:100%;object-fit:cover;">' +
                            '</div>';
                });
                html += '</div>';
                grid.innerHTML = html;

                // Click handler → select image
                grid.querySelectorAll('.smf-item').forEach(function (item) {
                    item.addEventListener('click', function () {
                        if (_smfActiveField) {
                            _smfActiveField.input.value = item.dataset.url;
                            _smfActiveField.refreshPreview();
                        }
                        closeSMFModal();
                    });
                });
            })
            .catch(function () {
                grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + ((window.iwT||{}).load_failed || 'Failed to load images.') + '</p>';
            });
    }

    function _escH(str) {
        return String(str).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
    }

    // Auto-init on DOMContentLoaded
    document.addEventListener('DOMContentLoaded', function () {
        initSectionMediaFields();
    });
})();

// =============================================================================
// IW Media Picker – global API (Phase video-hero)
// =============================================================================
//
// Provides window.iwOpenMediaPicker(type, callback) where:
//   type     – 'image' or 'video'
//   callback – function(item) called when user selects an item.
//              item = { url, file_path, name, thumb_url, poster_url, file_type }
//
// Also wires up all .iw-mpf-pick-btn and .iw-mpf-clear-btn elements
// anywhere in the DOM (hero admin form, media edit page, etc.).
// =============================================================================
(function () {
    'use strict';

    var T = window.iwT || {};
    var _iwmpModal    = null;
    var _iwmpCallback = null;
    var _iwmpType     = 'image';

    function escH(str) {
        return String(str || '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
    }

    // ── Build modal (once) ────────────────────────────────────────────────
    function buildModal() {
        if (_iwmpModal) return;

        _iwmpModal = document.createElement('div');
        _iwmpModal.id = 'iwmpOverlay';
        _iwmpModal.className = 'media-picker-overlay';
        _iwmpModal.setAttribute('role', 'dialog');
        _iwmpModal.setAttribute('aria-modal', 'true');
        _iwmpModal.style.display = 'none';

        _iwmpModal.innerHTML =
            '<div class="media-picker-modal" style="max-width:900px;">' +
                '<div class="media-picker-header">' +
                    '<h3 id="iwmpTitle">' + escH(T.media_library || 'Media Library') + '</h3>' +
                    '<button type="button" class="media-picker-close" id="iwmpClose" aria-label="' + escH(T.close || 'Close') + '">&times;</button>' +
                '</div>' +
                '<div class="iwmp-toolbar" style="display:flex;gap:.75rem;padding:.75rem 1.25rem;border-bottom:1px solid #e5e7eb;align-items:center;flex-wrap:wrap;">' +
                    '<input type="text" id="iwmpSearch" placeholder="' + escH(T.search || 'Search…') + '" style="flex:1;min-width:160px;" class="form-control">' +
                    '<label class="btn btn-secondary btn-sm" id="iwmpUploadLabel" style="cursor:pointer;margin:0;">' +
                        (T.upload_btn || '⬆ Upload') +
                        '<input type="file" id="iwmpUploadInput" style="display:none;" multiple>' +
                    '</label>' +
                '</div>' +
                '<div id="iwmpGrid" style="padding:1rem;max-height:460px;overflow-y:auto;">' +
                    '<p style="text-align:center;color:#6b7280;padding:2rem;">' + escH(T.loading_short || 'Loading…') + '</p>' +
                '</div>' +
            '</div>';

        document.body.appendChild(_iwmpModal);

        // Close handlers
        document.getElementById('iwmpClose').addEventListener('click', closeModal);
        _iwmpModal.addEventListener('click', function (e) { if (e.target === _iwmpModal) closeModal(); });
        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape' && _iwmpModal.style.display !== 'none') closeModal();
        });

        // Search
        var searchInput = document.getElementById('iwmpSearch');
        if (searchInput) {
            var searchTimer;
            searchInput.addEventListener('input', function () {
                clearTimeout(searchTimer);
                var q = this.value;
                searchTimer = setTimeout(function () { loadItems(q); }, 350);
            });
        }

        // Upload
        var uploadInput = document.getElementById('iwmpUploadInput');
        if (uploadInput) {
            uploadInput.addEventListener('change', function () {
                var files = this.files;
                if (!files || !files.length) return;
                var file = files[0];

                // Size guard
                var isVid = file.type.indexOf('video/') === 0;
                var maxB  = isVid ? 200 * 1024 * 1024 : 5 * 1024 * 1024;
                if (file.size > maxB) {
                    var grid = document.getElementById('iwmpGrid');
                    if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + escH((T.file_too_large_short || 'File too large (max. :max MB).').replace(':max', isVid ? '200' : '5')) + '</p>';
                    return;
                }

                var csrfInput = document.querySelector('input[name="_csrf_token"]');
                if (!csrfInput) return;

                var fd = new FormData();
                fd.append('media_file[]', file);
                fd.append('_csrf_token', csrfInput.value);

                var grid = document.getElementById('iwmpGrid');
                if (grid) grid.innerHTML = '<p style="text-align:center;color:#6b7280;padding:2rem;">' + escH(T.uploading_short || 'Uploading…') + '</p>';

                var xhr = new XMLHttpRequest();
                xhr.open('POST', window.IW_ADMIN + '/media/upload', true);
                xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                xhr.timeout = 120000;
                xhr.onload = function () {
                    try {
                        var resp = JSON.parse(xhr.responseText);
                        if (resp.success) {
                            loadItems('');
                        } else {
                            if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + escH(resp.error || T.upload_failed_short || 'Upload failed.') + '</p>';
                        }
                    } catch (e) {
                        if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + escH(T.upload_failed_short || 'Upload failed.') + ' (HTTP ' + xhr.status + ')</p>';
                    }
                };
                xhr.onerror = function () {
                    if (grid) grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + escH(T.network_error || 'Network error.') + '</p>';
                };
                xhr.send(fd);

                this.value = '';
            });
        }
    }

    // ── Load items from API ──────────────────────────────────────────────
    function loadItems(q) {
        var grid = document.getElementById('iwmpGrid');
        if (!grid) return;

        grid.innerHTML = '<p style="text-align:center;color:#6b7280;padding:2rem;">' + escH(T.loading_short || 'Loading…') + '</p>';

        var endpoint = _iwmpType === 'video'
            ? window.IW_ADMIN + '/media/picker-videos?q=' + encodeURIComponent(q || '')
            : window.IW_ADMIN + '/media/picker-images?q=' + encodeURIComponent(q || '');

        fetch(endpoint, { credentials: 'same-origin' })
            .then(function (r) { return r.json(); })
            .then(function (data) {
                var items = _iwmpType === 'video' ? (data.videos || []) : (data.images || []);

                if (!items.length) {
                    grid.innerHTML = '<p style="text-align:center;color:#6b7280;padding:2rem;">' +
                        (_iwmpType === 'video' ? (T.no_videos || 'No videos found.') : (T.no_images || 'No images found.')) + '</p>';
                    return;
                }

                var html = '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(110px,1fr));gap:.5rem;">';
                items.forEach(function (item) {
                    var thumb = '';
                    if (_iwmpType === 'video') {
                        thumb = item.poster_url
                            ? '<img src="' + escH(item.poster_url) + '" alt="' + escH(item.name) + '" loading="lazy" style="width:100%;height:100%;object-fit:cover;">'
                            : '<div style="display:flex;align-items:center;justify-content:center;height:100%;font-size:2rem;background:#e0f2fe;">▶</div>';
                    } else {
                        var thumbSrc = item.thumb_url || ('/uploads/' + item.url);
                        thumb = '<img src="' + escH(thumbSrc) + '" alt="' + escH(item.name) + '" loading="lazy" style="width:100%;height:100%;object-fit:cover;">';
                    }
                    html +=
                        '<div class="iwmp-item" ' +
                            'data-url="' + escH(item.url) + '" ' +
                            'data-file-path="' + escH(item.file_path || item.url.replace('/uploads/', '')) + '" ' +
                            'data-name="' + escH(item.name) + '" ' +
                            'data-thumb="' + escH(item.thumb_url || '') + '" ' +
                            'data-poster="' + escH(item.poster_url || '') + '" ' +
                            'data-file-type="' + escH(item.file_type || '') + '" ' +
                            'title="' + escH(item.name) + '" ' +
                            'style="cursor:pointer;border:2px solid transparent;border-radius:6px;overflow:hidden;aspect-ratio:1;background:#f3f4f6;position:relative;">' +
                            thumb +
                            (_iwmpType === 'video' ? '<div style="position:absolute;bottom:4px;right:4px;background:rgba(0,0,0,.6);color:#fff;border-radius:3px;font-size:0.65rem;padding:1px 4px;">VIDEO</div>' : '') +
                        '</div>';
                });
                html += '</div>';
                grid.innerHTML = html;

                // Click: call callback
                grid.querySelectorAll('.iwmp-item').forEach(function (el) {
                    el.addEventListener('click', function () {
                        if (typeof _iwmpCallback === 'function') {
                            _iwmpCallback({
                                url:       el.dataset.url,
                                file_path: el.dataset.filePath,
                                name:      el.dataset.name,
                                thumb_url: el.dataset.thumb,
                                poster_url: el.dataset.poster,
                                file_type: el.dataset.fileType,
                            });
                        }
                        closeModal();
                    });
                });
            })
            .catch(function () {
                grid.innerHTML = '<p style="text-align:center;color:#dc2626;padding:2rem;">' + escH(T.load_failed_short || 'Failed to load.') + '</p>';
            });
    }

    function openModal(type, callback) {
        _iwmpType     = type || 'image';
        _iwmpCallback = callback;

        buildModal();

        // Update title + upload accept
        var title  = document.getElementById('iwmpTitle');
        var upload = document.getElementById('iwmpUploadInput');
        if (title) title.textContent = _iwmpType === 'video' ? (T.select_video || 'Select video') : (T.select_image || 'Select image');
        if (upload) {
            upload.accept = _iwmpType === 'video'
                ? 'video/mp4,video/webm,video/ogg,video/quicktime,.mp4,.webm,.ogv,.mov'
                : 'image/*,.svg,.ico';
        }

        _iwmpModal.style.display = 'flex';
        document.body.classList.add('iw-modal-open');

        var search = document.getElementById('iwmpSearch');
        if (search) search.value = '';

        loadItems('');
    }

    function closeModal() {
        if (_iwmpModal) _iwmpModal.style.display = 'none';
        document.body.classList.remove('iw-modal-open');
        _iwmpCallback = null;
    }

    // ── Public API ────────────────────────────────────────────────────────
    window.iwOpenMediaPicker = openModal;

    // ── Wire .iw-mpf-pick-btn and .iw-mpf-clear-btn ───────────────────────
    function wireMpfButtons(root) {
        root = root || document;

        root.querySelectorAll('.iw-mpf-pick-btn').forEach(function (btn) {
            if (btn._iwmpWired) return;
            btn._iwmpWired = true;

            btn.addEventListener('click', function () {
                var pickerType  = btn.dataset.pickerType || 'image';
                var inputId     = btn.dataset.input;
                var previewId   = btn.dataset.preview;
                var inputEl     = inputId ? document.getElementById(inputId) : null;
                var previewWrap = previewId ? document.getElementById(previewId) : null;

                openModal(pickerType, function (item) {
                    // Determine what value to store: relative path (for hero sections) or full URL
                    var relPath = item.file_path || item.url.replace(/^\/uploads\//, '');

                    if (inputEl) inputEl.value = relPath;

                    if (previewWrap) {
                        // Remove any placeholder text nodes/spans before showing media
                        previewWrap.querySelectorAll('.iw-mpf-placeholder').forEach(function (el) { el.remove(); });

                        if (pickerType === 'video') {
                            var vid = previewWrap.querySelector('video') || document.createElement('video');
                            vid.src = '/uploads/' + item.url;
                            vid.style.cssText = 'max-height:80px;border-radius:4px;display:block;';
                            vid.muted = true;
                            vid.preload = 'metadata';
                            if (!previewWrap.querySelector('video')) previewWrap.appendChild(vid);
                        } else {
                            var img = previewWrap.querySelector('img') || document.createElement('img');
                            img.src = '/uploads/' + item.url;
                            img.alt = item.name || '';
                            img.style.cssText = 'max-height:80px;border-radius:4px;display:block;';
                            if (!previewWrap.querySelector('img')) previewWrap.appendChild(img);
                        }
                        previewWrap.style.display = '';
                    }
                });
            });
        });

        root.querySelectorAll('.iw-mpf-clear-btn').forEach(function (btn) {
            if (btn._iwmpWired) return;
            btn._iwmpWired = true;

            btn.addEventListener('click', function () {
                var inputId     = btn.dataset.input;
                var previewId   = btn.dataset.preview;
                var inputEl     = inputId ? document.getElementById(inputId) : null;
                var previewWrap = previewId ? document.getElementById(previewId) : null;

                if (inputEl) inputEl.value = '';
                if (previewWrap) previewWrap.style.display = 'none';
            });
        });
    }

    document.addEventListener('DOMContentLoaded', function () {
        wireMpfButtons(document);
    });

    // Re-expose for dynamic content
    window.iwWireMpfButtons = wireMpfButtons;

})();

// =============================================================================
// IW Toast System – Global notification API (Phase 3c)
// =============================================================================
//
// Usage from JS:
//   iwToast('Settings saved', 'success');
//   iwToast('Upload failed', 'error', 'The file was too large.');
//   iwToast('Note', 'info', 'Check your email.', 8000);
//
// Also auto-dismisses server-side .alert flash messages after 5 seconds.
// =============================================================================
(function () {
    'use strict';

    var ICON_PATHS = {
        success: '<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/>',
        error:   '<circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',
        warning: '<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>',
        info:    '<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>'
    };

    var container = null;

    function getContainer() {
        if (container) return container;
        container = document.createElement('div');
        container.className = 'toast-container';
        container.setAttribute('aria-live', 'polite');
        container.setAttribute('aria-atomic', 'false');
        document.body.appendChild(container);
        return container;
    }

    function createIcon(type) {
        var path = ICON_PATHS[type] || ICON_PATHS.info;
        return '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' + path + '</svg>';
    }

    /**
     * Show a toast notification.
     * @param {string} title   – Main text
     * @param {string} type    – 'success'|'error'|'warning'|'info'
     * @param {string} message – Optional detail text
     * @param {number} duration – Auto-dismiss ms (0 = manual, default 5000)
     */
    function showToast(title, type, message, duration) {
        type = type || 'info';
        duration = typeof duration === 'number' ? duration : 5000;

        var el = document.createElement('div');
        el.className = 'toast toast--' + type;
        el.setAttribute('role', type === 'error' ? 'alert' : 'status');

        var html = '<div class="toast-icon">' + createIcon(type) + '</div>';
        html += '<div class="toast-body">';
        html += '<div class="toast-title">' + escHtml(title) + '</div>';
        if (message) {
            html += '<div class="toast-message">' + escHtml(message) + '</div>';
        }
        html += '</div>';
        html += '<button type="button" class="toast-close" aria-label="Close">';
        html += '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>';
        html += '</button>';

        el.innerHTML = html;

        var closeBtn = el.querySelector('.toast-close');
        closeBtn.addEventListener('click', function () { dismissToast(el); });

        getContainer().appendChild(el);

        // Trigger slide-in animation
        requestAnimationFrame(function () {
            requestAnimationFrame(function () {
                el.classList.add('toast-visible');
            });
        });

        // Auto-dismiss
        if (duration > 0) {
            setTimeout(function () { dismissToast(el); }, duration);
        }

        return el;
    }

    function dismissToast(el) {
        if (!el || el._dismissed) return;
        el._dismissed = true;
        el.classList.remove('toast-visible');
        el.classList.add('toast-exit');
        setTimeout(function () {
            if (el.parentNode) el.parentNode.removeChild(el);
        }, 350);
    }

    function escHtml(str) {
        var d = document.createElement('div');
        d.textContent = str;
        return d.innerHTML;
    }

    // Expose globally
    window.iwToast = showToast;

    // ── Auto-dismiss server-side flash messages ────────────────────────────
    document.addEventListener('DOMContentLoaded', function () {
        var alerts = document.querySelectorAll('.admin-content > .alert');
        alerts.forEach(function (alert) {
            // Skip persistent warnings (theme fallback, plugin errors, safe mode)
            if (alert.querySelector('ul') || alert.querySelector('a[href="/admin/themes"]') || alert.querySelector('a[href="/admin/plugins"]')) {
                return;
            }

            alert.setAttribute('data-auto-dismiss', '');

            setTimeout(function () {
                alert.classList.add('alert-dismissing');
                setTimeout(function () {
                    if (alert.parentNode) alert.parentNode.removeChild(alert);
                }, 350);
            }, 5000);
        });
    });

    // ─────────────────────────────────────────────────────────────────────
    // Tabs (generic iw-tabs component)
    // ─────────────────────────────────────────────────────────────────────
    document.querySelectorAll('.iw-tabs').forEach(function (tabBar) {
        tabBar.querySelectorAll('.iw-tab').forEach(function (tab) {
            tab.addEventListener('click', function () {
                var targetId = tab.getAttribute('data-tab');
                if (!targetId) return;

                tabBar.querySelectorAll('.iw-tab').forEach(function (t) {
                    t.classList.remove('active');
                    t.setAttribute('aria-selected', 'false');
                });
                var container = tabBar.parentElement;
                container.querySelectorAll('.iw-tab-panel').forEach(function (p) {
                    p.classList.remove('active');
                });

                tab.classList.add('active');
                tab.setAttribute('aria-selected', 'true');
                var panel = document.getElementById(targetId);
                if (panel) panel.classList.add('active');
            });
        });
    });

    // ─────────────────────────────────────────────────────────────────────
    // Mail Settings (v3.3.0 Phase 4)
    // ─────────────────────────────────────────────────────────────────────
    (function () {
        var transportCards = document.querySelectorAll('.mail-transport-card');
        var smtpPanel      = document.getElementById('smtp-settings');

        if (!transportCards.length) return;

        transportCards.forEach(function (card) {
            card.addEventListener('click', function () {
                transportCards.forEach(function (c) { c.classList.remove('selected'); });
                card.classList.add('selected');

                var transport = card.getAttribute('data-transport');
                if (smtpPanel) {
                    if (transport === 'smtp') {
                        smtpPanel.classList.add('visible');
                    } else {
                        smtpPanel.classList.remove('visible');
                    }
                }
            });
        });

        // Password toggle (handled by global handler below)

        // Test mail button (AJAX)
        var testBtn  = document.getElementById('mail-test-btn');
        var feedback = document.getElementById('mail-action-feedback');
        if (testBtn) {
            testBtn.addEventListener('click', function () {
                testBtn.disabled = true;
                testBtn.style.opacity = '0.6';

                var csrfInput = document.querySelector('#mail-settings-form input[name="_csrf_token"]');
                var csrfToken = csrfInput ? csrfInput.value : '';

                var fd = new FormData();
                fd.append('_csrf_token', csrfToken);

                fetch(window.IW_ADMIN + '/settings/mail/test', {
                    method: 'POST',
                    body: fd,
                    headers: { 'X-Requested-With': 'XMLHttpRequest' }
                })
                .then(function (res) { return res.json(); })
                .then(function (data) {
                    if (feedback) {
                        feedback.textContent = data.message || (data.ok ? 'OK' : 'Error');
                        feedback.className = 'mail-action-feedback show ' + (data.ok ? 'success' : 'error');
                        setTimeout(function () { feedback.classList.remove('show'); }, 5000);
                    }
                    if (typeof iwToast === 'function') {
                        iwToast(data.message, data.ok ? 'success' : 'error', '', 5000);
                    }
                })
                .catch(function () {
                    if (feedback) {
                        feedback.textContent = 'Netzwerkfehler';
                        feedback.className = 'mail-action-feedback show error';
                    }
                })
                .finally(function () {
                    testBtn.disabled = false;
                    testBtn.style.opacity = '';
                });
            });
        }
    })();

    // ── F4: Dashboard ───────────────────────────────────────────────────────
    (function () {
        var dashLeft  = document.getElementById('dash-col-left');
        var dashRight = document.getElementById('dash-col-right');
        if (!dashLeft && !dashRight) return;

        var csrfToken = (document.getElementById('dash-csrf-token') || {}).value || '';

        // Helper: AJAX POST
        function dashPost(url, formData) {
            formData.append('_csrf_token', csrfToken);
            fetch(url, {
                method: 'POST',
                body: formData,
                headers: { 'X-Requested-With': 'XMLHttpRequest' }
            }).catch(function () {});
        }

        // Collect current column order and save to server
        function saveLayout() {
            var layout = { left: [], right: [] };
            if (dashLeft) {
                dashLeft.querySelectorAll(':scope > .dash-panel').forEach(function (p) {
                    var id = p.getAttribute('data-panel-id');
                    if (id) layout.left.push(id);
                });
            }
            if (dashRight) {
                dashRight.querySelectorAll(':scope > .dash-panel').forEach(function (p) {
                    var id = p.getAttribute('data-panel-id');
                    if (id) layout.right.push(id);
                });
            }
            var fd = new FormData();
            fd.append('layout', JSON.stringify(layout));
            dashPost(window.IW_ADMIN + '/dashboard/save-layout', fd);
        }

        // Sortable.js – drag & drop panel ordering
        if (typeof Sortable !== 'undefined') {
            var sortableOpts = {
                group: 'dashboard-panels',
                handle: '.dash-panel-drag-handle',
                animation: 150,
                ghostClass: 'sortable-ghost',
                chosenClass: 'sortable-chosen',
                dragClass: 'sortable-drag',
                onEnd: function () { saveLayout(); }
            };
            if (dashLeft)  Sortable.create(dashLeft,  sortableOpts);
            if (dashRight) Sortable.create(dashRight, sortableOpts);
        }

        // Eye icon SVGs for eye/eye-off
        var SVG_EYE     = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></svg>';
        var SVG_EYE_OFF = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"/><path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"/><path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"/><path d="m2 2 20 20"/></svg>';

        // Panel visibility toggle (eye button)
        document.addEventListener('click', function (e) {
            var btn = e.target.closest('.dash-panel-eye');
            if (!btn) return;
            var panelId = btn.getAttribute('data-panel-id');
            var panel   = document.querySelector('.dash-panel[data-panel-id="' + panelId + '"]');
            if (!panel) return;

            var isNowCollapsed = panel.classList.toggle('dash-panel--collapsed');
            btn.innerHTML = isNowCollapsed ? SVG_EYE_OFF : SVG_EYE;
            btn.title = isNowCollapsed ? 'Panel ausklappen' : 'Panel einklappen';

            var fd = new FormData();
            fd.append('panel', panelId);
            fd.append('visible', isNowCollapsed ? '0' : '1');
            dashPost(window.IW_ADMIN + '/dashboard/toggle-panel', fd);
        });

        // Quick-Draft: disable button on submit to prevent double-submit
        var qdForm = document.getElementById('quick-draft-form');
        if (qdForm) {
            qdForm.addEventListener('submit', function () {
                var btn = qdForm.querySelector('button[type="submit"]');
                if (btn) { btn.disabled = true; btn.textContent = '...'; }
            });
        }

        // What's New Banner – close + localStorage persistence
        var newsBanner = document.getElementById('dash-news-banner');
        var newsClose  = document.getElementById('dash-news-close');
        if (newsBanner) {
            try {
                if (localStorage.getItem('iw_news_banner_dismissed') === '1') {
                    newsBanner.classList.add('is-hidden');
                }
            } catch (err) {}
            if (newsClose) {
                newsClose.addEventListener('click', function () {
                    newsBanner.classList.add('is-hidden');
                    try { localStorage.setItem('iw_news_banner_dismissed', '1'); } catch (err) {}
                });
            }
        }
    })();

    // ── Global Password Visibility Toggle ────────────────────────────────────
    (function () {
        document.querySelectorAll('.password-toggle').forEach(function (btn) {
            btn.addEventListener('click', function () {
                var wrap  = btn.closest('.input-password-wrap');
                if (!wrap) return;
                var input = wrap.querySelector('input[type="password"], input[type="text"]');
                if (!input) return;

                var isHidden = input.type === 'password';
                input.type = isHidden ? 'text' : 'password';

                var iconEye    = btn.querySelector('.icon-eye');
                var iconEyeOff = btn.querySelector('.icon-eye-off');
                if (iconEye)    iconEye.style.display    = isHidden ? 'none' : '';
                if (iconEyeOff) iconEyeOff.style.display = isHidden ? '' : 'none';

                input.focus();
            });
        });
    })();

})();
