jQuery(document).ready(function ($) {

    // Initialize hero confetti animation
    initHeroConfetti();

    // Initialize footer confetti
    initFooterConfetti();

    // Tab navigation
    initTabNavigation();

    // Form validation
    initFormValidation();

    // Auto-save functionality
    // initAutoSave(); — disabled: showed fake "Saving..." without actually saving

    // Save-confirmation toasts
    tamrankInitSaveToasts();

    // 404 Monitor
    tamrankInit404Monitor($);

    /**
     * Translation helper for JS strings
     */
    const t = (key, fallback) => {
        if (window.tamRank && tamRank.i18n && tamRank.i18n[key]) {
            return tamRank.i18n[key];
        }
        return fallback;
    };

    /**
     * Initialize hero confetti animation
     */
    function initHeroConfetti() {
        const heroSection = document.querySelector(".hero-confetti");
        const wrapper = document.getElementById("tamConfettiWrapper");
        if (!heroSection || !wrapper) return;

        heroSection.appendChild(wrapper);

        const colors = ["#25AC75", "#DC7EA0", "#3b82f6", "#FAA530"];

        function createTamBubble() {
            const maxX = wrapper.offsetWidth;
            const maxY = wrapper.offsetHeight;

            if (maxX < 10 || maxY < 10) return;

            const dot = document.createElement("div");
            dot.classList.add("tam-confetti-dot");
            dot.textContent = "TAM";

            const size = 20 + Math.random() * 20;
            dot.style.width = `${size}px`;
            dot.style.height = `${size}px`;
            dot.style.fontSize = `${size * 0.4}px`;
            dot.style.color = "#fff";
            dot.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];

            const startX = Math.random() * maxX;
            const startY = Math.random() * maxY;

            dot.style.left = `${startX}px`;
            dot.style.top = `${startY}px`;

            wrapper.appendChild(dot);

            const angle = Math.random() * 2 * Math.PI;
            const distance = 50 + Math.random() * 100;
            const dx = Math.cos(angle) * distance;
            const dy = Math.sin(angle) * distance;

            dot.animate(
                [
                    { transform: "translate(0, 0)", opacity: 1 },
                    { transform: `translate(${dx}px, ${dy}px)`, opacity: 0 }
                ],
                {
                    duration: 3000 + Math.random() * 2000,
                    easing: "ease-out",
                    fill: "forwards"
                }
            );

            setTimeout(() => dot.remove(), 5000);
        }

        function startBubblesWhenReady() {
            if (wrapper.offsetHeight < 10 || wrapper.offsetWidth < 10) {
                return setTimeout(startBubblesWhenReady, 100);
            }

            // Initial bubbles
            for (let i = 0; i < 30; i++) {
                setTimeout(createTamBubble, Math.random() * 1500);
            }

            // Continuous bubbles
            setInterval(() => {
                for (let i = 0; i < 2; i++) createTamBubble();
            }, 600);
        }

        startBubblesWhenReady();
    }

    /**
     * Initialize footer confetti effect
     */
    function initFooterConfetti() {
        const colors = ["#25AC75", "#DC7EA0", "#3b82f6", "#FAA530"];
        let confettiInterval;

        function createConfetti(x, y) {
            const dot = document.createElement("div");
            dot.classList.add("confetti-dot");
            dot.textContent = "TAM";

            const size = 10 + Math.random() * 10;
            dot.style.width = `${size}px`;
            dot.style.height = `${size}px`;
            dot.style.fontSize = `${size * 0.4}px`;

            dot.style.left = `${x}px`;
            dot.style.top = `${y}px`;
            dot.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];

            document.body.appendChild(dot);

            const angle = Math.random() * 2 * Math.PI;
            const distance = 50 + Math.random() * 50;
            const dx = Math.cos(angle) * distance;
            const dy = Math.sin(angle) * distance;

            dot.animate(
                [
                    { transform: `translate(0, 0)`, opacity: 1 },
                    { transform: `translate(${dx}px, ${dy}px)`, opacity: 0 }
                ],
                {
                    duration: 2000,
                    easing: "ease-out",
                    fill: "forwards"
                }
            );

            setTimeout(() => {
                dot.remove();
            }, 2000);
        }

        const confettiTarget = document.getElementById("confettiTarget");

        if (confettiTarget) {
            // Desktop: mouse
            confettiTarget.addEventListener("mouseenter", () => {
                confettiInterval = setInterval(() => {
                    const rect = confettiTarget.getBoundingClientRect();
                    const centerX = rect.left + rect.width / 2;
                    const centerY = rect.top + rect.height / 2;

                    for (let i = 0; i < 5; i++) {
                        createConfetti(centerX, centerY);
                    }
                }, 200);
            });

            confettiTarget.addEventListener("mouseleave", () => {
                clearInterval(confettiInterval);
            });

            // Mobile: touch
            confettiTarget.addEventListener("touchstart", () => {
                const rect = confettiTarget.getBoundingClientRect();
                const centerX = rect.left + rect.width / 2;
                const centerY = rect.top + rect.height / 2;

                for (let i = 0; i < 20; i++) {
                    createConfetti(centerX, centerY);
                }
            });
        }
    }

    /**
     * Initialize tab navigation
     */
    function initTabNavigation() {
        var $nav = $('.tam-rank-nav');
        if (!$nav.length) return;

        var $pills = $nav.find('.tr-pill');
        var $panels = $('.tr-tab-panel');

        $pills.on('click', function (e) {
            e.preventDefault();

            var target = $(this).attr('href');

            $pills.removeClass('is-active');
            $(this).addClass('is-active');

            $panels.removeClass('is-active');
            $(target).addClass('is-active');

            if (history.pushState) {
                history.pushState(null, null, target);
            }
        });

        // Show the panel the URL fragment points at. Runs on page load AND on
        // every hash change, so the visible panel can never drift away from the
        // URL — code that restores a tab after a save reload (settings-page.php)
        // only has to set the hash.
        function activateTabFromHash() {
            if (!window.location.hash) return;

            var hash = window.location.hash;
            var $tab = $pills.filter('[href="' + hash + '"]');
            if (!$tab.length) return;
            if ($tab.hasClass('is-active') && $(hash).hasClass('is-active')) return;

            $pills.removeClass('is-active');
            $panels.removeClass('is-active');
            $tab.addClass('is-active');
            $(hash).addClass('is-active');
            window.scrollTo(0, 0);
        }

        activateTabFromHash();
        $(window).on('hashchange', activateTabFromHash);

        // Exposed so a restore that sets the hash to its current value — which
        // fires no hashchange event — can still force the panel to follow.
        window.TamRank = window.TamRank || {};
        window.TamRank.activateTabFromHash = activateTabFromHash;
    }

    // PageSpeed functions removed — now in tamrank-pagespeed.js


    /**
     * Initialize form validation
     */
    function initFormValidation() {
        // Character counters are handled by meta-box.js — no duplicate logic here
    }

    /**
     * Initialize auto-save functionality
     */
    function initAutoSave() {
        let saveTimeout;

        $('.tam-rank-form input, .tam-rank-form textarea').on('input', function () {
            clearTimeout(saveTimeout);
            saveTimeout = setTimeout(function () {
                // Show saving indicator
                showSavingIndicator();
            }, 2000);
        });
    }

    /**
     * Show saving indicator
     */
    function showSavingIndicator() {
        const indicator = $('<div class="saving-indicator">' + t('saving', 'Saving...') + '</div>');
        $('body').append(indicator);

        setTimeout(function () {
            indicator.fadeOut(function () {
                indicator.remove();
            });
        }, 2000);
    }

    /**
     * Utility functions
     */
    function isValidUrl(string) {
        try {
            new URL(string);
            return true;
        } catch (_) {
            return false;
        }
    }

    // TamRank score class - Drempels: 80+ Uitstekend, 60-79 Goed, 40-59 Aandacht nodig, 0-39 Verbeteren
    function getScoreClass(score) {
        if (score >= 80) return 'tam-score-excellent';
        if (score >= 60) return 'tam-score-good';
        if (score >= 40) return 'tam-score-average';
        return 'tam-score-poor';
    }

    // Initialize tooltips
    $('[data-tooltip]').hover(
        function () {
            const tooltip = $('<div class="tam-tooltip">' + $(this).data('tooltip') + '</div>');
            $('body').append(tooltip);

            const offset = $(this).offset();
            tooltip.css({
                top: offset.top - tooltip.outerHeight() - 5,
                left: offset.left + ($(this).outerWidth() / 2) - (tooltip.outerWidth() / 2)
            });
        },
        function () {
            $('.tam-tooltip').remove();
        }
    );

    // Handle AJAX errors globally
    $(document).ajaxError(function (event, xhr, settings) {
        if (xhr.status === 403) {
            TamRank.notify(t('session_expired_message', 'Session expired. Refresh the page and try again.'), 'warning');
        }
    });

});

/**
 * Initialize save-confirmation toast notifications.
 */
function tamrankInitSaveToasts() {
    const $ = jQuery;

    const t = (key, fallback) => {
        if (window.tamRank && tamRank.i18n && tamRank.i18n[key]) {
            return tamRank.i18n[key];
        }
        return fallback;
    };

    // Post save handler (Gutenberg)
    if (typeof wp !== 'undefined' && wp.data && wp.data.subscribe && wp.data.select('core/editor')) {
        var wasSaving = false;

        wp.data.subscribe(function () {
            var editor = wp.data.select('core/editor');
            if (!editor) return;
            var isSaving = editor.isSavingPost();
            var isAutosave = editor.isAutosavingPost();

            if (wasSaving && !isSaving && !isAutosave) {
                // Determine if publish or update
                var isPublished = editor.isCurrentPostPublished();
                var title = isPublished ? t('optimizations_saved', 'Optimizations saved') : t('draft_saved', 'Draft saved');

                // Post has been saved
                if (window.TamRankToast) {
                    TamRankToast.success(title, t('changes_processed', 'Your changes have been processed'));
                }

                // Flag for auto-indexing toast (shown after redirect, skip noindex pages)
                var isNoindex = document.getElementById('_tam_rank_noindex') && document.getElementById('_tam_rank_noindex').checked;
                if (isPublished && window.tamRank && tamRank.autoIndexing && !isNoindex) {
                    sessionStorage.setItem('tamrank_auto_indexed', '1');
                }
            }

            wasSaving = isSaving && !isAutosave;
        });
    }

    // Classic Editor save handler
    $(document).on('submit', '#post', function () {
        // Toast is shown after the page reload, so store the flag in sessionStorage
        sessionStorage.setItem('tamrank_show_save_toast', '1');
    });

    // Check for pending toast on page load
    if (sessionStorage.getItem('tamrank_show_save_toast')) {
        sessionStorage.removeItem('tamrank_show_save_toast');
        setTimeout(function () {
            if (window.TamRankToast) {
                TamRankToast.success(t('optimizations_saved', 'Optimizations saved'), t('changes_processed', 'Your changes have been processed'));
            }
        }, 500);
    }
}

// ─── TamRank 404 Monitor ──────────────────────────────────────
function tamrankInit404Monitor($) {
    if (!document.getElementById('tr-404-select-all') && !document.querySelector('.tr-404-table') && !document.getElementById('tr-404-export')) return;

    var nonce = (window.tamRank && tamRank.nonce) ? tamRank.nonce : '';
    var ajaxUrl = (window.tamRank && tamRank.ajaxUrl) ? tamRank.ajaxUrl : ajaxurl;

    var t = function (key, fallback) {
        if (window.tamRank && tamRank.i18n && tamRank.i18n[key]) {
            return tamRank.i18n[key];
        }
        return fallback;
    };

    // --- Bulk Actions ---
    (function initBulkActions() {
        var selectAll = document.getElementById('tr-404-select-all');
        var bulkBar = document.querySelector('.tr-404-bulk-bar');
        var countEl = document.querySelector('.tr-404-bulk-count');
        if (!selectAll || !bulkBar) return;

        function updateBulkBar() {
            var checked = document.querySelectorAll('.tr-404-row-check:checked');
            var total = document.querySelectorAll('.tr-404-row-check');
            if (checked.length > 0) {
                bulkBar.classList.add('is-visible');
                if (countEl) countEl.textContent = checked.length;
            } else {
                bulkBar.classList.remove('is-visible');
            }
            selectAll.checked = total.length > 0 && checked.length === total.length;
            selectAll.indeterminate = checked.length > 0 && checked.length < total.length;
        }

        selectAll.addEventListener('click', function () {
            var all = document.querySelectorAll('.tr-404-row-check');
            var isChecked = selectAll.checked;
            all.forEach(function (cb) {
                cb.checked = isChecked;
                cb.closest('tr').classList.toggle('selected', isChecked);
            });
            updateBulkBar();
        });

        // Use event delegation for row checkboxes (works with dynamic content)
        var table = document.querySelector('.tr-404-table');
        if (table) {
            table.addEventListener('click', function (e) {
                var cb = e.target.closest('.tr-404-row-check');
                if (!cb) return;
                cb.closest('tr').classList.toggle('selected', cb.checked);
                updateBulkBar();
            });
        }

        // Bulk redirect opens panel with all selected URLs
        var bulkRedirectBtn = document.getElementById('tr-404-bulk-redirect');
        if (bulkRedirectBtn) {
            bulkRedirectBtn.addEventListener('click', function () {
                var checked = document.querySelectorAll('.tr-404-row-check:checked');
                if (checked.length === 0) return;
                var urls = [];
                checked.forEach(function (cb) {
                    urls.push(cb.closest('tr').dataset.url);
                });
                if (urls.length === 1) {
                    openRedirectPanel(urls[0]);
                } else {
                    openBulkRedirectPanel(urls);
                }
            });
        }

        // Close bulk bar & deselect all
        function closeBulkBar() {
            document.querySelectorAll('.tr-404-row-check, #tr-404-select-all').forEach(function (cb) {
                cb.checked = false;
            });
            document.querySelectorAll('tr.selected').forEach(function (r) {
                r.classList.remove('selected');
            });
            bulkBar.classList.remove('is-visible');
        }

        var bulkCloseBtn = document.getElementById('tr-404-bulk-close');
        if (bulkCloseBtn) {
            bulkCloseBtn.addEventListener('click', closeBulkBar);
        }

        // Bulk ignore: voegt URLs toe aan blocklist en verwijdert ze uit de log.
        // Genegeerde URLs worden ook nooit meer opnieuw gelogd bij volgende hits.
        var bulkIgnoreBtn = document.getElementById('tr-404-bulk-ignore');
        if (bulkIgnoreBtn) {
            bulkIgnoreBtn.addEventListener('click', function () {
                var checked = document.querySelectorAll('.tr-404-row-check:checked');
                if (checked.length === 0) return;

                var urls = [];
                checked.forEach(function (cb) {
                    var u = cb.closest('tr').dataset.url;
                    if (u) urls.push(u);
                });
                if (urls.length === 0) return;

                TamRank.confirm({
                    title: t('ignore_urls_title', 'Ignore URL(s)?'),
                    message: t('confirm_ignore_404', 'These URL(s) will be removed from the log and not registered in the future.'),
                    confirmLabel: t('ignore', 'Ignore'),
                    cancelLabel: t('cancel', 'Cancel'),
                    variant: 'default'
                }).then(function (ok) {
                    if (!ok) return;
                    doIgnore();
                });

                function doIgnore() {
                var originalHTML = bulkIgnoreBtn.innerHTML;
                bulkIgnoreBtn.disabled = true;
                bulkIgnoreBtn.innerHTML = '<span class="tam-loading"></span> ' + t('ignoring', 'Working...');

                $.ajax({
                    url: ajaxUrl,
                    type: 'POST',
                    data: {
                        action: 'tam_rank_ignore_404_urls',
                        nonce: nonce,
                        urls: urls
                    },
                    success: function (response) {
                        if (response.success) {
                            if (typeof TamRankToast !== 'undefined') {
                                TamRankToast.success(
                                    t('urls_ignored', 'URL(s) ignored'),
                                    String(response.data && response.data.ignored ? response.data.ignored : urls.length) + ' ' + t('urls_added_to_blocklist', 'URL(s) added to blocklist')
                                );
                            }
                            setTimeout(function () { location.reload(); }, 900);
                        } else {
                            if (typeof TamRankToast !== 'undefined') {
                                TamRankToast.show(t('error_occurred', 'An error occurred'), (response.data && response.data.message) || '', 'error');
                            }
                            bulkIgnoreBtn.disabled = false;
                            bulkIgnoreBtn.innerHTML = originalHTML;
                        }
                    },
                    error: function () {
                        if (typeof TamRankToast !== 'undefined') {
                            TamRankToast.show(t('error_occurred', 'An error occurred'), '', 'error');
                        }
                        bulkIgnoreBtn.disabled = false;
                        bulkIgnoreBtn.innerHTML = originalHTML;
                    }
                });
                }
            });
        }
    })();

    // --- Clear 404 Log ---
    (function initClear404Log() {
        var btn = document.getElementById('tr-404-clear-log');
        if (!btn) return;

        btn.addEventListener('click', function () {
            TamRank.confirm({
                title: t('clear_log_title', 'Clear 404 log?'),
                message: t('confirm_clear_log', 'All 404 errors will be permanently deleted. This action cannot be undone.'),
                confirmLabel: t('clear_log', 'Clear Log'),
                cancelLabel: t('cancel', 'Cancel'),
                variant: 'danger'
            }).then(function (ok) {
                if (!ok) return;
                doClear();
            });

            function doClear() {
            var originalHTML = btn.innerHTML;
            btn.disabled = true;
            btn.innerHTML = '<span class="tam-loading"></span> ' + t('clearing', 'Clearing...');

            $.ajax({
                url: ajaxUrl,
                type: 'POST',
                data: {
                    action: 'tam_rank_clear_404_log',
                    nonce: nonce
                },
                success: function (response) {
                    if (response.success) {
                        if (typeof TamRankToast !== 'undefined') {
                            TamRankToast.success(
                                t('clear_log', 'Clear Log'),
                                t('log_cleared', '404 log has been cleared')
                            );
                        }
                        setTimeout(function () { location.reload(); }, 1200);
                    } else {
                        if (typeof TamRankToast !== 'undefined') {
                            TamRankToast.show(t('error_occurred', 'An error occurred'), response.data || '', 'error');
                        } else {
                            TamRank.notify(response.data || t('error_generic_message', 'An error occurred.'), 'error');
                        }
                    }
                },
                error: function () {
                    if (typeof TamRankToast !== 'undefined') {
                        TamRankToast.show(t('error_occurred', 'An error occurred'), '', 'error');
                    } else {
                        TamRank.notify(t('error_generic_message', 'An error occurred.'), 'error');
                    }
                },
                complete: function () {
                    btn.disabled = false;
                    btn.innerHTML = originalHTML;
                }
            });
            }
        });
    })();

    // Export 404: direct link (<a> tag), no JS needed

    // --- Redirect Panel ---
    var overlay = document.querySelector('.tr-404-panel-overlay');
    var panel = document.querySelector('.tr-404-panel');

    function resetRadioType() {
        var radios = panel.querySelectorAll('input[name="tr-404-redirect-type"]');
        radios.forEach(function (r) { r.checked = r.value === '301'; });
        syncTargetRequirement();
    }

    function getSelectedType() {
        var checked = panel.querySelector('input[name="tr-404-redirect-type"]:checked');
        return checked ? checked.value : '301';
    }

    // A status outside 3xx has no destination: the server sends the status and
    // never reads the target. This is the same rule the add form on the
    // Redirects screen applies and the same one the server enforces through
    // TamRank_Redirect_Manager::status_needs_target() - asked as code, not
    // matched against a list, so a status added through the
    // tamrank_redirect_types filter behaves identically in all three places.
    function statusNeedsTarget(type) {
        var code = parseInt(type, 10);
        return code >= 300 && code <= 399;
    }

    // Keep the To field's note in step with the picked status. Resolving a 404
    // as 410 or 451 is a legitimate answer - the page really is gone - so the
    // panel must not keep asking for a URL that would be thrown away.
    function syncTargetRequirement() {
        if (!panel) return;
        var needs = statusNeedsTarget(getSelectedType());
        var note = document.getElementById('tr-404-panel-notarget-note');
        if (note) note.hidden = needs;
    }

    function openRedirectPanel(sourceUrl) {
        if (!panel || !overlay) return;
        var sourceEl = document.getElementById('tr-404-panel-source');
        var metaEl = document.getElementById('tr-404-panel-source-meta');
        var targetInput = document.getElementById('tr-404-panel-target');

        if (sourceEl) sourceEl.textContent = sourceUrl || '';
        if (targetInput) targetInput.value = '';
        resetRadioType();

        // Show metadata from the table row
        if (metaEl) {
            var row = document.querySelector('tr[data-url="' + sourceUrl + '"]');
            if (row) {
                var hits = row.querySelector('.tr-404-hits') ? row.querySelector('.tr-404-hits').textContent.trim() : '';
                metaEl.textContent = hits ? t('hit_count', 'Hits: ') + hits + '×' : '';
            } else {
                metaEl.textContent = '';
            }
        }

        overlay.classList.add('is-open');
        panel.classList.add('is-open');
        document.body.style.overflow = 'hidden';
        if (targetInput) {
            setTimeout(function () { targetInput.focus(); }, 350);
        }
    }

    function closePanel() {
        if (!panel || !overlay) return;
        overlay.classList.remove('is-open');
        panel.classList.remove('is-open');
        document.body.style.overflow = '';
    }

    // Track bulk mode state
    var bulkUrls = [];

    function openBulkRedirectPanel(urls) {
        if (!panel || !overlay) return;
        bulkUrls = urls;

        // Hide single source field, show bulk list
        var sourceField = document.getElementById('tr-404-panel-source-field');
        var bulkInfo = document.getElementById('tr-404-panel-bulk-info');
        var bulkList = document.getElementById('tr-404-panel-bulk-list');
        var targetInput = document.getElementById('tr-404-panel-target');
        var panelTitle = panel.querySelector('.tr-404-panel-title');

        if (sourceField) sourceField.style.display = 'none';
        if (bulkInfo) {
            bulkInfo.style.display = '';
            if (bulkList) {
                bulkList.innerHTML = '';
                urls.forEach(function (url) {
                    var item = document.createElement('div');
                    item.className = 'tr-404-panel-bulk-item';
                    item.textContent = url;
                    bulkList.appendChild(item);
                });
            }
        }
        if (panelTitle) panelTitle.textContent = urls.length + t('redirects_create_title', ' redirects to create');
        if (targetInput) targetInput.value = '';
        resetRadioType();

        overlay.classList.add('is-open');
        panel.classList.add('is-open');
        document.body.style.overflow = 'hidden';
        if (targetInput) {
            setTimeout(function () { targetInput.focus(); }, 350);
        }
    }

    function resetPanelMode() {
        bulkUrls = [];
        var sourceField = document.getElementById('tr-404-panel-source-field');
        var bulkInfo = document.getElementById('tr-404-panel-bulk-info');
        var panelTitle = panel ? panel.querySelector('.tr-404-panel-title') : null;
        if (sourceField) sourceField.style.display = '';
        if (bulkInfo) bulkInfo.style.display = 'none';
        if (panelTitle) panelTitle.textContent = t('create_redirect', 'Create redirect');
    }

    var origClosePanel = closePanel;
    closePanel = function () {
        resetPanelMode();
        origClosePanel();
    };

    if (panel) {
        var closeBtn = panel.querySelector('.tr-404-panel-close');
        var cancelBtn = document.getElementById('tr-404-panel-cancel');
        var submitBtn = document.getElementById('tr-404-panel-save');

        if (closeBtn) closeBtn.addEventListener('click', closePanel);
        if (cancelBtn) cancelBtn.addEventListener('click', closePanel);
        if (overlay) overlay.addEventListener('click', closePanel);

        panel.querySelectorAll('input[name="tr-404-redirect-type"]').forEach(function (r) {
            r.addEventListener('change', syncTargetRequirement);
        });

        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape' && panel.classList.contains('is-open')) {
                closePanel();
            }
        });

        // Helper: create a single redirect via AJAX (returns a Promise-like $.ajax)
        function createSingleRedirect(source, target, type) {
            return $.ajax({
                url: ajaxUrl,
                type: 'POST',
                data: {
                    action: 'tam_rank_create_redirect',
                    nonce: nonce,
                    source: source,
                    target: target,
                    type: type
                }
            });
        }

        // Mark a table row as redirected
        function markRowDone(source) {
            var row = document.querySelector('tr[data-url="' + source + '"]');
            if (row) {
                var rowBtn = row.querySelector('.tr-404-redirect-btn');
                if (rowBtn) {
                    rowBtn.textContent = 'OK';
                    rowBtn.disabled = true;
                    rowBtn.classList.add('is-done');
                }
            }
        }

        // Submit redirect (single or bulk)
        if (submitBtn) {
            submitBtn.addEventListener('click', function () {
                var target = (document.getElementById('tr-404-panel-target') || {}).value || '';
                var type = getSelectedType();
                target = target.trim();

                // Only a real redirection has to have somewhere to go.
                if (!target && statusNeedsTarget(type)) {
                    var targetInput = document.getElementById('tr-404-panel-target');
                    if (targetInput) targetInput.focus();
                    return;
                }

                var originalHTML = submitBtn.innerHTML;
                submitBtn.disabled = true;

                // Bulk mode: multiple URLs
                if (bulkUrls.length > 1) {
                    var total = bulkUrls.length;
                    var done = 0;
                    var failed = 0;
                    submitBtn.innerHTML = '<span class="tam-loading"></span> 0/' + total;

                    // Process URLs sequentially
                    function processNext(index) {
                        if (index >= total) {
                            // All done
                            closePanel();
                            if (typeof TamRankToast !== 'undefined') {
                                var msg = done + t('redirects_created', ' redirects created');
                                if (failed > 0) msg += ', ' + failed + t('failed_suffix', ' failed');
                                TamRankToast.success(t('redirect_created', 'Redirect created'), msg);
                            }
                            submitBtn.disabled = false;
                            submitBtn.innerHTML = originalHTML;
                            // Deselect all checkboxes
                            document.querySelectorAll('.tr-404-row-check, #tr-404-select-all').forEach(function (cb) { cb.checked = false; });
                            document.querySelectorAll('tr.selected').forEach(function (r) { r.classList.remove('selected'); });
                            var bulkBar = document.querySelector('.tr-404-bulk-bar');
                            if (bulkBar) bulkBar.classList.remove('is-visible');
                            return;
                        }

                        var source = bulkUrls[index];
                        createSingleRedirect(source, target, type)
                            .done(function (response) {
                                if (response.success) {
                                    done++;
                                    markRowDone(source);
                                } else {
                                    failed++;
                                }
                            })
                            .fail(function () { failed++; })
                            .always(function () {
                                submitBtn.innerHTML = '<span class="tam-loading"></span> ' + (done + failed) + '/' + total;
                                processNext(index + 1);
                            });
                    }

                    processNext(0);

                // Single mode
                } else {
                    var source = bulkUrls.length === 1 ? bulkUrls[0] : ((document.getElementById('tr-404-panel-source') || {}).textContent || '').trim();
                    if (!source) return;

                    submitBtn.innerHTML = '<span class="tam-loading"></span> ' + t('creating', 'Creating...');

                    createSingleRedirect(source, target, type)
                        .done(function (response) {
                            if (response.success) {
                                closePanel();
                                markRowDone(source);
                                if (typeof TamRankToast !== 'undefined') {
                                    TamRankToast.success(
                                        t('redirect_created', 'Redirect created'),
                                        source + ' → ' + target
                                    );
                                }
                            } else {
                                if (typeof TamRankToast !== 'undefined') {
                                    TamRankToast.show(
                                        t('redirect_error', 'Error creating redirect'),
                                        response.data || '',
                                        'error'
                                    );
                                }
                            }
                        })
                        .fail(function () {
                            if (typeof TamRankToast !== 'undefined') {
                                TamRankToast.show(t('error_occurred', 'An error occurred'), '', 'error');
                            }
                        })
                        .always(function () {
                            submitBtn.disabled = false;
                            submitBtn.innerHTML = originalHTML;
                        });
                }
            });
        }
    }

    // Delegate click for redirect buttons in the table
    $(document).on('click', '.tr-404-redirect-btn:not(:disabled)', function () {
        var url = $(this).closest('tr').data('url');
        openRedirectPanel(url);
    });

    // --- Client-side URL Search ---
    (function initUrlSearch() {
        var searchInput = document.getElementById('tr-404-search');
        if (!searchInput) return;

        var debounceTimer;
        searchInput.addEventListener('input', function () {
            clearTimeout(debounceTimer);
            var input = this;
            debounceTimer = setTimeout(function () {
                var query = input.value.toLowerCase().trim();
                var rows = document.querySelectorAll('.tr-404-table tbody tr');
                rows.forEach(function (row) {
                    var url = (row.dataset.url || '').toLowerCase();
                    row.style.display = url.indexOf(query) !== -1 ? '' : 'none';
                });
            }, 250);
        });
    })();
}

// ─── TamRank Settings Design System JS ────────────────────────
(function() {
    'use strict';

    var t = function(key, fallback) {
        if (window.tamRank && tamRank.i18n && tamRank.i18n[key]) {
            return tamRank.i18n[key];
        }
        return fallback;
    };

    // Slider live update
    document.querySelectorAll('.tr-slider').forEach(function(slider) {
        var valueEl = slider.closest('.tr-field-row') ? slider.closest('.tr-field-row').querySelector('.tr-slider-value') : null;
        if (valueEl) {
            slider.addEventListener('input', function() { valueEl.textContent = slider.value; });
        }
    });

    // Advanced settings toggle
    document.querySelectorAll('.tr-advanced-toggle').forEach(function(btn) {
        btn.addEventListener('click', function() {
            btn.classList.toggle('is-open');
            var content = btn.nextElementSibling;
            if (content) content.classList.toggle('is-open');
        });
    });

    // Advanced settings collapsible in the XML Sitemap card (hidden attribute)
    document.querySelectorAll('.tr-more-types-toggle').forEach(function(btn) {
        var content = btn.parentElement ? btn.parentElement.querySelector('.tr-more-types-content') : null;
        if (!content) return;
        btn.setAttribute('aria-expanded', content.hidden ? 'false' : 'true');
        btn.addEventListener('click', function() {
            content.hidden = !content.hidden;
            btn.setAttribute('aria-expanded', content.hidden ? 'false' : 'true');
        });
    });

    // Save feedback animation
    document.querySelectorAll('.tr-save-bar [type="submit"]').forEach(function(btn) {
        btn.addEventListener('click', function() {
            var feedback = btn.closest('.tr-save-bar') ? btn.closest('.tr-save-bar').querySelector('.tr-save-feedback') : null;
            if (feedback) {
                feedback.classList.add('is-visible');
                setTimeout(function() { feedback.classList.remove('is-visible'); }, 2500);
            }
        });
    });

    // Licentie deactiveren bevestiging
    var deactivateBtn = document.getElementById('tr-deactivate-license');
    if (deactivateBtn) {
        deactivateBtn.addEventListener('click', function(e) {
            if (deactivateBtn.dataset.trConfirmed === '1') {
                delete deactivateBtn.dataset.trConfirmed;
                return;
            }
            e.preventDefault();
            TamRank.confirm({
                title: t('deactivate_license_title', 'Deactivate license?'),
                message: t('confirm_deactivate_license', 'You will lose access to PRO features until you reactivate the license.'),
                confirmLabel: t('deactivate', 'Deactivate'),
                cancelLabel: t('cancel', 'Cancel'),
                variant: 'danger'
            }).then(function (ok) {
                if (!ok) return;
                deactivateBtn.dataset.trConfirmed = '1';
                deactivateBtn.click();
            });
        });
    }

    // ─── TamRank Indexering ────────────────────────────────────
    (function initIndexing() {
        var $ = jQuery;
        var nonce = (window.tamRank && tamRank.nonce) ? tamRank.nonce : '';
        var ajaxUrl = (window.tamRank && tamRank.ajaxUrl) ? tamRank.ajaxUrl : (typeof ajaxurl !== 'undefined' ? ajaxurl : '');

        // The edit-screen button carries its label in a span next to an icon;
        // the list-table row action is a bare <a>. Write to whichever exists so
        // one handler can drive both without eating the icon.
        function setIndexLabel(link, text) {
            var label = link.find('.tamrank-index-link__label');
            if (label.length) {
                label.text(text);
            } else {
                link.text(text);
            }
        }

        // Server-sent messages arrive as {message, code}; older paths sent a
        // bare string. Read both so a cooldown or permission message reaches
        // the toast instead of "[object Object]".
        function indexErrorMessage(payload, fallback) {
            if (!payload) return fallback;
            if (typeof payload === 'string') return payload;
            return payload.message || fallback;
        }

        // Click handler: "Request indexing" — posts list row action, post edit
        // screen and term edit screen all land here.
        $(document).on('click', '.tamrank-index-link', function(e) {
            e.preventDefault();
            var link = $(this);
            if (link.is(':disabled') || link.hasClass('tamrank-index--busy')) return;

            var isTerm = link.data('object-type') === 'term';
            var targetId = isTerm ? link.data('term-id') : link.data('post-id');
            if (!targetId) return;

            var payload = { action: 'tam_rank_request_indexing', nonce: nonce };
            if (isTerm) {
                payload.object_type = 'term';
                payload.term_id = targetId;
            } else {
                payload.post_id = targetId;
            }

            link.addClass('tamrank-index--busy');
            setIndexLabel(link, t('busy', 'Processing...'));

            $.ajax({
                url: ajaxUrl,
                type: 'POST',
                data: payload,
                success: function(response) {
                    if (response.success) {
                        if (window.TamRankToast) {
                            TamRankToast.success(t('indexing_requested', 'Indexing requested'), response.data.message || '');
                        }
                        setIndexLabel(link, t('requested_checkmark', 'Requested \u2713'));
                        setTimeout(function() {
                            link.removeClass('tamrank-index--busy');
                            setIndexLabel(link, t('request_indexing', 'Request indexing'));
                        }, 3000);

                        // Update column cell
                        if (response.data.status_html) {
                            var row = link.closest('tr');
                            var cell = row.find('.column-tamrank_index');
                            if (cell.length) {
                                cell.html(response.data.status_html);
                            }
                        }
                    } else {
                        var msg = indexErrorMessage(response.data, t('unknown_error', 'Unknown error'));
                        if (window.TamRankToast) {
                            TamRankToast.show(t('indexing_failed', 'Indexing failed'), msg, 'error');
                        }
                        link.removeClass('tamrank-index--busy');
                        setIndexLabel(link, t('request_indexing', 'Request indexing'));
                    }
                },
                error: function(xhr) {
                    // wp_send_json_error() with a status code lands here, not in
                    // success — the cooldown (429) and mismatch (409) messages
                    // live in the response body, so read them before falling back.
                    var body = xhr.responseJSON ? xhr.responseJSON.data : null;
                    var msg = indexErrorMessage(
                        body,
                        xhr.status === 403 ? t('reconnect_required', 'Reconnection required') : t('error_generic_message', 'An error occurred')
                    );
                    if (window.TamRankToast) {
                        TamRankToast.show(t('indexing_failed', 'Indexing failed'), msg, 'error');
                    }
                    link.removeClass('tamrank-index--busy');
                    setIndexLabel(link, t('request_indexing', 'Request indexing'));
                }
            });
        });

        // Auto-index toast after publish redirect
        if (sessionStorage.getItem('tamrank_auto_indexed')) {
            sessionStorage.removeItem('tamrank_auto_indexed');
            setTimeout(function() {
                if (window.TamRankToast) {
                    TamRankToast.success(t('auto_indexing_title', 'Indexing automatically requested'), t('auto_indexing_message', 'Google has been notified of your update'));
                }
            }, 800);
        }
    })();

    // Robots.txt toggle show/hide
    var robotsToggle = document.getElementById('tamrank_robots_enabled');
    var robotsContent = document.getElementById('tr-robots-content');
    if (robotsToggle && robotsContent) {
        robotsToggle.addEventListener('change', function() {
            robotsContent.style.display = robotsToggle.checked ? 'block' : 'none';
        });
        // Init state
        robotsContent.style.display = robotsToggle.checked ? 'block' : 'none';
    }
})();

// Dismiss .tr-alert close buttons via a delegated handler
// (replaces inline onclick="" for WordPress.org compliance).
jQuery(function ($) {
    $(document).on('click', '.tr-alert__close', function () {
        var alertEl = this.closest('.tr-alert');
        if (alertEl && alertEl.parentNode) {
            alertEl.parentNode.removeChild(alertEl);
        }
    });
});

