/**
 * Processing Module
 * Handles task scheduling and processing
 */
(function($, rank) {
    'use strict';

    if (typeof rank_ajax_obj === 'undefined' || !rank_ajax_obj) {
        console.error('RANK Critical Error: rank_ajax_obj is not defined in processing.js. Script will halt.');
        // Optionally, try to alert or display a message on the page if console is not open
        // alert('RANK Plugin Critical Error: Essential configuration (rank_ajax_obj) missing. Please contact support or check browser console.');
        return; // Stop execution of this IIFE if critical object is missing
    }
    
    // Helper function to extract filename from URL path
    function basename(url) {
        if (!url) return '';
        // Extract the filename from the URL
        return url.split('/').pop().split('#')[0].split('?')[0];
    }
    
    // Schedule all tasks for processing
    function scheduleAllTasks() {
        rank.elements.startButton.prop('disabled', true).hide();
        rank.elements.statusMessage.text(rank_ajax_obj.status_scheduling || 'Scheduling tasks...');
        rank.helpers.addLogMessage('Scheduling all tasks for processing...');
        
        rank.helpers.trackAjaxRequest($.ajax({
            url: rank_ajax_obj.ajax_url,
            type: 'POST',
            data: {
                action: 'rank_schedule_tasks',
                nonce: rank_ajax_obj.nonce,
                batch_id: rank.state.batchId
            },
            dataType: 'json',
            success: function(response) {
                if (response.success) {
                    rank.helpers.addLogMessage('All tasks scheduled successfully: ' + response.data.message);
                    rank.helpers.showNotice('Tasks scheduled. Processing will begin shortly.', 'success');
                    rank.elements.statusMessage.text('Monitoring progress...');
                    
                    // Start polling for status updates
                    startStatusPolling();
                } else {
                    rank.helpers.showNotice((rank_ajax_obj.error_scheduling || 'Error scheduling tasks.') + ' ' + (response.data || ''), 'error');
                    rank.helpers.addLogMessage('Error scheduling tasks: ' + (response.data || 'Unknown error'));
                    rank.elements.startButton.prop('disabled', false).show();
                }
            },
            error: function(jqXHR, textStatus, errorThrown) {
                // If the request was aborted, handle silently
                if (textStatus === 'abort') {
                    return; // Exit silently without showing error message
                }
                
                rank.helpers.showNotice((rank_ajax_obj.error_scheduling || 'Error scheduling tasks.') + ` (AJAX Error: ${textStatus})`, 'error');
                rank.helpers.addLogMessage(`AJAX Error during scheduling: ${textStatus} - ${errorThrown}`);
                rank.elements.startButton.prop('disabled', false).show();
            }
        }));
    }
    
    // Start polling for status updates
    function startStatusPolling() {
        // This function is a placeholder for future implementation
        console.log('Status polling started');
    }
    
    // Reset all processing state
    function resetProcessingState() {
        // Reset state variables
        rank.state.isAutoProcessingActive = false;
        rank.state.autoApproveFlag = false;
        rank.state.autoProcessActionCompleted = false;
        rank.state.processedCount = 0;
        rank.state.is_continuation = false; // Initialize the continuation flag
        
        // Reset UI elements
        if (rank.elements.progressBarContainer) {
            rank.elements.progressBarContainer.hide();
        }
        
        if (rank.elements.approvalArea) {
            rank.elements.approvalArea.empty().hide();
        }
        
        // Hide processing area and show health issues
        if (rank.elements.processingArea) {
            rank.elements.processingArea.hide();
        }
        
        if (rank.elements.healthIssuesContainer) {
            rank.elements.healthIssuesContainer.show();
        }
        
        // Reset buttons
        if (rank.elements.startButton) {
            rank.elements.startButton.prop('disabled', false).show();
        }
        
        if (rank.elements.autoProcessButton) {
            rank.elements.autoProcessButton
                .removeClass('button-secondary')
                .addClass('button-primary')
                .show();
        }
        
        // Hide spinner and log container
        $('#rank-log-spinner').removeClass('is-active').hide();
        $('.rank-log-container').hide();
        
        // Reset cancel button to normal state
        if (rank.elements.cancelBtn) {
            rank.elements.cancelBtn.removeClass('cancelling').text('Cancel').prop('disabled', false);
        }
        
        // Clear localStorage flags
        localStorage.removeItem('rank_review_started');
        localStorage.setItem('rank_auto_approve', '0');
        
        // Add log message
        rank.helpers.addLogMessage('Processing state has been completely reset.');
    }
    
    // Start manual review process
    function startManualReview() {
        rank.state.processedCount = 0;
        rank.elements.startButton.hide();
        rank.elements.autoProcessButton.hide();
        
        // Remove the "View all pages" link immediately
        if (rank.urlListModal && typeof rank.urlListModal.removeViewUrlsButton === 'function') {
            rank.urlListModal.removeViewUrlsButton();
        }
        
        // Show and initialize progress bar with animation
        rank.elements.progressBarContainer.show();
        rank.helpers.updateProgressBar(0);
        
        // Get the health issue name based on the current issue type
        let healthIssueName = '';
        if (rank.state.issueType && window.rankLocalizedData && window.rankLocalizedData.healthCheckCategories && window.rankLocalizedData.healthCheckCategories[rank.state.issueType]) {
            healthIssueName = window.rankLocalizedData.healthCheckCategories[rank.state.issueType] + ': ';
        }
        
        // Update status message to show review progress
        rank.elements.statusMessage.text(`Review: 1 of ${rank.state.totalCount}`);
        
        // Update counts display with health issue name
        const alreadyFixedSuffix = rank.state.alreadyFixedCount > 0
            ? ` (<span style="color: #28a745 !important;">${rank.state.alreadyFixedCount}</span> already fixed<span class="rank-inline-tooltip" data-tooltip="${rankLocalizedData.tooltip_already_fixed}">❓</span>)`
            : '';
        rank.elements.counts.html(`${healthIssueName}${rank_ajax_obj.text_decide_label || 'Processed'}: <span style="color: #dc3545 !important;">1</span> of <span style="color: #dc3545 !important;">${rank.state.totalCount}</span>${alreadyFixedSuffix}`);
        
        // Show loading placeholder immediately before fetching the first item
        if (rank.elements.approvalArea) {
            rank.elements.approvalArea.empty().append(`
                <div class="rank-approval-row">
                    <div class="rank-loading-placeholder">Loading... 5-15 seconds</div>
                </div>
            `).show();
        }
        
        // Hide the spinner for manual processing (we have the loading placeholder now)
        $('#rank-log-spinner').removeClass('is-active').hide();
        
        // Get the first item
        fetchNextRow();
    }
    
    // Helper to extract solution for auto-approval
    function _getSolutionForAutoApproval(solutionData) {
        // Handle array with object inside (most common case from logs)
        if (Array.isArray(solutionData) && solutionData.length > 0) {
            const firstItem = solutionData[0];
            if (typeof firstItem === 'string') {
                return firstItem;
            } else if (firstItem && typeof firstItem === 'object') {
                // If it has solution_value property, use that
                if (firstItem.solution_value) {
                    return firstItem.solution_value;
                }
                // Otherwise try to stringify it
                return JSON.stringify(firstItem);
            }
            return String(firstItem);
        }
        // Handle string
        else if (typeof solutionData === 'string') {
            return solutionData;
        }
        // Handle object
        else if (solutionData && typeof solutionData === 'object') {
            if (solutionData.solution_value) {
                return solutionData.solution_value;
            }
            return JSON.stringify(solutionData);
        }
        
        return ''; // Default to empty if no suitable solution
    }
    
    // Helper to extract URLs from issue_data
    function _extractUrlsFromIssueData(issue_data, api_issue_type) {
        let page_url = null;
        let item_url = null;
        
        if (!issue_data) {
            return { page_url, item_url, missing_data: true, missing_page_url: true };
        }
        
        // Try to extract page_url from different possible structures
        if (issue_data.page_url) {
            page_url = issue_data.page_url;
        } else if (issue_data.page && issue_data.page.path_full) {
            page_url = issue_data.page.path_full;
        } else if (issue_data.page && issue_data.page.path) {
            // Try to construct a full URL from the path
            const site_url = window.location.origin;
            const path = issue_data.page.path.startsWith('/') ? issue_data.page.path.substring(1) : issue_data.page.path;
            page_url = site_url + '/' + path;
        }
        
        // Extract item_url based on issue type
        if (api_issue_type === 'missing_alt_tags' && issue_data.image_url) {
            item_url = issue_data.image_url;
        } else if (api_issue_type === 'missing_alt_tags' && issue_data.issue_identifier) {
            // For missing_alt_tags, the issue_identifier is often the image URL
            item_url = issue_data.issue_identifier;
        } else if (issue_data.issue_identifier && issue_data.issue_identifier.includes('://')) {
            // If issue_identifier looks like a URL, use it as item_url
            item_url = issue_data.issue_identifier;
        }
        
        // Add other conditions for item_url if different issue types have specific item URLs in issue_data
        
        // Flag if page_url is missing
        const missing_page_url = !page_url;
        
        // Log if page_url is missing for debugging
        if (missing_page_url) {
            console.warn('Missing page_url in issue_data:', issue_data);
        }
        
        return { page_url, item_url, missing_page_url };
    }
    
    // Helper to update counts and progress bar
    function _updateCountsAndProgressOnFetch(responseData, isManualListItem) {
        // Use processedCount directly from response data if available, otherwise fall back to decisions count
        rank.state.processedCount = responseData.processedCount !== undefined ?
            responseData.processedCount :
            (responseData.decisions ? Object.keys(responseData.decisions).length : 0);
        
        // Only update totalCount from server if we haven't already filtered out "already fixed" items
        // When alreadyFixedCount > 0, we've already set the correct filtered totalCount and should NOT
        // let the server overwrite it (server doesn't track the pre-filtering removal count)
        if (!rank.state.alreadyFixedCount || rank.state.alreadyFixedCount === 0) {
            rank.state.totalCount = responseData.totalCount || rank.state.totalCount;
        }
        
        // Calculate the number of processed items for progress display
        const itemsProcessedOrListed = rank.state.processedCount;
        
        // Progress bar shows completed items (0%, 25%, 50%, etc.)
        const pct = rank.state.totalCount > 0 ? Math.round((itemsProcessedOrListed / rank.state.totalCount) * 100) : 0;
        rank.helpers.updateProgressBar(pct);

        // Display count shows current item being processed (1 of 4, 2 of 4, etc.)
        // For all modes, show the next item to be processed (processed count + 1)
        // Ensure displayCount is never less than 1
        let displayCount = Math.max(1, itemsProcessedOrListed + 1);


        // Get the health issue name based on the current issue type
        let healthIssueName = '';
        if (rank.state.issueType && window.rankLocalizedData && window.rankLocalizedData.healthCheckCategories && window.rankLocalizedData.healthCheckCategories[rank.state.issueType]) {
            healthIssueName = window.rankLocalizedData.healthCheckCategories[rank.state.issueType] + ': ';
        }

        // Update the counts display
        let countsLabel = rank_ajax_obj.text_decide_label || 'Processed';
        if (rank.state.isAutoProcessingActive && rank.state.autoApproveFlag) {
            countsLabel = 'Auto-processing';
        } else if (rank.state.isAutoProcessingActive) {
            countsLabel = 'Auto-processing';
        } else {
            countsLabel = 'Review';
        }
        const alreadyFixedSuffix = rank.state.alreadyFixedCount > 0
            ? ` (<span style="color: #28a745 !important;">${rank.state.alreadyFixedCount}</span> already fixed<span class="rank-inline-tooltip" data-tooltip="${rankLocalizedData.tooltip_already_fixed}">❓</span>)`
            : '';
        rank.elements.counts.html(`${healthIssueName}${countsLabel}: <span style="color: #dc3545 !important;">${displayCount}</span> of <span style="color: #dc3545 !important;">${rank.state.totalCount}</span>${alreadyFixedSuffix}`);
        
        // Update the status message to show progress
        
        if (rank.state.isAutoProcessingActive && rank.state.autoApproveFlag) {
            // For auto-approval mode
            rank.elements.statusMessage.text(`${healthIssueName}Auto-processing: ${displayCount} of ${rank.state.totalCount}`);
        } else if (rank.state.isAutoProcessingActive) {
            // For auto-processing but not auto-approve (shouldn't happen, but just in case)
            rank.elements.statusMessage.text(`${healthIssueName}Auto-processing: ${displayCount} of ${rank.state.totalCount}`);
        } else {
            // For manual review mode
            rank.elements.statusMessage.text(`${healthIssueName}Review: ${displayCount} of ${rank.state.totalCount}`);
        }
    }

    // Helper to handle batch completion
    function _handleBatchCompletionOnFetch(responseData) {
        // Set progress bar to 100% on completion
        rank.helpers.updateProgressBar(100);

        const completionMessage = rank.state.isAutoProcessingActive && rank.state.autoApproveFlag ?
                                 (rank_ajax_obj.status_auto_approve_complete || 'Auto-approval Complete. All items processed.') :
                                 (rank_ajax_obj.status_complete || 'Processing Complete. All items reviewed.');
        rank.helpers.showNotice(completionMessage, 'success');
        rank.helpers.addLogMessage('Automatic processing completed for all pages ✅');
        
        rank.elements.statusMessage.text(completionMessage);
        
        // Get the health issue name based on the current issue type
        let healthIssueName = '';
        if (rank.state.issueType && window.rankLocalizedData && window.rankLocalizedData.healthCheckCategories && window.rankLocalizedData.healthCheckCategories[rank.state.issueType]) {
            healthIssueName = window.rankLocalizedData.healthCheckCategories[rank.state.issueType] + ': ';
        }
        
        // Update the counts display to show "Processing Complete!" instead of "Review: X of Y"
        const alreadyFixedSuffix = rank.state.alreadyFixedCount > 0
            ? ` (<span style="color: #28a745 !important;">${rank.state.alreadyFixedCount}</span> already fixed<span class="rank-inline-tooltip" data-tooltip="${rankLocalizedData.tooltip_already_fixed}">❓</span>)`
            : '';
        rank.elements.counts.html(`${healthIssueName}Processing Complete!${alreadyFixedSuffix}`);
        
        // Add completion video below the headline
        if (rank.elements.counts && rank.elements.counts.length) {
            // Remove any existing video first (in case of multiple completions)
            $('#rank-completion-video').remove();
            
            // Create and append the video element
            // Use the plugin URL provided by WordPress
            // Since we're always in the admin area, we can simplify this code
            const pluginDirName = 'rank-ai-by-morningscore'; // The actual plugin directory name
            
            // Use WordPress-provided URL if available, otherwise use a simple admin fallback
            let pluginPath;
            
            if (rank_ajax_obj.plugin_url) {
                // Handle the case where plugin_url might already have a trailing slash
                pluginPath = rank_ajax_obj.plugin_url.endsWith('/')
                    ? rank_ajax_obj.plugin_url + 'admin/done-guide.mp4'
                    : rank_ajax_obj.plugin_url + '/admin/done-guide.mp4';
            } else {
                // Simple fallback for admin area
                pluginPath = '../wp-content/plugins/' + pluginDirName + '/admin/done-guide.mp4';
            }
                
            const $video = $('<video>', {
                id: 'rank-completion-video',
                src: pluginPath,
                autoplay: true,
                muted: true,
                playsinline: true,
                style: 'display: block; max-width: 60%; margin-top: 10px;'
            });
            
            // Disable controls and looping
            $video.prop('controls', false);
            $video.prop('loop', false);
            
            // Create "See Fixes" button
            const $seeFixesBtn = $('<button>', {
                id: 'rank-see-fixes-button',
                text: 'See Fixes',
                class: 'button button-primary',
                style: 'margin-top: 15px; margin-bottom: 20px;'
            });
            
            // Add click handler to the button
            $seeFixesBtn.on('click', function() {
                // Navigate to the fixes overview page
                window.location.href = 'admin.php?page=rank-admin&tab=bulk_fix&subtab=fixes-view';
            });
            
            // Create a container for the video and button
            const $completionContainer = $('<div>', {
                id: 'rank-completion-container',
                style: 'text-align: center;'
            });
            
            // Add the video and button to the container
            $completionContainer.append($video);
            $completionContainer.append($seeFixesBtn);
            
            // Append the container after the counts element
            rank.elements.counts.after($completionContainer);
        }
        
        if (rank.elements.cancelBtn) rank.elements.cancelBtn.hide(); // This might be autoProcessButton now
        if (rank.elements.autoProcessButton) rank.elements.autoProcessButton.hide(); // Hide stop button

        // Create and show a "Done" button instead of automatically closing the processing view
        if (rank.elements.completeClearLogBtn) {
            rank.elements.completeClearLogBtn.text(rank_ajax_obj.text_done || 'Done').show();
        }
        
        if (rank.elements.approvalArea) {
            // Keep approval area visible but empty when batch processing is complete
            rank.elements.approvalArea.empty();
        }
        
        // Keep processing area visible when batch processing is complete
        
        // Reset all state variables that affect isProcessingActive()
        rank.state.isAutoProcessingActive = false; // Reset mode
        
        // Clear localStorage flag for both manual and automatic modes
        localStorage.removeItem('rank_review_started');
        
        
        // Hide the spinner when processing is complete
        $('#rank-log-spinner').removeClass('is-active').hide();
        
    }

    // Helper to handle fetch errors
    function _handleFetchErrorOrUnexpected(response) {
        console.warn('Request successful but data indicates an issue or unexpected structure.');
        const errorMessage = (response && response.data && response.data.message) ? response.data.message : (rank_ajax_obj.error_fetching_item || 'Error fetching next item or unexpected response.');
        
        // Store current auto-processing state before showing error
        const wasAutoProcessing = rank.state.isAutoProcessingActive;
        const wasAutoApproving = rank.state.autoApproveFlag;
        
        // Check if this is a recoverable error that we should retry
        const isRecoverableError = errorMessage.includes('No data found for resource') ||
                                  errorMessage.includes('resource with given identifier') ||
                                  errorMessage.includes('unexpected response') ||
                                  errorMessage.includes('batch not found');
        
        if (isRecoverableError && wasAutoProcessing) {
            // For recoverable errors during auto-processing, show warning and attempt to continue
            rank.helpers.showNotice(`${errorMessage}. Attempting to skip and continue...`, 'warning');
            rank.helpers.addLogMessage(`⚠️ Recoverable error: ${errorMessage}. Skipping and continuing...`);
            
            // Mark current item as skipped if we have a row key
            if (rank.state.currentRowKey) {
                $.ajax({
                    url: rank_ajax_obj.ajax_url,
                    type: 'POST',
                    data: {
                        action: 'rank_record_decision',
                        nonce: rank_ajax_obj.nonce,
                        batchId: rank.state.batchId,
                        rowKey: rank.state.currentRowKey,
                        approved: false,
                        skip_reason: 'fetch_error'
                    },
                    dataType: 'json'
                }).always(function() {
                    // Clear current row key and continue
                    rank.state.currentRowKey = null;
                    
                    setTimeout(function() {
                        // Restore auto-processing state and continue
                        rank.state.isAutoProcessingActive = wasAutoProcessing;
                        rank.state.autoApproveFlag = wasAutoApproving;
                        
                        if (wasAutoProcessing) {
                            rank.helpers.addLogMessage('Resuming auto-processing after recoverable error...');
                            fetchNextRow();
                        }
                    }, 1500);
                });
            } else {
                // No current row key, just wait and continue
                setTimeout(function() {
                    rank.state.isAutoProcessingActive = wasAutoProcessing;
                    rank.state.autoApproveFlag = wasAutoApproving;
                    
                    if (wasAutoProcessing) {
                        rank.helpers.addLogMessage('Resuming auto-processing after recoverable error...');
                        fetchNextRow();
                    }
                }, 1500);
            }
        } else {
            // For non-recoverable errors or manual mode, stop processing
            rank.helpers.showNotice(errorMessage, 'error');
            rank.helpers.addLogMessage('Error fetching next item: ' + errorMessage);
            if (rank.elements.healthIssuesContainer) rank.elements.healthIssuesContainer.show();
            if (rank.elements.processingArea) rank.elements.processingArea.hide();
            if (rank.elements.autoProcessButton) { // Show auto process button again
                rank.elements.autoProcessButton.show();
            }
            
            // Hide the spinner when there's an error
            $('#rank-log-spinner').removeClass('is-active').hide();
            
            rank.state.isAutoProcessingActive = false; // Reset mode
        }
    }


    // Fetch the next row for review (modified to be a central loop)
    function fetchNextRow() {
        
        // Prevent infinite loop when processing is canceled but fetchNextRow is called by a completing action
        if (rank.state.isAutoProcessingActive === false &&
            rank.state.autoProcessActionCompleted === true && // A flag to indicate we just finished an auto-process action
            !$('#rank-approval-area .rank-approval-row').length // And no new manual item is up
           ) {
           rank.state.autoProcessActionCompleted = false; // Reset flag
           return;
        }
        // Ensure autoProcessActionCompleted is initialized if not present
        if (typeof rank.state.autoProcessActionCompleted === 'undefined') {
            rank.state.autoProcessActionCompleted = false;
        }

        // Check if we have a valid batch ID
        if (!rank.state.batchId) {
            console.error('RANK ERROR: Aborting fetchNextRow, batchId is missing.');
            rank.helpers.showNotice('Error: Batch ID is missing, cannot fetch next item.', 'error');
            if (rank.elements.healthIssuesContainer) rank.elements.healthIssuesContainer.show();
            if (rank.elements.processingArea) rank.elements.processingArea.hide();
            return;
        }
        
        // Check if we have a valid issue type
        if (!rank.state.issueType) {
            console.error('RANK ERROR: Aborting fetchNextRow, issueType is missing.');
            rank.helpers.showNotice('Error: Issue type is missing, cannot fetch next item.', 'error');
            if (rank.elements.healthIssuesContainer) rank.elements.healthIssuesContainer.show();
            if (rank.elements.processingArea) rank.elements.processingArea.hide();
            return;
        }
        
        // Check if we have items to process
        if (rank.state.totalCount !== undefined && rank.state.totalCount <= 0) {
            // If we're in auto-processing mode, show completion message
            if (rank.state.isAutoProcessingActive) {
                rank.helpers.addLogMessage('No issues to process. Automatic processing completed.');
                if (rank.elements.statusMessage) {
                    rank.elements.statusMessage.text('Automatic processing completed for all pages ✅');
                }
                
                // Reset processing flags
                rank.state.isAutoProcessingActive = false;
                rank.state.autoApproveFlag = false;
                
                // Hide the spinner
                $('#rank-log-spinner').removeClass('is-active').hide();
            }
            
            return;
        }

        rank.helpers.trackAjaxRequest($.ajax({
            url: rank_ajax_obj.ajax_url,
            type: 'POST',
            data: {
                action: 'rank_get_batch_state',
                nonce: rank_ajax_obj.nonce,
                batchId: rank.state.batchId,
                is_continuation: rank.state.is_continuation === true ? 'true' : 'false'
            },
            dataType: 'json',
            success: function(response) {

                // Process UI logs and check for API errors
                let hasApiError = false;
                let apiErrorItem = null;
                let creditsExhaustedInLogs = false;
                
                if (response && response.data && response.data.ui_logs && Array.isArray(response.data.ui_logs)) {
                    // Process all logs and check for API errors
                    response.data.ui_logs.forEach(logMessage => {
                        if (typeof logMessage === 'string') {
                            // Check for credits exhausted message
                            if (logMessage.includes('⚠️ AI Credits Exhausted')) {
                                rank.helpers.addLogMessage(logMessage);
                                creditsExhaustedInLogs = true;
                                return; // Stop processing this batch of logs
                            }
                            // Check for API errors
                            else if (logMessage.includes('🐞 Error:')) {
                                const errorMatch = logMessage.match(/🐞 Error: (.*?) on \/(.*?): (.*)/);
                                
                                if (errorMatch && errorMatch.length >= 4) {
                                    const itemName = errorMatch[1];
                                    const pagePath = errorMatch[2];
                                    const errorMsg = errorMatch[3];
                                    
                                    // Format and display the error message
                                    rank.helpers.addLogMessage(`🐞 Error: ${itemName} on /${pagePath}: ${errorMsg}`);
                                    
                                    // Check for specific API errors
                                    if (errorMsg.includes('RANK AI could not find a fix.') ||
                                        errorMsg.includes('Too many requests') ||
                                        errorMsg.includes('Status code: 429')) {
                                        hasApiError = true;
                                        apiErrorItem = itemName;
                                    }
                                } else {
                                    // If we can't parse it, just show the original message
                                    rank.helpers.addLogMessage(logMessage);
                                }
                            }
                            // Handle URL validation logs
                            else if (logMessage.includes('🐞 Skipping URL as it does not exist on our website:')) {
                                const urlMatch = logMessage.match(/Skipping URL as it does not exist on our website: (.+)/);
                                const url = urlMatch && urlMatch[1] ? urlMatch[1] : 'unknown URL';
                                rank.helpers.addLogMessage(`🐞 URL to fix does not exist on our website: ${url}`);
                            }
                            else if (logMessage.includes('Skipping URL as it redirects:')) {
                                const urlMatch = logMessage.match(/Skipping URL as it redirects to another location: (.+)/);
                                const url = urlMatch && urlMatch[1] ? urlMatch[1] : 'unknown URL';
                                rank.helpers.addLogMessage(`🔄 URL to fix redirects to another location: ${url}`);
                            }
                            else {
                                // Add other log messages to the UI
                                rank.helpers.addLogMessage(logMessage);
                            }
                        }
                    });
                }

                // Handle credits exhausted detected in logs
                if (creditsExhaustedInLogs) {
                    // Stop processing immediately
                    rank.state.isAutoProcessingActive = false;
                    rank.state.autoApproveFlag = false;
                    rank.helpers.addLogMessage('Queue stopped. No more AI credits.');
                    rank.elements.statusMessage.text('Queue stopped. No more AI credits.');
                    $('#rank-log-spinner').removeClass('is-active').hide();
                    
                    if (rank.elements.cancelBtn) {
                        rank.elements.cancelBtn.show().text('Cancel');
                    }
                    
                    return; // Stop processing completely
                }

                // Handle API errors detected in logs
                if (hasApiError && rank.state.currentRowKey) {
                    rank.helpers.addLogMessage(`Detected API error for ${apiErrorItem}. Skipping this item...`);
                    
                    // Mark this item as skipped
                    $.ajax({
                        url: rank_ajax_obj.ajax_url,
                        type: 'POST',
                        data: {
                            action: 'rank_record_decision',
                            nonce: rank_ajax_obj.nonce,
                            batchId: rank.state.batchId,
                            rowKey: rank.state.currentRowKey,
                            approved: false,
                            skip_reason: 'api_error'
                        },
                        dataType: 'json',
                        complete: function() {
                            // Clear current row key to prevent processing it again
                            rank.state.currentRowKey = null;
                            
                            // Wait a moment before continuing to the next item
                            setTimeout(function() {
                                if (rank.state.isAutoProcessingActive) {
                                    fetchNextRow();
                                }
                            }, 1000);
                        }
                    });
                    
                    return; // Skip normal processing
                }
                
                if (response && response.success && response.data) {
                    // Check if credits are exhausted - STOP the queue
                    if (response.data.status === 'out_of_credits' && !creditsExhaustedInLogs) {
                        // Stop the processing queue (only if not already handled by UI logs)
                        rank.state.isAutoProcessingActive = false;
                        rank.state.autoApproveFlag = false;
                        
                        // Add final log message
                        rank.helpers.addLogMessage('Queue stopped. No more AI credits.');
                        
                        // Update status message
                        rank.elements.statusMessage.text('Queue stopped. No more AI credits.');
                        
                        // Hide the spinner
                        $('#rank-log-spinner').removeClass('is-active').hide();
                        
                        // Show cancel button so user can close the window
                        if (rank.elements.cancelBtn) {
                            rank.elements.cancelBtn.show().text('Cancel');
                        }
                        
                        // Don't continue processing - just return
                        return;
                    }
                    
                    if (response.data.nextRow) {
                        const nextRowData = response.data.nextRow;
                        
                        // Store the current row key for error handling
                        if (nextRowData.rowKey) {
                            rank.state.currentRowKey = nextRowData.rowKey;
                        }
                        
                        // Ensure progress bar is visible during processing
                        if (rank.elements.progressBarContainer && !rank.elements.progressBarContainer.is(':visible')) {
                            rank.elements.progressBarContainer.show();
                        }
                        
                        // Update credits counter if available in the response
                        if (response.data.credits) {
                            const $globalCreditStatusArea = $('#rank-global-credit-status');
                            if ($globalCreditStatusArea.length) {
                                $globalCreditStatusArea.text(`AI Credits left: ${response.data.credits.remaining} / ${response.data.credits.total}`);
                            }
                        }
                        
                        _updateCountsAndProgressOnFetch(response.data, false); // Update counts first

                        // Check if this is a continuation row that should be skipped for auto-approval
                        if (nextRowData.issue_data && nextRowData.issue_data.skip_auto_approve === true) {
                            // This is a continuation row, just fetch the next row without approving
                            rank.state.is_continuation = true; // Set the flag for the next request
                            fetchNextRow();
                            return;
                        } else {
                            rank.state.is_continuation = false; // Reset the flag
                            // Continue with normal processing below
                        }
                        
                        if (rank.state.isAutoProcessingActive && rank.state.autoApproveFlag) {
                            // Batch Auto-Approval Mode
                            let solutionToApprove = _getSolutionForAutoApproval(nextRowData.solution);
                            const { page_url, item_url, missing_page_url } = _extractUrlsFromIssueData(nextRowData.issue_data, rank.state.issueType);
                            
                            // Check if still in auto-processing mode before approving (user might have clicked stop)
                            if (!rank.state.isAutoProcessingActive) {
                                rank.helpers.addLogMessage('Auto-processing stopped. Item not auto-approved.');
                                // Potentially show the item for manual review or reset UI
                                rank.approval.renderApprovalRow(nextRowData); // Show the item that wasn't auto-approved
                                return;
                            }
                            
                            // Check if page_url is missing and handle accordingly
                            if (missing_page_url) {
                                // Log the issue
                                const itemDesc = item_url && typeof item_url === 'string' ? basename(item_url) : nextRowData.rowKey;
                                rank.helpers.addLogMessage(`⚠️ Skipping item ${itemDesc} due to missing page URL. Continuing with next item...`);
                                
                                // Mark this item as skipped in batch data
                                const skipDecisionData = {
                                    action: 'rank_record_decision',
                                    nonce: rank_ajax_obj.nonce,
                                    batchId: rank.state.batchId,
                                    rowKey: nextRowData.rowKey,
                                    approved: false,
                                    solution: 'Skipped due to missing page URL',
                                    api_issue_type: rank.state.issueType,
                                    skip_reason: 'missing_page_url'
                                };
                                
                                // Make a silent AJAX call to mark as skipped
                                $.ajax({
                                    url: rank_ajax_obj.ajax_url,
                                    type: 'POST',
                                    data: skipDecisionData,
                                    dataType: 'json',
                                    success: function() {
                                        // Continue with next item regardless of result
                                        fetchNextRow();
                                    },
                                    error: function() {
                                        // Continue with next item even if error
                                        fetchNextRow();
                                    }
                                });
                                
                                return; // Skip current item
                            }
                            
                            // Store the current row data for URL extraction in handleDecisionResponse
                            if (rank.state) {
                                rank.state.currentRowData = nextRowData;
                            }
                            
                            rank.approval.approveItem(nextRowData.rowKey, solutionToApprove, page_url, item_url, rank.state.issueType);
                            // approveItem will call fetchNextRow again, continuing the loop.
                        } else {
                            // Standard Manual One-by-One Mode (or first item before auto-process mode fully kicks in)
                            rank.approval.renderApprovalRow(nextRowData);
                        }
                    } else {
                        // No nextRow: Batch complete
                        _updateCountsAndProgressOnFetch(response.data, false); // Ensure counts are final
                        _handleBatchCompletionOnFetch(response.data);
                    }
                } else {
                    // Default error handling for other cases
                    _handleFetchErrorOrUnexpected(response);
                }
            },
            error: function(jqXHR, textStatus, errorThrown) {
                // If the request was aborted, handle silently
                if (textStatus === 'abort') {
                    return; // Exit silently without showing error message
                }
                
                // Store current auto-processing state
                const wasAutoProcessing = rank.state.isAutoProcessingActive;
                const wasAutoApproving = rank.state.autoApproveFlag;
                
                // Check specifically for 504 Gateway Timeout errors
                if (jqXHR.status === 504) {
                    console.error('Server timeout (504) error fetching next item.');
                    
                    // Show a friendly error message
                    rank.helpers.showNotice('Error. Your server timed out. Attempting to continue processing...', 'warning');
                    
                    // Log the timeout error
                    rank.helpers.addLogMessage('⚠️ Server timeout (504) error during processing. Attempting to continue...');
                } else if (jqXHR.status === 400) {
                    // Handle 400 Bad Request errors - likely missing page URL or other validation issue
                    console.error('Bad request (400) error fetching next item:', jqXHR.responseText);
                    
                    // Show a warning message
                    rank.helpers.showNotice('Error with this item. Skipping and continuing with next item...', 'warning');
                    
                    // Log the error
                    rank.helpers.addLogMessage(`⚠️ Error with current item (400): ${errorThrown}. Skipping to next item...`);
                } else if (jqXHR.status === 404) {
                    // Handle 404 Not Found errors - resource/batch item not found
                    console.error('Resource not found (404) error fetching next item:', jqXHR.responseText);
                    
                    // Show a warning message
                    rank.helpers.showNotice('Item not found. Skipping and continuing with next item...', 'warning');
                    
                    // Log the error
                    rank.helpers.addLogMessage(`⚠️ Item not found (404): ${errorThrown}. Skipping to next item...`);
                } else if (jqXHR.status === 500) {
                    // Handle 500 Internal Server Error
                    console.error('Server error (500) fetching next item:', jqXHR.responseText);
                    
                    // Show a warning message
                    rank.helpers.showNotice('Server error encountered. Attempting to continue processing...', 'warning');
                    
                    // Log the error
                    rank.helpers.addLogMessage(`⚠️ Server error (500): ${errorThrown}. Attempting to continue...`);
                } else {
                    // Original error handling for other error types
                    console.error('AJAX error fetching next item:', jqXHR.responseText);
                    rank.helpers.showNotice(`${rank_ajax_obj.error_ajax_item || 'Error fetching item'}: ${textStatus}. Attempting to continue...`, 'warning');
                    rank.helpers.addLogMessage(`⚠️ AJAX Error: ${textStatus} - ${errorThrown}. Attempting to continue processing...`);
                }
                
                // Mark the current item as skipped in the batch data if we can identify it
                // This ensures we don't retry the same row that caused an error
                if (rank.state.currentRowKey) {
                    // Make a silent AJAX call to mark as skipped
                    $.ajax({
                        url: rank_ajax_obj.ajax_url,
                        type: 'POST',
                        data: {
                            action: 'rank_record_decision',
                            nonce: rank_ajax_obj.nonce,
                            batchId: rank.state.batchId,
                            rowKey: rank.state.currentRowKey,
                            approved: false,
                            skip_reason: 'ajax_error'
                        },
                        dataType: 'json'
                    }).always(function() {
                        // Wait a moment and then continue with the next row
                        setTimeout(function() {
                            // Restore auto-processing state
                            rank.state.isAutoProcessingActive = wasAutoProcessing;
                            rank.state.autoApproveFlag = wasAutoApproving;
                            
                            if (wasAutoProcessing) {
                                rank.helpers.addLogMessage('Resuming auto-processing with next item...');
                                // Continue with the next row
                                fetchNextRow();
                            } else {
                                // For manual mode, show UI elements again
                                if (rank.elements.autoProcessButton) {
                                    rank.elements.autoProcessButton.show();
                                }
                                
                                // Hide the spinner
                                $('#rank-log-spinner').removeClass('is-active').hide();
                            }
                        }, 2000); // Wait 2 seconds before continuing
                    });
                } else {
                    // If we don't have a current row key, just wait and continue
                    setTimeout(function() {
                        // Restore auto-processing state
                        rank.state.isAutoProcessingActive = wasAutoProcessing;
                        rank.state.autoApproveFlag = wasAutoApproving;
                        
                        if (wasAutoProcessing) {
                            rank.helpers.addLogMessage('Resuming auto-processing...');
                            // Continue with the next row
                            fetchNextRow();
                        } else {
                            // For manual mode, show UI elements again
                            if (rank.elements.autoProcessButton) {
                                rank.elements.autoProcessButton.show();
                            }
                            
                            // Hide the spinner
                            $('#rank-log-spinner').removeClass('is-active').hide();
                        }
                    }, 2000); // Wait 2 seconds before continuing
                }
            }
        }));
    }
    
    // Initialize the module
    function init() {
        // Clear processing area on page load/tab switch
        if (rank.elements.processingArea) {
            // Hide processing area when plugin is loaded or tab is switched
            rank.elements.processingArea.hide();
            if (rank.elements.healthIssuesContainer) {
                rank.elements.healthIssuesContainer.show();
            }
        }

        // Bind start button click handler
        rank.elements.startButton.on('click', function() {
            // Remove the "View all pages" link immediately
            if (rank.urlListModal && typeof rank.urlListModal.removeViewUrlsButton === 'function') {
                rank.urlListModal.removeViewUrlsButton();
            }
            
            // Make sure we have a valid batch ID
            rank.state.batchId = rank.elements.batchIdInput.val() || localStorage.getItem('rank_batch_id');
            if (!rank.state.batchId) {
                rank.helpers.showNotice(rank_ajax_obj.error_no_batch_id || 'Error: Batch ID is missing', 'error');
                return;
            }
            
            // Make sure we have a valid issue type
            if (!rank.state.issueType) {
                rank.helpers.showNotice('Error: Issue type is missing', 'error');
                return;
            }
            
            // Make sure we have items to process
            if (!rank.state.totalCount || rank.state.totalCount <= 0) {
                rank.helpers.showNotice('No issues to process', 'info');
                return;
            }
    
            // Standard Manual Processing
            rank.state.isAutoProcessingActive = false; // Explicitly set manual mode
            rank.state.autoApproveFlag = false; // Ensure auto-approve is off
            localStorage.setItem('rank_review_started', '1');
            localStorage.setItem('rank_auto_approve', '0');
            
            rank.elements.startButton.hide(); // Hide self
            if (rank.elements.autoProcessButton) rank.elements.autoProcessButton.hide(); // Hide "Automatic" button
            rank.elements.statusMessage.text(rank_ajax_obj.status_reviewing || 'Reviewing issues...');
            rank.elements.logOutput.empty();
            rank.state.processedCount = 0;
            if(rank.elements.progressBarContainer) rank.elements.progressBarContainer.show();
            rank.helpers.updateProgressBar(0);
            
            // Get the health issue name based on the current issue type
            let healthIssueName = '';
            if (rank.state.issueType && window.rankLocalizedData && window.rankLocalizedData.healthCheckCategories && window.rankLocalizedData.healthCheckCategories[rank.state.issueType]) {
                healthIssueName = window.rankLocalizedData.healthCheckCategories[rank.state.issueType] + ': ';
            }
            
            const alreadyFixedSuffix = rank.state.alreadyFixedCount > 0
                ? ` (<span style="color: #28a745 !important;">${rank.state.alreadyFixedCount}</span> already fixed<span class="rank-inline-tooltip" data-tooltip="${rankLocalizedData.tooltip_already_fixed}">❓</span>)`
                : '';
            rank.elements.counts.html(`${healthIssueName}${rank_ajax_obj.text_decide_label || 'Processed'}: <span style="color: #dc3545 !important;">1</span> of <span style="color: #dc3545 !important;">${rank.state.totalCount}</span>${alreadyFixedSuffix}`);
            
            // Show the log container when starting manual processing
            $('.rank-log-container').show();
            
            // Hide the spinner for manual processing (we have the loading placeholder now)
            $('#rank-log-spinner').removeClass('is-active').hide();
            
            // Show loading placeholder immediately before fetching the first item
            if (rank.elements.approvalArea) {
                rank.elements.approvalArea.empty().append(`
                    <div class="rank-approval-row">
                        <div class="rank-loading-placeholder">Loading... 5-15 seconds</div>
                    </div>
                `).show();
            }
    
            // Start fetching items for manual review
            fetchNextRow();
        });
    }
    
    // Expose public methods
    window.rank.processing = {
        init: init,
        scheduleAllTasks: scheduleAllTasks,
        startManualReview: startManualReview,
        fetchNextRow: fetchNextRow,
        resetProcessingState: resetProcessingState,
        startBatchAutoApproval: function() {
            
            rank.helpers.addLogMessage('Batch auto-approval process initiated.');
            
            // Remove the "View all pages" link immediately
            if (rank.urlListModal && typeof rank.urlListModal.removeViewUrlsButton === 'function') {
                rank.urlListModal.removeViewUrlsButton();
            }
            
            // Validate required state
            if (!rank.state.batchId) {
                console.error('RANK ERROR: Cannot start batch auto-approval - batchId is missing');
                rank.helpers.showNotice('Error: Batch ID is missing, cannot start automatic processing.', 'error');
                return;
            }
            
            if (!rank.state.issueType) {
                console.error('RANK ERROR: Cannot start batch auto-approval - issueType is missing');
                rank.helpers.showNotice('Error: Issue type is missing, cannot start automatic processing.', 'error');
                return;
            }
            
            if (!rank.state.totalCount || rank.state.totalCount <= 0) {
                rank.helpers.addLogMessage('No issues to process. Automatic processing completed.');
                rank.helpers.showNotice('Automatic processing completed - no issues found to process.', 'success');
                
                // Update status message
                if (rank.elements.statusMessage) {
                    rank.elements.statusMessage.text('Automatic processing completed for all pages ✅');
                }
                
                // Reset processing flags
                rank.state.isAutoProcessingActive = false;
                rank.state.autoApproveFlag = false;
                
                return;
            }
            
            // Set auto-processing flags to true
            rank.state.isAutoProcessingActive = true;
            rank.state.autoApproveFlag = true;
            
            // Show and initialize progress bar
            if (rank.elements.progressBarContainer) {
                rank.elements.progressBarContainer.show();
                rank.helpers.updateProgressBar(0);
            }
            
            // Update status message to show auto-processing
            if (rank.elements.statusMessage) {
                rank.elements.statusMessage.text(`Auto-processing: 1 of ${rank.state.totalCount}`);
            }
            
            // Ensure UI is clear for this mode (no single item approval showing from previous manual step)
            if (rank.elements.approvalArea && rank.elements.approvalArea.is(':visible')) {
                 // If an item was shown for manual review before clicking "Automatic", clear it.
                const manualItemVisible = rank.elements.approvalArea.find('.rank-approval-row').length > 0;
                if (manualItemVisible) {
                    rank.elements.approvalArea.empty().hide(); // Hide approval area for automatic processing
                    rank.helpers.addLogMessage('Cleared single item view for batch auto-approval.');
                }
            }
            
            // Reset continuation flag to ensure we start fresh
            rank.state.is_continuation = false;
            
            fetchNextRow(); // fetchNextRow will now handle the auto-approval loop with the flags set
        },
        // Clear processing area when switching tabs or reloading
        clearProcessingArea: function() {
            if (rank.elements.processingArea) {
                rank.elements.processingArea.hide();
            }
            if (rank.elements.healthIssuesContainer) {
                rank.elements.healthIssuesContainer.show();
            }
            if (rank.elements.approvalArea) {
                rank.elements.approvalArea.empty().hide(); // Hide approval area when clearing processing area
            }
            // Hide the log container and spinner when clearing processing area
            $('.rank-log-container').hide();
            $('#rank-log-spinner').removeClass('is-active').hide();
        },
        // Cancel all processing and reset state
        cancelProcessing: function() {
            // First, stop any active processing
            rank.state.isAutoProcessingActive = false;
            rank.state.autoProcessActionCompleted = true; // Set to true to prevent further processing
            
            // Reset all state variables and UI
            resetProcessingState();
            
            // If approval module is available, reset its UI
            if (rank.approval && typeof rank.approval.resetApprovalUI === 'function') {
                rank.approval.resetApprovalUI();
            }
            
            // Clear any pending AJAX requests if possible
            if (window.stop) {
                window.stop(); // This attempts to stop pending AJAX requests
            }
            
            // Force a page reload if requested
            if (rank_ajax_obj.force_reload_on_cancel === '1') {
                window.location.reload();
                return;
            }
            
            // Show notification
            rank.helpers.showNotice('Processing canceled. All state has been reset.', 'info');
        }
    };
    
})(jQuery, window.rank = window.rank || {});