jQuery(document).ready(function($) {
    // Function to format bytes into KB, MB, etc.
    function formatBytes(bytes, decimals = 2) {
        if (!bytes || bytes === 0) return '0 Bytes'; // Handle null/undefined/zero
        const k = 1024;
        const dm = decimals < 0 ? 0 : decimals;
        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
    }

    // Function to poll server and check if conversion actually succeeded after timeout
    function checkConversionStatus(attachmentId, $statusElement, maxAttempts = 10) {
        let attempts = 0;
        
        const pollInterval = setInterval(function() {
            attempts++;
            
            // Stop after maxAttempts (10 attempts = ~30 seconds of checking)
            if (attempts > maxAttempts) {
                clearInterval(pollInterval);
                console.log(`[WEBPICR] Stopped polling for attachment ${attachmentId} after ${maxAttempts} attempts`);
                return;
            }
            
            console.log(`[WEBPICR] Polling attempt ${attempts} for attachment ${attachmentId}`);
            
            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'webpicr_check_conversion_status',
                    attachment_id: attachmentId,
                    nonce: webpicr_status_check_nonce // Will be localized from PHP
                },
                timeout: 10000, // 10 second timeout for status check
                dataType: 'json'
            })
            .done(function(response) {
                if (response.success && response.data.converted) {
                    // Conversion actually succeeded! Update UI
                    clearInterval(pollInterval);
                    console.log(`[WEBPICR] Conversion actually succeeded for attachment ${attachmentId}!`);
                    
                    const savedBytes = response.data.saved_bytes;
                    const savedFormatted = savedBytes ? formatBytes(savedBytes) : 'N/A';
                    const successMsg = 'Converted to WebP' + (savedFormatted !== 'N/A' ? ' (Saved ' + savedFormatted + ')' : '');
                    
                    $statusElement.replaceWith('<span class="webpicr-success" style="color: green !important; display: inline-block !important; visibility: visible !important;">' + successMsg + '</span>');
                    
                    // Update media library display if we have attachment ID
                    const oldExt = determineOriginalExtension(attachmentId);
                    updateMediaLibraryDisplay(attachmentId, oldExt, 'webp');
                    
                    // Update global banner if available
                    if (response.data.total_saved_bytes !== undefined) {
                        const totalSavedFormatted = formatBytes(response.data.total_saved_bytes);
                        const $bannerValue = $('#webpicr-total-savings-banner-value');
                        const $bannerContainer = $('#webpicr-total-savings-banner-container');
                        
                        if ($bannerValue.length) {
                            $bannerValue.text(totalSavedFormatted);
                            if ($bannerContainer.length) {
                                $bannerContainer.css('display', 'inline-block');
                            }
                        }
                    }
                }
            })
            .fail(function(xhr, status, error) {
                console.warn(`[WEBPICR] Status check failed for attachment ${attachmentId}:`, status);
            });
        }, 3000); // Check every 3 seconds
    }

    // Single item conversion handler (remains largely the same)
    $('body').on('click', '.webpicr-convert-link', function(e) {
        e.preventDefault();

        const $link = $(this);
        const $actionsDiv = $link.closest('div.row-actions');
        const attachmentId = $link.data('attachment-id');
        const nonce = $link.data('nonce');

        if (!attachmentId || !nonce) {
            console.error('Missing attachment ID or nonce.');
            if ($actionsDiv.length) $actionsDiv.html('<span style="color: red;">Error: Link data missing.</span>');
            return;
        }
        if (!$actionsDiv.length) {
             console.error('Could not find parent .row-actions div.');
             return;
        }

        const $convertingSpan = $('<span class="webpicr-converting">Converting... <span class="spinner is-active" style="float: none; vertical-align: middle;"></span></span>');
        $link.replaceWith($convertingSpan);

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'webpicr_convert_image_to_webp',
                attachment_id: attachmentId,
                webpicr_nonce: nonce
            },
            timeout: 300000, // 5 minute timeout for large images
            dataType: 'json'
        })
        .done(function(response) {
            handleAjaxResponse($convertingSpan, response, attachmentId); // Pass attachment ID directly
        })
        .fail(function(xhr, status, error) {
            console.error('WebP Conversion AJAX Error:', {
                status: status,
                error: error,
                httpStatus: xhr.status,
                responseText: xhr.responseText ? xhr.responseText.substring(0, 500) : 'No response'
            });
            
            let errorMsg = 'AJAX Error.';
            if (status === 'timeout') {
                errorMsg = 'Timeout - checking if conversion completed...';
                $convertingSpan.replaceWith('<span class="webpicr-checking" style="color: orange;">' + errorMsg + ' <span class="spinner is-active" style="float: none; vertical-align: middle;"></span></span>');
                
                // Start polling to see if it actually succeeded
                const $checkingSpan = $('.webpicr-checking').last();
                checkConversionStatus(attachmentId, $checkingSpan);
                return; // Don't show error immediately
            } else if (xhr.status === 0) {
                errorMsg = 'Network error - check connection.';
            } else if (xhr.status === 500) {
                errorMsg = 'Server error - check debug log.';
            } else if (xhr.status === 503) {
                errorMsg = 'Server busy - try again later.';
            }
            
            $convertingSpan.replaceWith('<span class="webpicr-error" style="color: red;">' + errorMsg + '</span>');
        });
    });

    // Recalculate Button Handler (remains the same)
    $('body').on('click', '#webpicr-recalculate-button', function(e) {
        e.preventDefault();
        const $button = $(this);
        const nonce = $button.data('nonce');
        const $bannerValue = $('#webpicr-total-savings-banner-value');
        const $originalIcon = $button.find('.dashicons');
        const originalTitle = $button.attr('title');

        if (!nonce) {
            console.error('Recalculate button nonce missing.');
            return;
        }

        $button.prop('disabled', true);
        $button.attr('title', 'Recalculating...');
        $button.html('<span class="spinner is-active" style="float: none; vertical-align: middle; margin: 0 5px;"></span>');

        $.post(ajaxurl, {
            action: 'webpicr_recalculate_savings',
            webpicr_nonce: nonce
        })
        .done(function(response) {
             if (response.success) {
                 const accurateTotalBytes = response.data.accurate_total_saved_bytes;
                 const accurateTotalFormatted = formatBytes(accurateTotalBytes);
                 const accurateTotalCount = response.data.accurate_total_converted_count;
                 
                 // Update the savings display
                 if ($bannerValue.length) {
                     $bannerValue.text(accurateTotalFormatted);
                      $bannerValue.css({ backgroundColor: '#dff0d8' }).animate({ backgroundColor: 'transparent' }, 1000);
                 }
                 
                 // Update the overview stats if visible
                 const accurateTotalSkipped = response.data.accurate_total_skipped_count;
                 const accurateTotalFailed = response.data.accurate_total_failed_count;
                 
                 $('.webpicr-bulk-stats li').each(function() {
                     const $li = $(this);
                     if ($li.text().includes('already converted')) {
                         $li.html('<strong>' + accurateTotalCount.toLocaleString() + '</strong> already converted');
                         $li.css({ backgroundColor: '#dff0d8' }).animate({ backgroundColor: 'transparent' }, 1000);
                     } else if ($li.text().includes('skipped')) {
                         $li.html('<strong>' + accurateTotalSkipped.toLocaleString() + '</strong> Total skipped');
                         $li.css({ backgroundColor: '#dff0d8' }).animate({ backgroundColor: 'transparent' }, 1000);
                     } else if ($li.text().includes('failed')) {
                         $li.html('<strong>' + accurateTotalFailed.toLocaleString() + '</strong> Total failed');
                         $li.css({ backgroundColor: '#dff0d8' }).animate({ backgroundColor: 'transparent' }, 1000);
                     }
                 });
                 
                 $button.html('<span class="dashicons dashicons-yes-alt" style="color: green;"></span>');
                 $button.attr('title', 'Recalculated!');
             } else {
                 console.error('Recalculation AJAX call reported failure:', response.data.message);
                 $button.html('<span class="dashicons dashicons-dismiss" style="color: red;"></span>');
                 $button.attr('title', 'Error: ' + (response.data.message || 'Unknown error'));
             }
         })
         .fail(function(xhr, status, error) {
             console.error('Recalculation AJAX request failed:', status, error);
             $button.html('<span class="dashicons dashicons-dismiss" style="color: red;"></span>');
             $button.attr('title', 'AJAX Error. Check console.');
         })
         .always(function() {
             setTimeout(function() {
                 $button.prop('disabled', false);
                 $button.html($originalIcon.clone());
                 $button.attr('title', originalTitle);
             }, 1500);
         });
     });

    // --- Client-Side Bulk Processing Logic ---

    let webpicrBulkQueue = [];
    let webpicrTotalItems = 0;
    let webpicrProcessedItems = 0;
    let webpicrFailedItems = 0;
    let webpicrSkippedItems = 0;
    let webpicrAjaxFailedItems = 0;
    let $webpicrProgressBar;
    let $webpicrProgressText;
    let $webpicrProgressContainer;

    // Helper function to extract attachment ID from status element context (fallback)
    function extractAttachmentId($statusElement) {
        // Method 1: Extract from the table row ID (post-XXXX)
        const row = $statusElement.closest('tr[id^="post-"]');
        if (row.length) {
            const rowId = row.attr('id');
            const match = rowId.match(/^post-(\d+)$/);
            if (match) {
                return parseInt(match[1]);
            }
        }
        
        // Method 2: Look in Phoenix rename input
        const phoenixInput = $statusElement.closest('tr').find('.phoenix-media-rename-filename[data-post-id]');
        if (phoenixInput.length) {
            return parseInt(phoenixInput.data('post-id'));
        }
        
        // Method 3: Look for data-attachment-id in nearby elements
        let attachmentId = $statusElement.closest('.row-actions').find('[data-attachment-id]').data('attachment-id');
        if (attachmentId) return attachmentId;
        
        console.warn('[WEBPICR] Could not extract attachment ID from status element context');
        return null;
    }
    
    // Helper function to determine original file extension
    function determineOriginalExtension(attachmentId) {
        // Look at the current filename display to determine extension
        const row = $(`#post-${attachmentId}`);
        if (row.length) {
            const filenameText = row.find('p.filename').text().trim();
            const match = filenameText.match(/\.([a-zA-Z0-9]+)$/);
            if (match) {
                return match[1].toLowerCase();
            }
            
            // Fallback: look at Phoenix extension display
            const phoenixExt = row.find('.file_ext').text().replace('.', '');
            if (phoenixExt) {
                return phoenixExt.toLowerCase();
            }
        }
        
        // Default fallback - most common conversion types
        console.warn(`[WEBPICR] Could not determine original extension for attachment ${attachmentId}, defaulting to 'png'`);
        return 'png';
    }

    // Function to update media library display after successful conversion
    function updateMediaLibraryDisplay(attachmentId, oldExt, newExt) {
        // Skip DOM updates if we're not on the media library page (e.g., during bulk all from settings)
        if (!$('body').hasClass('upload-php') || !$('.wp-list-table.media').length) {
            console.log(`[WEBPICR] Skipping media library DOM updates - not on media library page`);
            return;
        }
        
        const row = $(`#post-${attachmentId}`);
        
        if (row.length) {
            console.log(`[WEBPICR] Updating media library display for attachment ${attachmentId}: .${oldExt} → .${newExt}`);
            
            // 1. Update filename display - use a more direct approach
            const filenameElement = row.find('p.filename');
            if (filenameElement.length) {
                const currentHtml = filenameElement.html();
                console.log('[WEBPICR] Current filename HTML:', currentHtml);
                
                // Replace the extension in the HTML content
                const updatedHtml = currentHtml.replace(
                    new RegExp(`(\\S+)\\.${oldExt}(\\s*</|\\s*$)`, 'gi'), 
                    `$1.${newExt}$2`
                );
                console.log('[WEBPICR] Updated filename HTML:', updatedHtml);
                
                if (updatedHtml !== currentHtml) {
                    filenameElement.html(updatedHtml);
                    console.log('[WEBPICR] Filename display updated successfully');
                } else {
                    console.warn('[WEBPICR] Filename HTML did not change - trying alternative approach');
                    // Alternative: directly replace any occurrence of the old extension
                    const alternativeHtml = currentHtml.replace(new RegExp(`\\.${oldExt}`, 'gi'), `.${newExt}`);
                    if (alternativeHtml !== currentHtml) {
                        filenameElement.html(alternativeHtml);
                        console.log('[WEBPICR] Filename display updated with alternative approach');
                    } else {
                        console.error('[WEBPICR] Could not update filename display');
                    }
                }
            }
            
            // 2. Update Copy URL button
            row.find('.copy-attachment-url').attr('data-clipboard-text', function(i, url) {
                if (url) {
                    return url.replace(new RegExp(`\\.${oldExt}$`, 'i'), `.${newExt}`);
                }
                return url;
            });
            
            // 3. Update Download link
            row.find('.download a').attr('href', function(i, url) {
                if (url && url.includes(`.${oldExt}`)) {
                    return url.replace(new RegExp(`\\.${oldExt}$`, 'i'), `.${newExt}`);
                }
                return url;
            });
            
            // 4. Update thumbnail image (handle src and srcset attributes)
            row.find('.media-icon img').each(function() {
                const $img = $(this);
                
                // Update src attribute
                const currentSrc = $img.attr('src');
                if (currentSrc) {
                    console.log('[WEBPICR] Current thumbnail src:', currentSrc);
                    // Update various thumbnail sizes (not just 150x150)
                    const updatedSrc = currentSrc.replace(new RegExp(`-\\d+x\\d+\\.${oldExt}$`, 'i'), function(match) {
                        return match.replace(`.${oldExt}`, `.${newExt}`);
                    });
                    if (updatedSrc !== currentSrc) {
                        $img.attr('src', updatedSrc);
                        console.log('[WEBPICR] Updated thumbnail src to:', updatedSrc);
                    }
                }
                
                // Update srcset attribute (contains multiple sizes)
                const currentSrcset = $img.attr('srcset');
                if (currentSrcset) {
                    console.log('[WEBPICR] Current thumbnail srcset:', currentSrcset);
                    const updatedSrcset = currentSrcset.replace(new RegExp(`\\.${oldExt}\\s+\\d+w`, 'gi'), function(match) {
                        return match.replace(`.${oldExt}`, `.${newExt}`);
                    });
                    if (updatedSrcset !== currentSrcset) {
                        $img.attr('srcset', updatedSrcset);
                        console.log('[WEBPICR] Updated thumbnail srcset to:', updatedSrcset);
                    }
                }
            });
            
            // 5. Update Phoenix extension display (if Phoenix is active)
            row.find('.file_ext').text(`.${newExt}`);
            
            console.log(`[WEBPICR] Successfully updated media library display for attachment ${attachmentId}`);
        } else {
            console.warn(`[WEBPICR] Could not find media library row for attachment ${attachmentId}`);
        }
    }

    // Shared function to handle AJAX response for both single and bulk actions
    function handleAjaxResponse($statusElement, response, attachmentId) {
        if (response.success) {
            // Use the TOTAL sizes returned from the AJAX call
            const totalOriginalSize = response.data.original_size;
            const totalFinalSize = response.data.final_size;
            let savedFormatted = 'N/A';
            // Calculate savings based on TOTAL sizes
            if (totalOriginalSize && totalFinalSize && totalOriginalSize > totalFinalSize) {
                const savedBytes = totalOriginalSize - totalFinalSize;
                savedFormatted = formatBytes(savedBytes);
            } else {
                console.warn("Conversion successful but size info missing/invalid or final size not smaller.", response.data);
            }

            // Update individual row status - Use !important to try and override WP styles
            const successMsg = response.data.message + (savedFormatted !== 'N/A' ? ' (Saved ' + savedFormatted + ')' : '');
            $statusElement.replaceWith('<span class="webpicr-success" style="color: green !important; display: inline-block !important; visibility: visible !important;">' + successMsg + '</span>');
            
            // NEW: Update media library display after successful conversion
            if (attachmentId) {
                console.log(`[WEBPICR] Using passed attachment ID: ${attachmentId}`);
                // Determine file extensions - assume common conversions to WebP
                const oldExt = determineOriginalExtension(attachmentId);
                updateMediaLibraryDisplay(attachmentId, oldExt, 'webp');
            } else {
                // Fallback: Extract attachment ID from the status element's context
                console.log('[WEBPICR] No attachment ID passed, attempting to extract from DOM');
                const extractedId = extractAttachmentId($statusElement);
                if (extractedId) {
                    const oldExt = determineOriginalExtension(extractedId);
                    updateMediaLibraryDisplay(extractedId, oldExt, 'webp');
                }
            }

            // Update Global Banner if total is provided (usually only from single conversion response)
            if (response.data.total_saved_bytes !== undefined) {
                const totalSavedFormatted = formatBytes(response.data.total_saved_bytes);
                const $bannerValue = $('#webpicr-total-savings-banner-value');
                const $bannerContainer = $('#webpicr-total-savings-banner-container');

                if ($bannerValue.length) {
                    $bannerValue.text(totalSavedFormatted);
                    if ($bannerContainer.length) {
                        $bannerContainer.css('display', 'inline-block');
                    }
                }
            }
        } else {
            // Display error message from PHP
            const errorMsg = response.data.message || 'Unknown error during conversion.';
            $statusElement.replaceWith('<span class="webpicr-error" style="color: red;">' + errorMsg + '</span>');
        }
    }

    // Function to process the next item in the bulk queue
    function processNextBulkItem() {
        if (webpicrBulkQueue.length === 0) {
            // Finished
            if ($webpicrProgressText && $webpicrProgressBar) {
                let finalMessage = `Bulk conversion complete. Success: ${webpicrProcessedItems}, Skipped: ${webpicrSkippedItems}, Failed: ${webpicrAjaxFailedItems}.`;
                $webpicrProgressText.text('Complete'); // Clear the old text
                // Display final message inside the bar area
                $webpicrProgressBar.html(`<div style="width: 100%; text-align: center; font-weight: bold; background: #5ec8fd40;color: #3c434a; padding: 2px 0;">${finalMessage}</div>`);
                $webpicrProgressContainer.addClass('webpicr-bulk-complete'); // Add class to grey out bar via CSS
            }
            return;
        }

        const attachmentId = webpicrBulkQueue.shift(); // Get next ID
        const $row = $('#post-' + attachmentId);
        const $actionsDiv = $row.find('div.row-actions');

        if (!$actionsDiv.length) {
            console.warn(`Could not find actions div for attachment ID ${attachmentId}. Skipping.`);
            webpicrSkippedItems++; // Count as skipped
            updateBulkProgress();
            setTimeout(processNextBulkItem, 50); // Move quickly to the next one
            return;
        }

        // Find the original convert link *within this specific row* to get its nonce.
        // If the link doesn't exist, the item likely isn't eligible (already done/failed/wrong type).
        const $link = $actionsDiv.find('.webpicr-convert-link[data-attachment-id="' + attachmentId + '"]');
        const nonce = $link.data('nonce'); // Get nonce directly from the specific link

        // If the link doesn't exist or doesn't have a nonce, skip this item.
        if (!$link.length || !nonce) {
            // Find the current status to log it
            const $currentStatus = $actionsDiv.children('span, a').first();
            console.log(`Skipping item ${attachmentId} - No valid convert link/nonce found. Current status: ${$currentStatus.text().trim()}`);
            webpicrSkippedItems++; // Count as skipped
            updateBulkProgress();
            setTimeout(processNextBulkItem, 50); // Quick skip
            return;
        }

        // Show processing status in the specific row
        const $convertingSpan = $('<span class="webpicr-converting">Processing... <span class="spinner is-active" style="float: none; vertical-align: middle;"></span></span>');
        $link.replaceWith($convertingSpan); // Replace the link we found

        // Perform AJAX request for this single item
        $.ajax({
            url: webpicr_bulk_vars.ajax_url,
            type: 'POST',
            data: {
                action: 'webpicr_convert_image_to_webp',
                attachment_id: attachmentId,
                webpicr_nonce: nonce
            },
            timeout: 300000, // 5 minute timeout for large images
            dataType: 'json'
        })
        .done(function(response) {
            webpicrProcessedItems++;
            handleAjaxResponse($convertingSpan, response, attachmentId); // Update row UI with attachment ID
            if (!response.success) {
                // If the server specifically reported an error (not just 'not smaller')
                // Consider this a failure for the summary, otherwise it's just 'processed'.
                // Maybe check response.data.message for specific failure strings?
                // For now, let's count any response where success=false as processed, but log potential issues.
                console.warn(`Processing reported success=false for ID ${attachmentId}: `, response.data.message);
            }
        })
        .fail(function(xhr, status, error) {
            console.error(`AJAX Error for ID ${attachmentId}:`, {
                status: status,
                error: error,
                httpStatus: xhr.status,
                responseText: xhr.responseText ? xhr.responseText.substring(0, 200) : 'No response'
            });
            
            let errorMsg = 'AJAX Error';
            if (status === 'timeout') {
                errorMsg = 'Checking...';
                $convertingSpan.replaceWith(`<span class="webpicr-checking" style="color: orange;">${errorMsg}</span>`);
                
                // Start polling to see if it actually succeeded
                const $checkingSpan = $convertingSpan.parent().find('.webpicr-checking').last();
                checkConversionStatus(attachmentId, $checkingSpan);
                
                // Still count as failed initially, but might be corrected by polling
                webpicrAjaxFailedItems++;
                return; // Don't show error immediately
            } else if (xhr.status === 0) {
                errorMsg = 'Network Error';
            } else if (xhr.status >= 500) {
                errorMsg = 'Server Error';
            }
            
            webpicrAjaxFailedItems++; // Count actual AJAX errors as failed
            $convertingSpan.replaceWith(`<span class="webpicr-error" style="color: red;">${errorMsg} (${xhr.status || status})</span>`);
        })
        .always(function() {
            updateBulkProgress();
            // Schedule the next one after a short delay
            setTimeout(processNextBulkItem, 250); // 250ms delay
        });
    }

    // Function to update the overall progress bar and text
    function updateBulkProgress() {
        if (!$webpicrProgressBar || !$webpicrProgressText) return;

        const totalAttemptedOrSkipped = webpicrProcessedItems + webpicrSkippedItems + webpicrAjaxFailedItems;
        const percent = webpicrTotalItems > 0 ? Math.round((totalAttemptedOrSkipped / webpicrTotalItems) * 100) : 0;
        $webpicrProgressBar.find('div').css('width', percent + '%');
        $webpicrProgressText.html(`Processing: ${totalAttemptedOrSkipped} of ${webpicrTotalItems} (${percent}%) - Success: ${webpicrProcessedItems}, Skipped: ${webpicrSkippedItems}, Failed: ${webpicrAjaxFailedItems} <span class="spinner is-active" style="float: none; vertical-align: middle;"></span>`);
    }

    // Initialize bulk processing if triggered (Media Library)
    // Use webpicr_bulk_vars passed from PHP
    if (typeof webpicr_bulk_vars !== 'undefined' && webpicr_bulk_vars.webpicrStartBulk && webpicr_bulk_vars.webpicrBulkIds.length > 0) {
        webpicrBulkQueue = webpicr_bulk_vars.webpicrBulkIds;
        webpicrTotalItems = webpicrBulkQueue.length;
        webpicrProcessedItems = 0;
        webpicrFailedItems = 0;
        webpicrSkippedItems = 0;
        webpicrAjaxFailedItems = 0;

        // Add progress bar UI above the table
        const progressBarHtml = `
            <style>
                #webpicr-bulk-progress-bar.webpicr-bulk-complete > div {background-color: #d1d1d1 !important; transition: background-color 0.5s ease-in;}
                #webpicr-bulk-progress-container.webpicr-bulk-complete small {opacity: 0;height: 0;overflow: hidden; transition: opacity 0.5s ease-in, height 0.5s ease-in;}
            </style>
            <div id="webpicr-bulk-progress-container" style="margin: 15px 0; padding: 10px; border: 1px solid #ccd0d4; background: #fff;">
                <h3 style="margin:8px 0 18px;">WebP Bulk Conversion</h3>
                <div id="webpicr-bulk-progress-text" style="margin-bottom: 5px;">Initializing...</div>
                <div id="webpicr-bulk-progress-bar" style="height: 24px; /* Slightly taller */ background: #e1e1e1; border-radius: 3px; overflow: hidden; position: relative; /* For potential text overlay */">
                    <div style="width: 0%; height: 100%; background: #007cba; transition: width 0.3s ease-out;"></div>
                    <!-- Final text will be placed inside here -->
                </div>
                 <small>Please keep this browser tab open until the process is complete.</small>
            </div>
        `;
        // Insert above the main form containing the media table
        $('form#posts-filter').before(progressBarHtml);

        $webpicrProgressContainer = $('#webpicr-bulk-progress-container'); // Select container
        $webpicrProgressBar = $('#webpicr-bulk-progress-bar');
        $webpicrProgressText = $('#webpicr-bulk-progress-text');

        // Start the first item
        updateBulkProgress(); // Show initial state
        processNextBulkItem();
    }

    // Initialize "Bulk Optimize All" processing if triggered (Settings Page)
    if (typeof webpicr_bulk_all_vars !== 'undefined' && webpicr_bulk_all_vars.webpicrStartBulkAll && webpicr_bulk_all_vars.webpicrBulkAllIds.length > 0) {
        initializeBulkOptimizeAll();
    }

    // Handle "Start Bulk Optimization" button click
    $(document).on('click', '#webpicr-start-bulk-all-btn', function(e) {
        e.preventDefault();
        
        if (!confirm('This will convert all eligible images to WebP. Continue?')) {
            return;
        }

        const $btn = $(this);
        $btn.prop('disabled', true).text('Getting ready...');
        
        // Hide any previous success message
        $('#webpicr-bulk-success-message').hide();

        // First, get the list of eligible IDs via AJAX
        $.ajax({
            url: webpicr_bulk_all_vars.ajaxurl,
            type: 'POST',
            data: {
                action: 'webpicr_get_bulk_all_ids',
                nonce: webpicr_bulk_all_vars.get_ids_nonce
            },
            dataType: 'json'
        })
        .done(function(response) {
            if (response.success && response.data.attachment_ids.length > 0) {
                // Debug the AJAX response
                console.log('AJAX Response Debug - IDs count:', response.data.attachment_ids.length);
                console.log('AJAX Response Debug - Timestamp:', response.data.debug_timestamp);
                console.log('AJAX Response Debug - First 5 IDs from server:', response.data.debug_first_5_ids);
                console.log('AJAX Response Debug - First 5 IDs from response:', response.data.attachment_ids.slice(0, 5));
                console.log('AJAX Response Debug - Full response:', response.data);
                
                // Set up the bulk processing variables
                webpicr_bulk_all_vars.webpicrStartBulkAll = true;
                webpicr_bulk_all_vars.webpicrBulkAllIds = response.data.attachment_ids;
                webpicr_bulk_all_vars.webpicrBulkAllNonces = response.data.nonces || {};
                webpicr_bulk_all_vars.webpicrStartingSavings = response.data.current_total_savings || 0;
                webpicr_bulk_all_vars.webpicrFormattedSavings = response.data.formatted_savings || '0 Bytes';
                webpicr_bulk_all_vars.webpicrCurrentConvertedCount = response.data.current_converted_count || 0;
                webpicr_bulk_all_vars.webpicrTotalConvertible = response.data.total_convertible || response.data.attachment_ids.length;
                
                console.log('After setting vars - webpicrBulkAllIds length:', webpicr_bulk_all_vars.webpicrBulkAllIds.length);
                console.log('After setting vars - webpicrTotalConvertible:', webpicr_bulk_all_vars.webpicrTotalConvertible);
                
                // Hide the button and start processing
                $btn.closest('div').hide();
                initializeBulkOptimizeAll();
            } else {
                // Show friendly success message instead of error alert
                const message = response.success ? 
                    'All eligible images have already been converted! 🎉' : 
                    (response.data?.message || 'No eligible images found or an error occurred.');
                
                // Create or update success message directly above the button
                let $successMessage = $('#webpicr-bulk-success-message');
                if ($successMessage.length === 0) {
                    $successMessage = $('<div id="webpicr-bulk-success-message" style="background: #d4edda; color: #155724; padding: 12px; border-radius: 4px; margin-bottom: 15px; border: 1px solid #c3e6cb;"></div>');
                    $btn.before($successMessage);
                }
                $successMessage.html(message).show();
                
                $btn.prop('disabled', false).text('Start Bulk Optimization');
            }
        })
        .fail(function(xhr, status, error) {
            console.error('Failed to get bulk IDs:', status, error);
            alert('Failed to start bulk optimization. Please try again.');
            $btn.prop('disabled', false).text('Start Bulk Optimization');
        });
    });

    // Bulk Optimize All functionality for Settings Page (moved inside jQuery scope)
    function initializeBulkOptimizeAll() {
    // Set up variables for "Bulk Optimize All"
    let bulkAllQueue = webpicr_bulk_all_vars.webpicrBulkAllIds;
    let bulkAllNonces = webpicr_bulk_all_vars.webpicrBulkAllNonces || {};
    let bulkAllTotal = webpicr_bulk_all_vars.webpicrTotalConvertible || bulkAllQueue.length; // Use total convertible images for progress
    
    // Debug logging to track the count discrepancy
    console.log('Bulk All Debug - Queue length:', bulkAllQueue.length);
    console.log('Bulk All Debug - Total convertible images:', webpicr_bulk_all_vars.webpicrTotalConvertible);
    console.log('Bulk All Debug - bulkAllTotal set to:', bulkAllTotal);
    let bulkAllProcessed = 0;
    let bulkAllSkipped = 0;
    let bulkAllFailed = 0;
    let bulkAllPaused = false;
    let bulkAllCanceling = false; // Track graceful cancel state
    let bulkAllStartingSavings = webpicr_bulk_all_vars.webpicrStartingSavings || 0;
    let bulkAllCurrentSavings = bulkAllStartingSavings;
    
    // Progress state management (persistent across page refreshes)
    const stateKey = 'webpicr_bulk_all_state';
    let savedState = localStorage.getItem(stateKey);
    
    // Check if user explicitly canceled recently (within last 5 minutes)
    const cancelFlag = localStorage.getItem('webpicr_bulk_all_canceled');
    const recentlyCanceled = cancelFlag && (Date.now() - parseInt(cancelFlag) < 5 * 60 * 1000); // 5 minutes
    
    if (savedState && !recentlyCanceled) {
        try {
            savedState = JSON.parse(savedState);
            if (savedState.timestamp && (Date.now() - savedState.timestamp < 24 * 60 * 60 * 1000)) { // 24 hours
                // Check if this is the same session (same original queue size) or a new one
                const originalQueueSize = savedState.originalQueueSize || 0;
                const currentQueueSize = bulkAllQueue.length;
                
                if (originalQueueSize === currentQueueSize) {
                    // Same session - resume from saved state
                    bulkAllQueue = savedState.remainingIds || bulkAllQueue;
                    bulkAllProcessed = savedState.processed || 0;
                    bulkAllSkipped = savedState.skipped || 0;
                    bulkAllFailed = savedState.failed || 0;
                    console.log('Resuming bulk conversion from saved state');
                } else {
                    // Different queue size = new bulk operation, start fresh
                    localStorage.removeItem(stateKey);
                    console.log(`New bulk operation detected (queue: ${currentQueueSize} vs saved: ${originalQueueSize}), starting fresh`);
                }
            }
        } catch (e) {
            // Invalid state, start fresh
            localStorage.removeItem(stateKey);
        }
    } else if (recentlyCanceled) {
        // User recently canceled, start fresh and clear the cancel flag
        localStorage.removeItem(stateKey);
        localStorage.removeItem('webpicr_bulk_all_canceled');
    }

    // Create progress UI
    const $section = $('#webpicr-bulk-optimize-all-section');
    const progressHtml = `
        <div id="webpicr-bulk-all-progress" style="margin: 20px 0; padding: 20px; border: 1px solid #ccd0d4; background: #fff; border-radius: 4px;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
                <h3 style="margin: 0;">Bulk WebP Optimization Progress</h3>
                <div>
                    <button type="button" id="webpicr-pause-resume-btn" class="button button-secondary">Pause</button>
                    <button type="button" id="webpicr-cancel-bulk-btn" class="button" style="margin-left: 10px;">Cancel</button>
                </div>
            </div>
            <div id="webpicr-bulk-all-progress-text" style="margin-bottom: 10px;">Initializing...</div>
            <div style="background: #e1e1e1; border-radius: 3px; overflow: hidden; height: 30px; position: relative;">
                <div id="webpicr-bulk-all-progress-bar" style="width: 0%; height: 100%; background: #007cba; transition: width 0.3s ease-out;"></div>
                <div id="webpicr-bulk-all-progress-overlay" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: center; font-weight: bold; color: #333; text-shadow: 1px 1px 2px rgba(255,255,255,0.8);">0%</div>
            </div>
            <div style="margin-top: 10px; font-size: 14px; color: #666;">
                <strong>Success:</strong> <span id="webpicr-success-count">${bulkAllProcessed}</span> | 
                <strong>Skipped:</strong> <span id="webpicr-skipped-count">${bulkAllSkipped}</span> | 
                <strong>Failed:</strong> <span id="webpicr-failed-count">${bulkAllFailed}</span> | 
                <strong>Total Savings:</strong> <span id="webpicr-total-savings-count">Loading...</span>
            </div>
            <div style="margin-top: 10px; padding: 10px; background: #fff3cd; border-left: 4px solid #ffc107; font-size: 13px;">
                <strong>Keep this tab open!</strong> Progress is automatically saved and can be resumed if interrupted.
            </div>
        </div>
    `;
    
    $section.after(progressHtml);

    // Cache UI elements
    const $progressContainer = $('#webpicr-bulk-all-progress');
    const $progressBar = $('#webpicr-bulk-all-progress-bar');
    const $progressText = $('#webpicr-bulk-all-progress-text');
    const $progressOverlay = $('#webpicr-bulk-all-progress-overlay');
    const $pauseResumeBtn = $('#webpicr-pause-resume-btn');
    const $cancelBtn = $('#webpicr-cancel-bulk-btn');
    const $successCount = $('#webpicr-success-count');
    const $skippedCount = $('#webpicr-skipped-count');
    const $failedCount = $('#webpicr-failed-count');
    const $totalSavingsCount = $('#webpicr-total-savings-count');

    // Button handlers
    $pauseResumeBtn.on('click', function(e) {
        e.preventDefault(); // Prevent any default form submission
        bulkAllPaused = !bulkAllPaused;
        $(this).text(bulkAllPaused ? 'Resume' : 'Pause');
        if (!bulkAllPaused) {
            processNextBulkAllItem();
        }
    });

    $cancelBtn.on('click', function(e) {
        e.preventDefault(); // Prevent any default form submission
        
        // Check if button says "Close" (bulk process completed)
        if ($(this).text() === 'Close') {
            // Just close/hide the progress UI and reset
            $progressContainer.remove();
            $('#webpicr-start-bulk-all-btn').closest('div').show();
            $('#webpicr-start-bulk-all-btn').prop('disabled', false).text('Start Bulk Optimization');
            localStorage.removeItem(stateKey);
            return;
        }
        
        // Start graceful cancel process - finish current operation first
        bulkAllCanceling = true;
        bulkAllPaused = true; // Stop scheduling new items
        
        // Update UI to show canceling state
        $(this).text('Canceling...').prop('disabled', true);
        $pauseResumeBtn.prop('disabled', true);
        
        // The confirmation dialog will appear after current operation completes
    });

    // Helper function to format bytes (mimics PHP webpicr_format_bytes)
    function formatBytes(bytes, decimals = 2) {
        bytes = parseInt(bytes) || 0;
        if (bytes <= 0) return '0 Bytes';
        
        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
        const factor = Math.floor((bytes.toString().length - 1) / 3);
        const safeFactor = Math.min(factor, sizes.length - 1);
        
        const result = bytes / Math.pow(1024, safeFactor);
        return parseFloat(result.toFixed(decimals)) + ' ' + sizes[safeFactor];
    }
    
    // Update total savings display
    function updateTotalSavingsDisplay(totalBytes) {
        const formatted = formatBytes(totalBytes);
        $totalSavingsCount.text(formatted);
        // Also update the global variable so other parts can access it
        webpicr_bulk_all_vars.webpicrFormattedSavings = formatted;
    }
    
    // Update total converted count display
    function updateTotalConvertedDisplay(totalCount) {
        $successCount.text(totalCount);
    }

    // Update progress display
    function updateBulkAllProgress() {
        const totalProcessed = bulkAllProcessed + bulkAllSkipped + bulkAllFailed;
        const percent = bulkAllTotal > 0 ? Math.round((totalProcessed / bulkAllTotal) * 100) : 0;
        
        // Debug logging for progress tracking
        console.log('Progress Debug - totalProcessed:', totalProcessed, 'bulkAllTotal:', bulkAllTotal);
        
        $progressBar.css('width', percent + '%');
        $progressOverlay.text(percent + '%');
        $successCount.text(bulkAllProcessed);
        $skippedCount.text(bulkAllSkipped);
        $failedCount.text(bulkAllFailed);
        
        if (bulkAllQueue.length === 0 && totalProcessed === bulkAllTotal) {
            // Only show completion message when we've actually processed all original items
            // Create a more accurate completion message
            let completionMessage = `✅ Bulk optimization complete! `;
            if (bulkAllProcessed > 0 || bulkAllSkipped > 0 || bulkAllFailed > 0) {
                const parts = [];
                if (bulkAllProcessed > 0) parts.push(`${bulkAllProcessed} converted`);
                if (bulkAllSkipped > 0) parts.push(`${bulkAllSkipped} skipped`);
                if (bulkAllFailed > 0) parts.push(`${bulkAllFailed} failed`);
                completionMessage += parts.join(', ') + ` (${totalProcessed} total).`;
            } else {
                completionMessage += `${totalProcessed} images processed.`;
            }
            
            $progressText.text(completionMessage);
            $pauseResumeBtn.prop('disabled', true);
            $cancelBtn.text('Close');
            localStorage.removeItem(stateKey); // Clear saved state
            
            // Refresh statistics after bulk conversion completes
            refreshStatisticsAfterBulk();
        } else if (bulkAllCanceling) {
            $progressText.text(`🛑 Finishing current conversion`);
        } else if (bulkAllPaused) {
            $progressText.text(`⏸️ Paused - ${totalProcessed} of ${bulkAllTotal} processed`);
        } else {
            $progressText.text(`🔄 Processing ${totalProcessed + 1} of ${bulkAllTotal}...`);
        }
    }

    // Save progress state
    function saveProgressState() {
        const state = {
            remainingIds: bulkAllQueue,
            processed: bulkAllProcessed,
            skipped: bulkAllSkipped,
            failed: bulkAllFailed,
            originalQueueSize: bulkAllTotal, // Track original queue size to detect new operations
            timestamp: Date.now()
        };
        localStorage.setItem(stateKey, JSON.stringify(state));
    }

    // Process individual items
    function processNextBulkAllItem() {
        if (bulkAllPaused || bulkAllQueue.length === 0) {
            updateBulkAllProgress();
            
            // Check if we're canceling and this was the last operation
            if (bulkAllCanceling) {
                completeCancellation();
            }
            return;
        }

        const attachmentId = bulkAllQueue.shift();
        updateBulkAllProgress();
        saveProgressState();

        // Get the correct nonce for this attachment
        const attachmentNonce = bulkAllNonces[attachmentId];
        if (!attachmentNonce) {
            console.error(`No nonce found for attachment ${attachmentId}, skipping`);
            bulkAllSkipped++;
            if (!bulkAllPaused && bulkAllQueue.length > 0) {
                setTimeout(processNextBulkAllItem, 10); // No delay for skipped items
            }
            return;
        }

        // Smart delay variable (accessible to all callbacks)
        let nextDelay = 100; // Default delay
        
        // Make AJAX request
        $.ajax({
            url: webpicr_bulk_all_vars.ajaxurl,
            type: 'POST',
            data: {
                action: 'webpicr_convert_image_to_webp',
                attachment_id: attachmentId,
                webpicr_nonce: attachmentNonce
            },
            dataType: 'json',
            timeout: 300000 // 5 minute timeout for large images (matches single/bulk conversions)
        })
        .done(function(response) {
            
            if (response.success) {
                bulkAllProcessed++;
                
                // Smart delay based on file size - smaller files get faster processing
                if (response.data && response.data.main_original_size !== undefined) {
                    const fileSizeMB = response.data.main_original_size / (1024 * 1024);
                    if (fileSizeMB > 1.2) {
                        nextDelay = 200; // Larger files need slightly more time for server recovery
                    } else {
                        nextDelay = 50;  // Smaller files can be processed faster
                    }
                }
                
                // Update total savings from server response if available
                if (response.data && response.data.total_saved_bytes !== undefined) {
                    // Format the bytes on the frontend (we can add a helper function if needed)
                    bulkAllCurrentSavings = response.data.total_saved_bytes;
                    updateTotalSavingsDisplay(bulkAllCurrentSavings);
                }
                
                // Update the total success count from server if available
                if (response.data && response.data.total_converted_count !== undefined) {
                    updateTotalConvertedDisplay(response.data.total_converted_count);
                }
            } else {
                bulkAllSkipped++;
                // Failed/skipped items can be processed immediately
                nextDelay = 10;
            }
        })
        .fail(function(xhr, status, error) {
            console.error(`Bulk All: Failed to process attachment ${attachmentId}: ${status} - ${error}. HTTP Status: ${xhr.status}`);
            
            // Check if it's a timeout - might have succeeded anyway
            if (status === 'timeout') {
                console.log(`[WEBPICR Bulk All] Timeout for attachment ${attachmentId}, checking if it completed...`);
                
                // Check conversion status without blocking the queue
                $.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: {
                        action: 'webpicr_check_conversion_status',
                        attachment_id: attachmentId,
                        nonce: webpicr_status_check_nonce
                    },
                    timeout: 10000,
                    dataType: 'json'
                })
                .done(function(response) {
                    if (response.success && response.data.converted) {
                        console.log(`[WEBPICR Bulk All] Attachment ${attachmentId} actually succeeded!`);
                        // Decrement failed count and increment processed
                        bulkAllFailed--;
                        bulkAllProcessed++;
                        updateBulkAllProgress();
                    } else {
                        console.log(`[WEBPICR Bulk All] Attachment ${attachmentId} genuinely timed out`);
                    }
                });
                
                bulkAllFailed++;
                nextDelay = 500; // Slight delay after timeout
            } else {
                // Log specific errors to help troubleshoot
                if (xhr.status === 403) {
                    console.error(`403 Forbidden for attachment ${attachmentId}. Check nonce: ${attachmentNonce}`);
                } else if (xhr.status === 0) {
                    console.error(`Network error for attachment ${attachmentId}. This could be due to network changes, server restart, or timeout.`);
                    
                    // For network errors, consider pausing the process to avoid overwhelming the server
                    if (status === 'error' && error === '') {
                        console.warn('Network connection issue detected. You may want to pause and check your connection.');
                    }
                }
                
                bulkAllFailed++;
                nextDelay = 10; // Failed requests can move quickly to next item
            }
        })
        .always(function() {
            updateBulkAllProgress();
            saveProgressState();
            
            // Continue with next item using smart delay, or complete cancellation
            if (bulkAllCanceling) {
                completeCancellation();
            } else if (!bulkAllPaused && bulkAllQueue.length > 0) {
                setTimeout(processNextBulkAllItem, nextDelay); // Smart delay: 50ms small files, 200ms large files, 10ms failed/skipped
            }
        });
    }

    // Complete graceful cancellation after current operation finishes
    function completeCancellation() {
        console.log('Current operation finished, showing cancellation confirmation...');
        
        // Now show confirmation dialog after current operation is complete
        if (confirm('Current image conversion finished. Are you sure you want to cancel the bulk optimization? All progress will be lost and you will need to start over.')) {
            // User confirmed - proceed with cancellation
            console.log('User confirmed cancellation, clearing state and refreshing...');
            
            // Clear saved state completely
            localStorage.removeItem(stateKey);
            
            // Set a flag to indicate we explicitly canceled (not just paused)
            localStorage.setItem('webpicr_bulk_all_canceled', Date.now());
            
            // Refresh the page to reset everything cleanly
            window.location.reload();
        } else {
            // User canceled the cancellation - resume operation
            console.log('User canceled the cancellation, resuming...');
            
            bulkAllCanceling = false;
            bulkAllPaused = false; // Resume processing
            
            // Restore button states
            $cancelBtn.text('Cancel').prop('disabled', false);
            $pauseResumeBtn.text('Pause').prop('disabled', false);
            
            // Continue processing if there are items left
            if (bulkAllQueue.length > 0) {
                processNextBulkAllItem();
            }
        }
    }

    // Initialize total savings display
    if (webpicr_bulk_all_vars.webpicrFormattedSavings) {
        $totalSavingsCount.text(webpicr_bulk_all_vars.webpicrFormattedSavings);
    }
    
    // Initialize success count with current total converted count
    if (webpicr_bulk_all_vars.webpicrCurrentConvertedCount !== undefined) {
        $successCount.text(webpicr_bulk_all_vars.webpicrCurrentConvertedCount);
    }

    // Start processing
    updateBulkAllProgress();
    if (bulkAllQueue.length > 0) {
        processNextBulkAllItem();
    }
    }

    // Function to refresh statistics after bulk conversion completes
    function refreshStatisticsAfterBulk() {
        // Call the AJAX endpoint to refresh statistics
        $.post(ajaxurl, {
            action: 'webpicr_refresh_statistics',
            nonce: window.webpicrRefreshStatsNonce || ''
        })
        .done(function(response) {
            if (response.success) {
                // Force a page reload after 2 seconds to show the updated statistics
                setTimeout(function() {
                    window.location.reload();
                }, 2000);
            } else {
                console.warn('Statistics refresh failed:', response.data ? response.data.message : 'Unknown error');
            }
        })
        .fail(function(xhr, status, error) {
            console.error('Statistics refresh AJAX error:', status, error);
        });
    }

    // Fix WebP MIME Types button handler
    $('#webpicr-fix-mime-types-btn').on('click', function(e) {
        e.preventDefault();
        
        var $button = $(this);
        var $result = $('#webpicr-fix-mime-types-result');
        
        // Disable button and show loading state
        $button.prop('disabled', true).text('Fixing...');
        $result.html('<span style="color: #666;">⏳ Processing...</span>');
        
        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'webpicr_fix_mime_types',
                nonce: webpicr_fix_mime_types_nonce
            },
            success: function(response) {
                if (response.success) {
                    $result.html('<span style="color: #0a7f0a;">✅ ' + response.data.message + '</span>');
                    
                    // Hide the entire utility box after 2 seconds
                    setTimeout(function() {
                        $('.webpicr-fix-mime-types').fadeOut(300, function() {
                            $(this).remove();
                        });
                    }, 2000);
                } else {
                    $result.html('<span style="color: #d63638;">❌ ' + (response.data.message || 'Failed to fix MIME types.') + '</span>');
                    $button.prop('disabled', false).text('Try Again');
                }
            },
            error: function(xhr, status, error) {
                console.error('Fix MIME types error:', status, error);
                $result.html('<span style="color: #d63638;">❌ AJAX Error</span>');
                $button.prop('disabled', false).text('Try Again');
            }
        });
    });

});