jQuery(document).ready(function($) {
    // Define ajaxurl for frontend if missing.
    var ajaxurl = window.ajaxurl || (typeof wpsh_admin_vars !== 'undefined' ? wpsh_admin_vars.ajax_url : '');
    function log(msg, type = 'success') {
        var $window = $('.wpsh-log-window');
        if (!$window.length) return; // Silent return if log window doesn't exist (e.g. frontend)
        
        var icon = '✓';
        if (type === 'error') icon = '✗';
        if (type === 'warning') icon = '⚠';
        var cls = type === 'success' ? '' : type;
        var $line = $('<div class="wpsh-log-item ' + cls + '"><span class="icon">' + icon + '</span> <span>' + msg + '</span></div>');
        $window.append($line);
        $window.scrollTop($window[0].scrollHeight);
    }

    var nonceRefreshRequest = null;
    function isNonceExpiredResponse(response, jqXHR) {
        if (response === '-1' || response === -1) return true;

        if (response && response.success === false && typeof response.data === 'string') {
            var msg = response.data.toLowerCase();
            if (msg.indexOf('nonce') !== -1 || msg.indexOf('expired') !== -1) {
                return true;
            }
        }

        var body = jqXHR && typeof jqXHR.responseText === 'string' ? jqXHR.responseText.trim() : '';
        if (body === '-1') return true;

        return false;
    }

    function notifySessionExpired() {
        if (typeof toastr !== 'undefined') {
            toastr.error('Your admin session expired. Please refresh the page and try again.');
        }
    }

    function refreshNonces(onSuccess, onFail) {
        if (nonceRefreshRequest) {
            nonceRefreshRequest.done(onSuccess).fail(onFail);
            return;
        }

        nonceRefreshRequest = $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: { action: 'wpsh_refresh_nonces' }
        });

        nonceRefreshRequest.done(function(res) {
            if (res && res.success && res.data && res.data.nonces) {
                wpsh_admin_vars.nonces = res.data.nonces;
                if (typeof onSuccess === 'function') onSuccess();
            } else if (typeof onFail === 'function') {
                onFail(res);
            }
        }).fail(function(err) {
            if (typeof onFail === 'function') onFail(err);
        }).always(function() {
            nonceRefreshRequest = null;
        });
    }

    function ajaxWithNonceRecovery(options, retried) {
        var requestOptions = $.extend(true, {}, options);
        var originalSuccess = requestOptions.success;
        var originalError = requestOptions.error;

        requestOptions.success = function(response, textStatus, jqXHR) {
            if (isNonceExpiredResponse(response, jqXHR)) {
                if (retried) {
                    notifySessionExpired();
                    if (typeof originalError === 'function') originalError(jqXHR, 'error', 'nonce_expired');
                    return;
                }

                refreshNonces(function() {
                    ajaxWithNonceRecovery(options, true);
                }, function() {
                    notifySessionExpired();
                    if (typeof originalError === 'function') originalError(jqXHR, 'error', 'nonce_refresh_failed');
                });
                return;
            }

            if (typeof originalSuccess === 'function') {
                originalSuccess(response, textStatus, jqXHR);
            }
        };

        requestOptions.error = function(jqXHR, textStatus, errorThrown) {
            if (isNonceExpiredResponse(null, jqXHR)) {
                if (retried) {
                    notifySessionExpired();
                    if (typeof originalError === 'function') originalError(jqXHR, textStatus, errorThrown);
                    return;
                }

                refreshNonces(function() {
                    ajaxWithNonceRecovery(options, true);
                }, function() {
                    notifySessionExpired();
                    if (typeof originalError === 'function') originalError(jqXHR, textStatus, errorThrown);
                });
                return;
            }

            if (typeof originalError === 'function') {
                originalError(jqXHR, textStatus, errorThrown);
            }
        };

        return $.ajax(requestOptions);
    }

    function postWithNonceRecovery(data, success, error) {
        return ajaxWithNonceRecovery({
            url: ajaxurl,
            type: 'POST',
            data: data,
            success: success,
            error: error
        });
    }

    var nonceAutoRefreshTimer = null;
    var nonceAutoRefreshListenersBound = false;

    function applyNonceAutoRefreshConfig(cfg) {
        if (nonceAutoRefreshTimer) {
            clearInterval(nonceAutoRefreshTimer);
            nonceAutoRefreshTimer = null;
        }

        var normalizedCfg = cfg || (typeof wpsh_admin_vars !== 'undefined' ? wpsh_admin_vars.nonce_auto_refresh : null);
        if (!normalizedCfg) {
            normalizedCfg = { enabled: true, interval_ms: 300000 };
        }

        var enabled = normalizedCfg.enabled !== false;
        if (!enabled) return;

        var intervalMs = Number(normalizedCfg.interval_ms || 300000);
        if (!Number.isFinite(intervalMs) || intervalMs < 60000) {
            intervalMs = 60000;
        }

        // Warm up nonces once on load or when settings are updated.
        refreshNonces();

        nonceAutoRefreshTimer = setInterval(function() {
            if (document.visibilityState === 'visible') {
                refreshNonces();
            }
        }, intervalMs);

        if (!nonceAutoRefreshListenersBound) {
            document.addEventListener('visibilitychange', function() {
                if (document.visibilityState === 'visible') {
                    refreshNonces();
                }
            });

            window.addEventListener('focus', function() {
                refreshNonces();
            });

            nonceAutoRefreshListenersBound = true;
        }
    }

    function initNonceAutoRefresh() {
        var cfg = (typeof wpsh_admin_vars !== 'undefined' && wpsh_admin_vars.nonce_auto_refresh)
            ? wpsh_admin_vars.nonce_auto_refresh
            : null;

        applyNonceAutoRefreshConfig(cfg);
    }

    function syncNonceAutoRefreshControlsState() {
        var $enabled = $('#wpsh-nonce-auto-refresh-enabled');
        var $interval = $('#wpsh-nonce-auto-refresh-interval');
        var $controls = $('#wpsh-nonce-auto-refresh-controls');

        if (!$enabled.length || !$interval.length) return;

        var isEnabled = $enabled.is(':checked');
        $interval.prop('disabled', !isEnabled);

        if ($controls.length) {
            $controls.css('opacity', isEnabled ? '1' : '0.7');
        }
    }

    initNonceAutoRefresh();
    syncNonceAutoRefreshControlsState();

    $(document).on('change', '#wpsh-nonce-auto-refresh-enabled', function() {
        syncNonceAutoRefreshControlsState();
    });

    // Tab Handling.
    $('.wpsh-nav-item').on('click', function(e) {
        e.preventDefault();
        $('.wpsh-nav-item').removeClass('active');
        $(this).addClass('active');
        var tab = $(this).data('tab');
        $('.wpsh-tab-content').removeClass('active');
        $('#tab-' + tab).addClass('active');
        $('.wpsh-header h1').text($(this).text().trim());
        if (tab === 'redirections') $('#wpsh-generate-btn-header').hide();
        else $('#wpsh-generate-btn-header').show();
    });

    // Generation Logic.
    var totalToProcess = 0, currentProcessed = 0, isGenerating = false, isPaused = false, isCancelled = false, currentPhase = 'posts', currentOffset = 0;

    function startGeneration() {
        if(isGenerating) return;
        isGenerating = true; isPaused = false; isCancelled = false;
        $('#wpsh-generate-btn, #wpsh-generate-btn-header').prop('disabled', true);
        $('#wpsh-progress').fadeIn();
        $('#wpsh-pause-btn').show(); $('#wpsh-resume-btn').hide(); $('#wpsh-cancel-btn').show();
        $('.wpsh-log-window').empty(); $('#wpsh-progress-bar').css('width', '0%'); $('#wpsh-percent').text('0%');
        currentProcessed = 0; totalToProcess = 0; currentPhase = 'posts'; currentOffset = 0;

        $('html, body').animate({ scrollTop: $("#wpsh-progress").offset().top - 100 }, 500);
        postWithNonceRecovery( { action: 'wpsh_clear_interrupt', nonce: wpsh_admin_vars.nonces.generate }, function() {
            processBatch('posts', 0);
        });
    }

    function processBatch(phase, offset) {
        if (isCancelled) return;
        if (isPaused) { currentPhase = phase; currentOffset = offset; return; }
        $('#wpsh-status-text').text('Phase: ' + phase.toUpperCase() + ' - Processing...');
        
        ajaxWithNonceRecovery({
            url: ajaxurl,
            type: 'POST',
            data: { action: 'wpsh_generate_all', phase: phase, offset: offset, nonce: wpsh_admin_vars.nonces.generate },
            success: function(response) {
                if (response.success) {
                    var data = response.data;
                    if (phase === 'posts' && offset === 0) { totalToProcess = data.total_estimate; log('Starting generation process...'); }
                    if (data.processed) {
                        $.each(data.processed, function(i, item) {
                            if (typeof item === 'string' && item.indexOf('FAILED') === 0) log(item, 'error');
                            else log(item);
                            currentProcessed++;
                        });
                    }
                    var percent = totalToProcess > 0 ? Math.round((currentProcessed / totalToProcess) * 100) : 0;
                    if(percent > 100) percent = 99;
                    $('#wpsh-progress-bar').css('width', percent + '%'); $('#wpsh-percent').text(percent + '%');

                    if (data.complete) {
                        log('Generation Completed Successfully!', 'success');
                        toastr.success('Static HTML generation complete!');
                        $('#wpsh-status-text').text('Completed');
                        $('#wpsh-progress-bar').css('width', '100%');
                        $('#wpsh-percent').text('100%');
                        $('.wpsh-btn').prop('disabled', false);
                        $('#wpsh-pause-btn, #wpsh-cancel-btn, #wpsh-resume-btn').hide();
                        isGenerating = false;
                        postWithNonceRecovery( { action: 'wpsh_mark_completed', nonce: wpsh_admin_vars.nonces.generate }, function(res) {
                            if (res.success && res.data.time) $('#wpsh-last-gen-time').text(res.data.time);
                        });
                    } else {
                        currentPhase = data.next_phase; currentOffset = data.next_offset;
                        if (!isPaused && !isCancelled) processBatch(data.next_phase, data.next_offset);
                    }
                } else {
                    if (!isPaused && !isCancelled) log('Error: ' + (response.data || 'Unknown error'), 'error');
                    $('.wpsh-btn').prop('disabled', false);
                    $('#wpsh-pause-btn, #wpsh-cancel-btn, #wpsh-resume-btn').hide();
                    isGenerating = false;
                }
            },
            error: function() {
                if (isCancelled || isPaused) return;
                log('Server connection error', 'error');
                $('.wpsh-btn').prop('disabled', false);
                $('#wpsh-pause-btn, #wpsh-cancel-btn, #wpsh-resume-btn').hide();
                isGenerating = false;
            }
        });
    }

    $('#wpsh-generate-btn, #wpsh-generate-btn-header').on('click', startGeneration);

    $('#wpsh-pause-btn').on('click', function() {
        isPaused = true; $(this).hide(); $('#wpsh-resume-btn').show();
        $('#wpsh-status-text').text('Paused'); log('Generation paused.', 'warning');
        postWithNonceRecovery( { action: 'wpsh_interrupt_generation', nonce: wpsh_admin_vars.nonces.generate });
    });

    $('#wpsh-resume-btn').on('click', function() {
        isPaused = false; $(this).hide(); $('#wpsh-pause-btn').show();
        $('#wpsh-status-text').text('Resuming...'); log('Generation resumed.');
        postWithNonceRecovery( { action: 'wpsh_clear_interrupt', nonce: wpsh_admin_vars.nonces.generate }, function() {
            processBatch(currentPhase, currentOffset);
        });
    });

    $('#wpsh-cancel-btn').on('click', function() {
        Swal.fire({
            title: 'Cancel Generation?',
            text: 'Stop the process and DELETE all currently generated static files?',
            icon: 'warning',
            showCancelButton: true,
            confirmButtonColor: '#ef4444',
            confirmButtonText: 'Yes, stop & clear'
        }).then((result) => {
            if (result.isConfirmed) {
                isCancelled = true;
                $('#wpsh-status-text').text('Cancelling...');
                log('Generation cancelled by user. Clearing cache...', 'warning');
                
                // Stop any further AJAX
                postWithNonceRecovery( { action: 'wpsh_interrupt_generation', nonce: wpsh_admin_vars.nonces.generate }, function() {
                    // Then clear cache
                    postWithNonceRecovery( { action: 'wpsh_clear_cache', nonce: wpsh_admin_vars.nonces.clear }, function(res) {
                        if(res.success) {
                            toastr.success('Cancelled and cache cleared!');
                            $('#wpsh-status-text').text('Cancelled');
                            $('.wpsh-btn').prop('disabled', false);
                            $('#wpsh-pause-btn, #wpsh-cancel-btn, #wpsh-resume-btn').hide();
                            isGenerating = false;
                        }
                    });
                });
            }
        });
    });

    // Clear Cache.
    $('#wpsh-clear-btn').on('click', function() {
        Swal.fire({
            title: 'Clear Cache?',
            text: 'This will delete ALL generated static HTML files.',
            icon: 'warning',
            showCancelButton: true,
            confirmButtonColor: '#ef4444',
            confirmButtonText: 'Yes, delete all'
        }).then((result) => {
            if (result.isConfirmed) {
                // If generating, stop it
                if (isGenerating) {
                    isCancelled = true;
                    postWithNonceRecovery( { action: 'wpsh_interrupt_generation', nonce: wpsh_admin_vars.nonces.generate });
                }

                postWithNonceRecovery( { action: 'wpsh_clear_cache', nonce: wpsh_admin_vars.nonces.clear }, function(res) {
                    if(res.success) {
                        toastr.success('Cache cleared!');
                        if (isGenerating) {
                            location.reload(); // Refresh to reset UI if we were generating
                        }
                    }
                    else toastr.error('Error: ' + res.data);
                });
            }
        });
    });

    $('#wpsh-htaccess-btn, #wpsh-sync-redir-btn').on('click', function() {
        postWithNonceRecovery( { action: 'wpsh_update_htaccess', nonce: wpsh_admin_vars.nonces.htaccess }, function(res) {
            if(res.success) {
                toastr.success('.htaccess updated!');
                setTimeout(() => location.reload(), 1000);
            } else {
                toastr.error('Error: ' + res.data);
            }
        });
    });

    // Exclusions Saving.
    $('#wpsh-save-settings-btn').on('click', function() {
        var excludedTypes = [];
        $('.wpsh-exclude-post-type:checked').each(function() { excludedTypes.push($(this).val()); });
        
        var excludedTaxonomies = [];
        $('.wpsh-exclude-tax:checked').each(function() { excludedTaxonomies.push($(this).val()); });

        // CPT Listing Page Mapping.
        // Value is stored as: post_type => page URL/path or page ID.
        var cptListingPostTypes = [];
        var cptListingPageValues = [];
        $('.wpsh-cpt-listing-url-input').each(function() {
            var postType = $(this).data('post-type');
            var val = ($(this).val() || '').toString().trim();
            if (!postType) return;
            if (val.length === 0) return;
            cptListingPostTypes.push(postType);
            cptListingPageValues.push(val);
        });

        var nonceCfgFallback = (wpsh_admin_vars && wpsh_admin_vars.nonce_auto_refresh) ? wpsh_admin_vars.nonce_auto_refresh : { enabled: true, interval_ms: 300000 };
        var $nonceEnabledInput = $('#wpsh-nonce-auto-refresh-enabled');
        var $nonceIntervalInput = $('#wpsh-nonce-auto-refresh-interval');
        var nonceAutoRefreshEnabled = $nonceEnabledInput.length
            ? ($nonceEnabledInput.is(':checked') ? '1' : '0')
            : (nonceCfgFallback.enabled === false ? '0' : '1');
        var nonceAutoRefreshIntervalMs = $nonceIntervalInput.length
            ? (parseInt($nonceIntervalInput.val(), 10) || 300000)
            : (parseInt(nonceCfgFallback.interval_ms, 10) || 300000);

        var $btn = $(this); $btn.prop('disabled', true).html('<span class="dashicons dashicons-saved"></span> Saving...');
        postWithNonceRecovery( { 
            action: 'wpsh_save_settings', 
            nonce: wpsh_admin_vars.nonces.settings, 
            excluded_post_types: excludedTypes,
            excluded_taxonomies: excludedTaxonomies,
            cpt_listing_page_post_types: cptListingPostTypes,
            cpt_listing_page_values: cptListingPageValues,
            nonce_auto_refresh_enabled: nonceAutoRefreshEnabled,
            nonce_auto_refresh_interval_ms: nonceAutoRefreshIntervalMs
        }, function(res) {
            $btn.prop('disabled', false).html('<span class="dashicons dashicons-saved"></span> Save All Settings');
            if (res.success) {
                toastr.success('Settings saved!');

                if (res.data && res.data.nonce_auto_refresh) {
                    wpsh_admin_vars.nonce_auto_refresh = res.data.nonce_auto_refresh;
                    applyNonceAutoRefreshConfig(res.data.nonce_auto_refresh);
                }

                // If a CPT is excluded, clear its mapping field in the UI immediately
                // (server also removes it from saved mapping). This prevents the
                // user from thinking the old value is still active.
                if (Array.isArray(excludedTypes) && excludedTypes.length) {
                    excludedTypes.forEach(function(postType) {
                        $('.wpsh-cpt-listing-url-input[data-post-type="' + postType + '"]').val('');
                    });
                }

                if (res.data && res.data.needs_regeneration) {
                    Swal.fire({
                        title: 'Post Types Un-excluded',
                        text: 'You have un-excluded some post types. Would you like to regenerate the static HTML for all eligible posts now?',
                        icon: 'question',
                        showCancelButton: true,
                        confirmButtonText: 'Yes, Regenerate All',
                        cancelButtonText: 'Not now'
                    }).then((result) => {
                        if (result.isConfirmed) {
                            $('.wpsh-nav-item[data-tab="dashboard"]').click();
                            startGeneration();
                        }
                    });
                }
            }
            else toastr.error('Error: ' + res.data);
        });
    });

    // --- Redirections Logic (Resilient Ordering) ---
    let selectedIndices = new Set();
    const $redirTable = $('#wpsh-redir-table');
    let tableObj;

    function syncSelectAllHeader() {
        const currentCheckboxes = $('.wpsh-select-item');
        const allChecked = currentCheckboxes.length > 0 && currentCheckboxes.length === currentCheckboxes.filter(':checked').length;
        $('#wpsh-select-all').prop('checked', allChecked);
    }

    function updateBulkDeleteVisibility() {
        if (selectedIndices.size > 0) $('#wpsh-bulk-delete-btn').fadeIn().text('Delete Selected (' + selectedIndices.size + ')');
        else $('#wpsh-bulk-delete-btn').fadeOut();
    }

    // Toggle Selection.
    $(document).on('change', '.wpsh-select-item', function() {
        const idx = $(this).val();
        if ($(this).is(':checked')) selectedIndices.add(idx); 
        else selectedIndices.delete(idx);
        syncSelectAllHeader();
        updateBulkDeleteVisibility();
    });

    $('#wpsh-select-all').on('change', function() {
        const checked = $(this).is(':checked');
        if (tableObj) {
            tableObj.rows({page: 'current', search: 'applied'}).nodes().to$().find('.wpsh-select-item').each(function() {
                const idx = $(this).val(); $(this).prop('checked', checked);
                if (checked) selectedIndices.add(idx); else selectedIndices.delete(idx);
            });
        } else {
            $('.wpsh-select-item').each(function() {
                const idx = $(this).val(); $(this).prop('checked', checked);
                if (checked) selectedIndices.add(idx); else selectedIndices.delete(idx);
            });
        }
        updateBulkDeleteVisibility();
    });

    // Add Redirection.
    $(document).on('click', '#wpsh-add-redir-btn', function() {
        const source = $('#wpsh-new-source').val();
        const target = $('#wpsh-new-target').val();
        const code = $('#wpsh-new-code').val();
        if(!source || !target) { 
            if (typeof toastr !== 'undefined') toastr.warning('Fill Source and Target.'); 
            else alert('Fill Source and Target.');
            return; 
        }
        postWithNonceRecovery( { action: 'wpsh_save_redirection', nonce: wpsh_admin_vars.nonces.redir, source: source, target: target, code: code }, function(res) {
            if(res.success) { 
                if (typeof toastr !== 'undefined') toastr.success('Added!');
                setTimeout(() => location.reload(), 1000); 
            }
            else {
                if (typeof toastr !== 'undefined') toastr.error('Error: ' + res.data);
                else alert('Error: ' + res.data);
            }
        });
    });

    // Bulk Delete.
    $('#wpsh-bulk-delete-btn').on('click', function() {
        if (selectedIndices.size === 0) return;
        Swal.fire({
            title: 'Delete Selected?',
            text: `Are you sure you want to delete ${selectedIndices.size} redirection rules?`,
            icon: 'warning',
            showCancelButton: true,
            confirmButtonColor: '#ef4444',
            confirmButtonText: 'Yes, delete selected'
        }).then((result) => {
            if (result.isConfirmed) {
                postWithNonceRecovery( { action: 'wpsh_bulk_delete_redirections', nonce: wpsh_admin_vars.nonces.redir, indices: Array.from(selectedIndices) }, function(res) {
                    if (res.success) { toastr.success('Selected rules deleted!'); setTimeout(() => location.reload(), 1000); }
                    else toastr.error('Bulk delete failed: ' + (res.data || 'Unknown error'));
                });
            }
        });
    });

    // Row Actions: Delete/Edit/Toggle.
    $(document).on('click', '.wpsh-delete-redir', function() {
        const idx = $(this).closest('tr').data('idx');
        if(confirm('Delete rule?')) {
            postWithNonceRecovery( { action: 'wpsh_delete_redirection', nonce: wpsh_admin_vars.nonces.redir, idx: idx }, function(res) {
                if(res.success) location.reload();
            });
        }
    });

    $(document).on('click', '.wpsh-edit-redir', function() {
        const row = $(this).closest('tr');
        $('#wpsh-edit-idx').val(row.data('idx'));
        $('#wpsh-edit-source').val(row.find('.wpsh-source-cell code').text());
        $('#wpsh-edit-target').val(row.find('.wpsh-target-link').text());
        $('#wpsh-edit-code').val(row.find('.wpsh-badge').text().replace(/\D/g,''));
        $('#wpsh-edit-modal').fadeIn();
    });

    $('.wpsh-modal-close').on('click', () => $('.wpsh-modal').fadeOut());
    
    $('#wpsh-save-edit-btn').on('click', function() {
        const data = {
            action: 'wpsh_save_redirection', nonce: wpsh_admin_vars.nonces.redir,
            idx: $('#wpsh-edit-idx').val(), source: $('#wpsh-edit-source').val(),
            target: $('#wpsh-edit-target').val(), code: $('#wpsh-edit-code').val()
        };
        postWithNonceRecovery( data, (res) => { if(res.success) location.reload(); });
    });

    // Toggle Active Rule.
    $(document).on('change', '.wpsh-item-toggle', function() {
        const row = $(this).closest('tr');
        const idx = row.data('idx');
        const active = $(this).is(':checked') ? '1' : '0';
        postWithNonceRecovery( { action: 'wpsh_toggle_redirection_rule', nonce: wpsh_admin_vars.nonces.redir, idx: idx, active: active }, (res) => {
            if (res.success) toastr.success('Rule updated.');
            else toastr.error('Failed to update rule.');
        });
    });

    // Export/Import/Sample.
    $('#wpsh-export-btn').on('click', function() {
        const $btn = $(this); $btn.prop('disabled', true).text('Exporting...');
        postWithNonceRecovery( { action: 'wpsh_export_redirections', nonce: wpsh_admin_vars.nonces.redir }, function(res) {
            $btn.prop('disabled', false).text('Export');
            if (res.success) {
                const blob = new Blob([res.data], { type: 'text/csv' });
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a'); a.href = url; a.download = 'redirections_export.csv';
                document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url);
                toastr.success('Export completed!');
            } else toastr.error('Export failed: ' + (res.data || 'Unknown error'));
        });
    });

    $('#wpsh-sample-csv-btn').on('click', function() {
        let csv = "Source,Target,Code,Active,Hits\n\"/old-page-1\",\"/new-page-1\",301,1,0\n\"/old-page-2\",18765,301,1,0";
        const blob = new Blob([csv], { type: 'text/csv' });
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a'); a.href = url; a.download = 'redirections_sample.csv';
        document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url);
    });

    $('#wpsh-import-btn').on('click', () => $('#wpsh-import-file').click());
    $('#wpsh-import-file').on('change', function(e) {
        const file = e.target.files[0]; if (!file) return;
        const reader = new FileReader();
        reader.onload = function(event) {
            postWithNonceRecovery( { action: 'wpsh_import_redirections', nonce: wpsh_admin_vars.nonces.redir, csv_data: event.target.result }, function(res) {
                if (res.success) { toastr.success(res.data); setTimeout(() => location.reload(), 1500); }
                else toastr.error('Import failed: ' + (res.data || 'Unknown error'));
            });
        };
        reader.readAsText(file); $(this).val('');
    });

    // Initialize DataTable (at the end, wrapped in safety).
    if ($redirTable.length && $.fn.DataTable) {
        try {
            tableObj = $redirTable.DataTable({
                pageLength: 10,
                order: [[2, 'asc']],
                columnDefs: [ { orderable: false, targets: [0, 1, 5] } ],
                drawCallback: function() {
                    $('.wpsh-select-item').each(function() { if (selectedIndices.has($(this).val())) $(this).prop('checked', true); });
                    updateBulkDeleteVisibility(); syncSelectAllHeader();
                }
            });
        } catch (e) {
            console.error('DataTable initialization failed:', e);
        }
    }

    $(document).on('click', '.wpsh-regen-excluded', function(e) {
        e.preventDefault();
        Swal.fire({
            title: 'Regeneration Disabled',
            text: 'This post is currently excluded from static HTML cache. Please disable the "Exclude" option in the post settings to regenerate its static version.',
            icon: 'info',
            confirmButtonText: 'OK'
        });
    });

    // Logs functionality
    var currentPage = 1;
    var currentFilters = {
        level: '',
        search: '',
        date_from: '',
        date_to: ''
    };

    function loadLogs(page = 1) {
        currentPage = page;
        var offset = (page - 1) * 50;
        
        $('#wpsh-logs-tbody').html('<tr><td colspan="7" class="wpsh-loading">Loading logs...</td></tr>');
        
        ajaxWithNonceRecovery({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'wpsh_get_logs',
                nonce: wpsh_admin_vars.nonces.settings,
                level: currentFilters.level,
                search: currentFilters.search,
                date_from: currentFilters.date_from,
                date_to: currentFilters.date_to,
                limit: 50,
                offset: offset
            },
            success: function(response) {
                if (response.success) {
                    renderLogs(response.data.logs, response.data.total, response.data.stats);
                } else {
                    $('#wpsh-logs-tbody').html('<tr><td colspan="7" class="wpsh-loading">Error loading logs: ' + response.data + '</td></tr>');
                }
            },
            error: function() {
                $('#wpsh-logs-tbody').html('<tr><td colspan="7" class="wpsh-loading">Error loading logs</td></tr>');
            }
        });
    }

    function renderLogs(logs, total, stats) {
        // Update statistics
        $('#wpsh-logs-total').text(stats.total);
        $('#wpsh-logs-24h').text(stats.last_24h);
        $('#wpsh-logs-errors').text(stats.error);
        $('#wpsh-logs-success').text(stats.success);

        // Update pagination info
        var start = total > 0 ? ((currentPage - 1) * 50) + 1 : 0;
        var end = Math.min(currentPage * 50, total);
        $('#wpsh-logs-showing').text('Showing ' + start + '-' + end + ' of ' + total + ' entries');
        $('#wpsh-logs-current-page').text(currentPage);
        $('#wpsh-logs-total-pages').text(Math.ceil(total / 50));

        // Update pagination buttons
        $('#wpsh-logs-prev').prop('disabled', currentPage === 1);
        $('#wpsh-logs-next').prop('disabled', currentPage >= Math.ceil(total / 50));

        // Render logs table
        var tbody = '';
        if (logs.length === 0) {
            tbody = '<tr><td colspan="10" class="wpsh-loading">No logs found</td></tr>';
        } else {
            logs.forEach(function(log) {
                tbody += '<tr>';
                tbody += '<td>' + log.timestamp + '</td>';
                tbody += '<td>' + log.level + '</td>';
                tbody += '<td>' + log.message + '</td>';
                tbody += '<td>' + log.function + '</td>';
                tbody += '<td>' + log.file + '</td>';
                tbody += '<td>' + log.line + '</td>';
                tbody += '<td>' + log.user + '</td>';
                tbody += '<td>' + log.ip_address + '</td>';
                tbody += '<td>' + log.memory + '</td>';
                tbody += '<td><button class="wpsh-btn wpsh-btn-secondary wpsh-view-context" data-context="' + encodeURIComponent(log.context) + '">View Details</button></td>';
                tbody += '</tr>';
            });
        }
        $('#wpsh-logs-tbody').html(tbody);
    }

    // Logs event handlers
    $('#wpsh-logs-refresh').on('click', function() {
        loadLogs(currentPage);
    });

    $('#wpsh-logs-filter-btn').on('click', function() {
        currentFilters.level = $('#wpsh-log-level-filter').val();
        currentFilters.search = $('#wpsh-log-search').val();
        currentFilters.date_from = $('#wpsh-log-date-from').val();
        currentFilters.date_to = $('#wpsh-log-date-to').val();
        loadLogs(1);
    });

    $('#wpsh-logs-reset-btn').on('click', function() {
        $('#wpsh-log-level-filter').val('');
        $('#wpsh-log-search').val('');
        $('#wpsh-log-date-from').val('');
        $('#wpsh-log-date-to').val('');
        currentFilters = {
            level: '',
            search: '',
            date_from: '',
            date_to: ''
        };
        loadLogs(1);
    });

    $('#wpsh-logs-prev').on('click', function() {
        if (currentPage > 1) {
            loadLogs(currentPage - 1);
        }
    });

    $('#wpsh-logs-next').on('click', function() {
        loadLogs(currentPage + 1);
    });

    $('#wpsh-logs-clear').on('click', function() {
        Swal.fire({
            title: 'Clear All Logs?',
            text: 'This will permanently delete all log entries. This action cannot be undone.',
            icon: 'warning',
            showCancelButton: true,
            confirmButtonColor: '#ef4444',
            cancelButtonColor: '#6b7280',
            confirmButtonText: 'Clear All Logs',
            cancelButtonText: 'Cancel'
        }).then((result) => {
            if (result.isConfirmed) {
                ajaxWithNonceRecovery({
                    url: ajaxurl,
                    type: 'POST',
                    data: {
                        action: 'wpsh_clear_logs',
                        nonce: wpsh_admin_vars.nonces.settings
                    },
                    success: function(response) {
                        if (response.success) {
                            toastr.success('Logs cleared successfully');
                            loadLogs(1);
                        } else {
                            toastr.error('Failed to clear logs: ' + response.data);
                        }
                    },
                    error: function() {
                        toastr.error('Failed to clear logs');
                    }
                });
            }
        });
    });

    $('#wpsh-logs-export').on('click', function() {
        refreshNonces(function() {
            var form = $('<form>', {
                method: 'POST',
                action: ajaxurl
            });

            form.append($('<input>', {
                type: 'hidden',
                name: 'action',
                value: 'wpsh_export_logs'
            }));

            form.append($('<input>', {
                type: 'hidden',
                name: 'nonce',
                value: wpsh_admin_vars.nonces.settings
            }));

            form.append($('<input>', {
                type: 'hidden',
                name: 'level',
                value: currentFilters.level
            }));

            form.append($('<input>', {
                type: 'hidden',
                name: 'search',
                value: currentFilters.search
            }));

            form.append($('<input>', {
                type: 'hidden',
                name: 'date_from',
                value: currentFilters.date_from
            }));

            form.append($('<input>', {
                type: 'hidden',
                name: 'date_to',
                value: currentFilters.date_to
            }));

            form.appendTo('body').submit().remove();
        }, function() {
            notifySessionExpired();
        });
    });

    $(document).on('click', '.wpsh-view-context', function() {
        var context = $(this).data('context');
        if (context) {
            try {
                var contextData = JSON.parse(decodeURIComponent(context));
                Swal.fire({
                    title: 'Log Context',
                    html: '<pre style="text-align: left; font-size: 12px; max-height: 400px; overflow-y: auto;">' + JSON.stringify(contextData, null, 2) + '</pre>',
                    width: '600px',
                    confirmButtonText: 'Close'
                });
            } catch (e) {
                Swal.fire({
                    title: 'Log Context',
                    text: context,
                    confirmButtonText: 'Close'
                });
            }
        } else {
            Swal.fire({
                title: 'Log Context',
                text: 'No additional context available',
                confirmButtonText: 'Close'
            });
        }
    });

    // Load logs when logs tab is clicked
    $('.wpsh-nav-item[data-tab="logs"]').on('click', function() {
        loadLogs(1);
    });
});
