HEX
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.30
System: Linux iZj6c1151k3ad370bosnmsZ 3.10.0-1160.76.1.el7.x86_64 #1 SMP Wed Aug 10 16:21:17 UTC 2022 x86_64
User: root (0)
PHP: 7.4.30
Disabled: NONE
Upload Files
File: /var/www/html/www.winghung.com/wp-content/plugins/mxchat-basic/js/knowledge-processing.js
jQuery(document).ready(function($) {
    // Track if a form has been submitted to trigger updates
    let formSubmitted = false;
    
    // Global interval ID to manage the polling
    let updateIntervalId = null;
    
    
     $(document).on('click', '.mxchat-dismiss-button', function() {
        const $button = $(this);
        const $card = $button.closest('.mxchat-status-card');
        
        // Determine card type from data attribute or content
        let cardType = $card.data('card-type');
        if (!cardType) {
            // Fallback: determine from content
            cardType = $card.find('h4').text().includes('PDF') ? 'pdf' : 'sitemap';
        }
        
        // Fade out and remove the card
        $card.fadeOut(300, function() {
            $(this).remove();
        });
        
        // Clear the completed status on the server
        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'mxchat_dismiss_completed_status',
                nonce: mxchatAdmin.status_nonce,
                card_type: cardType
            },
            success: function(response) {
                //console.log('MxChat: Completed status dismissed');
            },
            error: function(xhr, status, error) {
                console.error('MxChat: Error dismissing status:', error);
            }
        });
    });
    
    // Check if we're on the right admin page with status cards or import forms
    if ($('.mxchat-status-card').length > 0 || $('.mxchat-import-options').length > 0) {
        //console.log('MxChat: Status update script initialized');
        // Initialize AJAX status updates
        initStatusUpdates();
    }
    
    // Initialize status updates
// Initialize status updates
function initStatusUpdates() {
    // Get the refresh interval (default to 2 seconds for more responsive updates)
    const refreshInterval = parseInt(mxchatAdmin.status_refresh_interval || 2000);
    
    // Check if there are active status cards
    const hasActiveStatus = $('.mxchat-status-card').length > 0;
    
    // Set up form submission listeners
    $('#mxchat-url-form, #mxchat-content-form').on('submit', function() {
        //console.log('MxChat: Form submitted, will start checking for updates');
        formSubmitted = true;
        
        // Store submission info in sessionStorage to persist through redirects
        sessionStorage.setItem('mxchat_form_submitted', 'true');
        sessionStorage.setItem('mxchat_form_submitted_time', Date.now());
        
        // Start checking for status updates right away
        startPolling(refreshInterval);
        
        // Create a temporary message
        if ($('.mxchat-processing-message').length === 0) {
            const message = $('<div class="mxchat-processing-message" style="text-align: center; padding: 15px; background: #f0f7ff; border-radius: 8px; margin-top: 15px;">Processing request... Status will update automatically.</div>');
            $('.mxchat-import-section').after(message);
            
            // Fade out after 5 seconds
            setTimeout(function() {
                message.fadeOut(500, function() {
                    $(this).remove();
                });
            }, 5000);
        }
    });
    
    // Listen for import option clicks
    $('.mxchat-import-box').on('click', function() {
        const option = $(this).data('option');
        //console.log('MxChat: Import option clicked - ' + option);
    });
    
    // Check if we recently submitted a form (within last 60 seconds for sitemap processing)
    if (sessionStorage.getItem('mxchat_form_submitted') === 'true') {
        const submittedTime = parseInt(sessionStorage.getItem('mxchat_form_submitted_time') || '0');
        if (Date.now() - submittedTime < 60000) { // 60 seconds
            //console.log('MxChat: Detected recent form submission via sessionStorage');
            formSubmitted = true;
        } else {
            // Clear old submission data
            sessionStorage.removeItem('mxchat_form_submitted');
            sessionStorage.removeItem('mxchat_form_submitted_time');
        }
    }
    
    // Attach event listener to stop button to clear the interval
    $('.mxchat-stop-form').on('submit', function() {
        //console.log('MxChat: Stop processing requested, clearing update interval');
        stopPolling();
        sessionStorage.removeItem('mxchat_form_submitted');
        sessionStorage.removeItem('mxchat_form_submitted_time');
    });
    
    // Start the interval for automatic updates if we have status cards or a form was submitted
    if (hasActiveStatus || formSubmitted) {
        //console.log('MxChat: Starting automatic status checks');
        startPolling(refreshInterval);
    }
}
    
    // Function to start polling
    function startPolling(interval) {
        // Clear any existing interval first
        stopPolling();
        
        // Do an initial fetch immediately
        fetchStatusUpdates();
        
        // Set up new interval
        updateIntervalId = setInterval(function() {
            fetchStatusUpdates();
        }, interval);
        
        //console.log('MxChat: Polling started with interval', interval);
    }
    
    // Function to stop polling
    function stopPolling() {
        if (updateIntervalId !== null) {
            clearInterval(updateIntervalId);
            updateIntervalId = null;
            //console.log('MxChat: Polling stopped');
        }
    }
    
// Fetch status updates from the server
function fetchStatusUpdates() {
    // If user is actively viewing the failed URLs or pages, don't refresh as frequently
    const $details = $('.mxchat-failed-urls-container details, .mxchat-failed-pages-container details');
    const isUserViewing = $details.length > 0 && $details.prop('open');
    
    // If details are open, we'll refresh at a slower rate
    if (isUserViewing) {
        // Alternative: Update less frequently when details are open
        setTimeout(function() {
            performStatusUpdate(false); // Pass false for normal updates
        }, 5000); // Slow down updates to every 5 seconds when details are open
    } else {
        performStatusUpdate(false); // Pass false for normal updates
    }
}
    
// Perform the actual AJAX request
function performStatusUpdate(clearCompleted = false) {
    //console.log('MxChat: Checking for status updates...');
    
    $.ajax({
        url: ajaxurl,
        type: 'POST',
        data: {
            action: 'mxchat_get_status_updates',
            nonce: mxchatAdmin.status_nonce,
            clear_completed: clearCompleted ? 'true' : 'false'
        },
        success: function(response) {
            //console.log('MxChat: Status update received', response);
            
            // Log specific status details for debugging
            if (response.sitemap_status) {
                //console.log('Sitemap status:', response.sitemap_status.status, 'Processed:', response.sitemap_status.processed_urls, 'Total:', response.sitemap_status.total_urls);
            }
            
            // Check for completion BEFORE updating UI
            let shouldStopPolling = false;
            
            if (response.sitemap_status && response.sitemap_status.status === 'complete') {
                //console.log('MxChat: Sitemap processing complete');
                shouldStopPolling = true;
            }
            
            if (response.pdf_status && response.pdf_status.status === 'complete') {
                //console.log('MxChat: PDF processing complete');
                shouldStopPolling = true;
            }
            
            // Always update UI
            if ((response && response.is_processing) || formSubmitted || shouldStopPolling) {
                updateStatusUI(response);
            }
            
            // Show single URL status if available and no active processing
            if (response.single_url_status && !response.is_processing) {
                updateSingleUrlStatus(response.single_url_status);
            }
            
            // Handle completion - REMOVE THE AUTOMATIC PAGE RELOAD
            if (shouldStopPolling) {
                // Clear session storage
                sessionStorage.removeItem('mxchat_form_submitted');
                sessionStorage.removeItem('mxchat_form_submitted_time');
                
                // Stop polling
                stopPolling();
                
                // DON'T clear the completed status automatically
                // DON'T reload the page automatically
                
                return; // Exit early
            }
            
            // Reset form submitted flag if no active processing
            if (!response.is_processing) {
                formSubmitted = false;
                sessionStorage.removeItem('mxchat_form_submitted');
                sessionStorage.removeItem('mxchat_form_submitted_time');
                stopPolling();
            }
        },
        error: function(xhr, status, error) {
            console.error('MxChat: Status update failed:', error);
        }
    });
}

function addDismissButtonToCompletedCards() {
    // Add dismiss buttons to completed cards that don't have them
    $('.mxchat-status-card').each(function() {
        const $card = $(this);
        const $badge = $card.find('.mxchat-status-badge');
        
        // Check if this is a completed card and doesn't already have a dismiss button
        if (($badge.hasClass('mxchat-status-success') || $badge.hasClass('mxchat-status-warning')) && 
            $card.find('.mxchat-dismiss-button').length === 0) {
            
            // Look for existing action buttons container, or create one
            let $actionContainer = $card.find('.mxchat-action-buttons');
            
            if ($actionContainer.length === 0) {
                // Create the action buttons container if it doesn't exist
                $actionContainer = $('<div class="mxchat-action-buttons"></div>');
                $card.find('.mxchat-status-header').append($actionContainer);
            }
            
            // Add dismiss button WITHOUT inline styles
            const dismissButton = $('<button type="button" class="mxchat-dismiss-button">Dismiss</button>');
            
            dismissButton.on('click', function() {
                // Fade out and remove the card
                $card.fadeOut(300, function() {
                    $(this).remove();
                });
                
                // Clear the completed status on the server
                $.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: {
                        action: 'mxchat_dismiss_completed_status',
                        nonce: mxchatAdmin.status_nonce,
                        card_type: $card.find('h4').text().includes('PDF') ? 'pdf' : 'sitemap'
                    },
                    success: function(response) {
                        //console.log('MxChat: Completed status dismissed');
                    }
                });
            });
            
            $actionContainer.append(dismissButton);
        }
    });
}

    // Update the UI with status information
function updateStatusUI(data) {
    // Update PDF status if available
    if (data.pdf_status) {
        updatePdfStatus(data.pdf_status);
    }
    
    // Update sitemap status if available
    if (data.sitemap_status) {
        updateSitemapStatus(data.sitemap_status);
    }
    
    // Handle single URL status if available and no active processing
    if (data.single_url_status && !data.is_processing) {
        updateSingleUrlStatus(data.single_url_status);
    } else if (data.is_processing) {
        // Hide single URL status while processing
        $('#mxchat-single-url-status-container').hide();
    }
    
    // Add dismiss buttons to any completed cards
    addDismissButtonToCompletedCards();
}
    
    // Update PDF status card
function updatePdfStatus(status) {
    // Check if PDF card exists
    let $pdfCard = $('.mxchat-status-card:contains("PDF Processing")');
    
    // If no card exists but we have status, create it
    if ($pdfCard.length === 0 && status) {
        //console.log('MxChat: Creating new PDF status card');
        createPdfStatusCard(status);
        $pdfCard = $('.mxchat-status-card:contains("PDF Processing")');
    }
    
    // If card exists, update it
    if ($pdfCard.length > 0) {
        // Update progress bar
        $pdfCard.find('.mxchat-progress-fill').css('width', status.percentage + '%');
        
        // Update progress text
        let progressText = 'Progress: ' + status.processed_pages + ' of ' + 
                          status.total_pages + ' pages (' + status.percentage + '%)';
        
        $pdfCard.find('.mxchat-status-details p:first').text(progressText);
        
        // Update failed pages count if exists
        const $failedText = $pdfCard.find('.mxchat-status-details p:contains("Failed pages")');
        if (status.failed_pages && status.failed_pages > 0) {
            if ($failedText.length === 0) {
                // Add failed pages text after progress
                $pdfCard.find('.mxchat-status-details p:first').after(
                    '<p><strong>Failed pages:</strong> ' + status.failed_pages + '</p>'
                );
            } else {
                $failedText.html('<strong>Failed pages:</strong> ' + status.failed_pages);
            }
        } else if ($failedText.length > 0) {
            $failedText.remove();
        }
        
        // Update status text
        const $statusText = $pdfCard.find('.mxchat-status-details p:contains("Status:")');
        if ($statusText.length > 0) {
            $statusText.text('Status: ' + status.status.charAt(0).toUpperCase() + status.status.slice(1));
        }
        
        // Update last update text
        const $lastUpdateText = $pdfCard.find('.mxchat-status-details p:contains("Last update:")');
        if ($lastUpdateText.length > 0) {
            $lastUpdateText.text('Last update: ' + status.last_update);
        }
        
        // Update status badges
        $pdfCard.find('.mxchat-status-badge').remove();
        if (status.status === 'error') {
            $pdfCard.find('.mxchat-status-header').append('<span class="mxchat-status-badge mxchat-status-failed">Error</span>');
        } else if (status.status === 'complete') {
            if (status.failed_pages && status.failed_pages > 0) {
                $pdfCard.find('.mxchat-status-header').append('<span class="mxchat-status-badge mxchat-status-warning">Completed with ' + status.failed_pages + ' failures</span>');
            } else {
                $pdfCard.find('.mxchat-status-header').append('<span class="mxchat-status-badge mxchat-status-success">Complete</span>');
            }
        }
        
        // Update or add completion summary
        if (status.completion_summary) {
            let $summaryContainer = $pdfCard.find('.mxchat-completion-summary');
            if ($summaryContainer.length === 0) {
                const summaryHtml = '<div class="mxchat-completion-summary">' +
                    '<h5>Processing Summary</h5>' +
                    '<p><strong>Total Pages:</strong> ' + status.completion_summary.total_pages + '</p>' +
                    '<p><strong>Successful:</strong> ' + status.completion_summary.successful_pages + '</p>' +
                    '<p><strong>Failed:</strong> ' + status.completion_summary.failed_pages + '</p>' +
                    '<p><strong>Completed:</strong> ' + status.completion_summary.completion_time + '</p>' +
                    '</div>';
                $pdfCard.find('.mxchat-status-details').append(summaryHtml);
            }
        }
        
        // Update failed pages list if exists
        if (status.failed_pages_list && status.failed_pages_list.length > 0) {
            updateFailedPagesList($pdfCard, status.failed_pages_list);
        }
        
        // If we have an error, show it
        if (status.status === 'error' && status.error) {
            let $errorNotice = $pdfCard.find('.mxchat-error-notice');
            
            if ($errorNotice.length === 0) {
                $errorNotice = $('<div class="mxchat-error-notice"><p class="error"></p></div>');
                $pdfCard.find('.mxchat-status-details').append($errorNotice);
            }
            
            $errorNotice.find('p.error').text(status.error);
        }
    }
}
    
    // Create a new PDF status card
function createPdfStatusCard(status) {
    let html = '<div class="mxchat-status-card">';
    html += '<div class="mxchat-status-header">';
    html += '<h4>PDF Processing Status</h4>';
    
    // Add stop processing form if processing
    if (status.status === 'processing') {
        html += '<form method="post" class="mxchat-stop-form" action="' + 
               mxchatAdmin.admin_url + 'admin-post.php?action=mxchat_stop_processing">';
        html += '<input type="hidden" name="mxchat_stop_processing_nonce" value="' + 
               mxchatAdmin.stop_nonce + '">';
        html += '<button type="submit" name="stop_processing" class="mxchat-button-secondary">';
        html += 'Stop Processing</button></form>';
    }
    
    // Add status badges
    if (status.status === 'error') {
        html += '<span class="mxchat-status-badge mxchat-status-failed">Error</span>';
    } else if (status.status === 'complete') {
        if (status.failed_pages && status.failed_pages > 0) {
            html += '<span class="mxchat-status-badge mxchat-status-warning">Completed with ' + status.failed_pages + ' failures</span>';
        } else {
            html += '<span class="mxchat-status-badge mxchat-status-success">Complete</span>';
        }
    }
    
    html += '</div>'; // End header
    
    // Progress bar
    html += '<div class="mxchat-progress-bar">';
    html += '<div class="mxchat-progress-fill" style="width: ' + status.percentage + '%"></div>';
    html += '</div>';
    
    // Status details
    html += '<div class="mxchat-status-details">';
    html += '<p>Progress: ' + status.processed_pages + ' of ' + 
            status.total_pages + ' pages (' + status.percentage + '%)</p>';
    
    // Show failed pages count if any
    if (status.failed_pages && status.failed_pages > 0) {
        html += '<p><strong>Failed pages:</strong> ' + status.failed_pages + '</p>';
    }
    
    html += '<p>Status: ' + status.status.charAt(0).toUpperCase() + status.status.slice(1) + '</p>';
    html += '<p>Last update: ' + status.last_update + '</p>';
    
    // Add completion summary if available
    if (status.completion_summary) {
        html += '<div class="mxchat-completion-summary">';
        html += '<h5>Processing Summary</h5>';
        html += '<p><strong>Total Pages:</strong> ' + status.completion_summary.total_pages + '</p>';
        html += '<p><strong>Successful:</strong> ' + status.completion_summary.successful_pages + '</p>';
        html += '<p><strong>Failed:</strong> ' + status.completion_summary.failed_pages + '</p>';
        html += '<p><strong>Completed:</strong> ' + status.completion_summary.completion_time + '</p>';
        html += '</div>';
    }
    
    // Add failed pages list if any
    if (status.failed_pages_list && status.failed_pages_list.length > 0) {
        html += createFailedPagesHtml(status.failed_pages_list);
    }
    
    // Add error message if any
    if (status.status === 'error' && status.error) {
        html += '<div class="mxchat-error-notice">';
        html += '<p class="error">' + status.error + '</p>';
        html += '</div>';
    }
    
    html += '</div>'; // End details
    html += '</div>'; // End card
    
    // Insert the card into the page
    let $importTabContent = $('#mxchat-kb-tab-import');
    if ($importTabContent.length > 0) {
        let $sitemapCard = $importTabContent.find('.mxchat-status-card:contains("Sitemap Processing")');
        if ($sitemapCard.length > 0) {
            $sitemapCard.before($(html));
        } else {
            $importTabContent.find('.mxchat-import-section').after($(html));
        }
    } else {
        let $sitemapCard = $('.mxchat-status-card:contains("Sitemap Processing")');
        if ($sitemapCard.length > 0) {
            $sitemapCard.before($(html));
        } else {
            $('.mxchat-import-section').after($(html));
        }
    }
}
    
    // Update sitemap status card
function updateSitemapStatus(status) {
    // Check if sitemap card exists
    let $sitemapCard = $('.mxchat-status-card:contains("Sitemap Processing")');
    
    // If no card exists but we have status, create it
    if ($sitemapCard.length === 0 && status) {
        //console.log('MxChat: Creating new sitemap status card');
        createSitemapStatusCard(status);
        $sitemapCard = $('.mxchat-status-card:contains("Sitemap Processing")');
    }
    
    // If card exists, update it
    if ($sitemapCard.length > 0) {
        // Update progress bar
        $sitemapCard.find('.mxchat-progress-fill').css('width', status.percentage + '%');
        
        // Update progress text
        let progressText = 'Progress: ' + status.processed_urls + ' of ' + 
                          status.total_urls + ' URLs (' + status.percentage + '%)';
        
        $sitemapCard.find('.mxchat-status-details p:first').text(progressText);
        
        // Update failed URLs count if exists
        const $failedText = $sitemapCard.find('.mxchat-status-details p:contains("Failed URLs")');
        if (status.failed_urls && status.failed_urls > 0) {
            if ($failedText.length === 0) {
                // Add failed URLs text after progress
                $sitemapCard.find('.mxchat-status-details p:first').after(
                    '<p><strong>Failed URLs:</strong> ' + status.failed_urls + '</p>'
                );
            } else {
                $failedText.html('<strong>Failed URLs:</strong> ' + status.failed_urls);
            }
        } else if ($failedText.length > 0) {
            $failedText.remove();
        }
        
        // Update status badges
        $sitemapCard.find('.mxchat-status-badge').remove();
        if (status.status === 'error') {
            $sitemapCard.find('.mxchat-status-header').append('<span class="mxchat-status-badge mxchat-status-failed">Error</span>');
        } else if (status.status === 'complete') {
            if (status.failed_urls && status.failed_urls > 0) {
                $sitemapCard.find('.mxchat-status-header').append('<span class="mxchat-status-badge mxchat-status-warning">Completed with ' + status.failed_urls + ' failures</span>');
            } else {
                $sitemapCard.find('.mxchat-status-header').append('<span class="mxchat-status-badge mxchat-status-success">Complete</span>');
            }
        }
        
        // Update or add completion summary
        if (status.completion_summary) {
            let $summaryContainer = $sitemapCard.find('.mxchat-completion-summary');
            if ($summaryContainer.length === 0) {
                const summaryHtml = '<div class="mxchat-completion-summary">' +
                    '<h5>Processing Summary</h5>' +
                    '<p><strong>Total URLs:</strong> ' + status.completion_summary.total_urls + '</p>' +
                    '<p><strong>Successful:</strong> ' + status.completion_summary.successful_urls + '</p>' +
                    '<p><strong>Failed:</strong> ' + status.completion_summary.failed_urls + '</p>' +
                    '<p><strong>Completed:</strong> ' + status.completion_summary.completion_time + '</p>' +
                    '</div>';
                $sitemapCard.find('.mxchat-status-details').append(summaryHtml);
            }
        }
        
        // Check if details is already open before updating
        const isDetailsOpen = $sitemapCard.find('.mxchat-failed-urls-container details').prop('open');
        
        // Update errors display
        let $errorContainer = $sitemapCard.find('.mxchat-error-notice');
        
        if ($errorContainer.length === 0 && 
            (status.error || status.last_error || (status.failed_urls_list && status.failed_urls_list.length > 0))) {
            // Create error container if it doesn't exist
            $errorContainer = $('<div class="mxchat-error-notice"></div>');
            $sitemapCard.find('.mxchat-status-details').append($errorContainer);
        }
        
        // Update or create error notices
        if ($errorContainer.length > 0) {
            let errorHTML = '';
            
            if (status.error) {
                errorHTML += '<p class="error">' + status.error + '</p>';
            }
            
            if (status.last_error) {
                errorHTML += '<p class="last-error">Last error: ' + status.last_error + '</p>';
            }
            
            // Add failed URLs list
            if (status.failed_urls_list && status.failed_urls_list.length > 0) {
                errorHTML += '<div class="mxchat-failed-urls-container">';
                errorHTML += '<h5>Failed URLs (' + status.failed_urls_list.length + ')</h5>';
                
                // Set the 'open' attribute based on previous state
                errorHTML += '<details' + (isDetailsOpen ? ' open' : '') + '>';
                errorHTML += '<summary>Show Failed URLs</summary>';
                errorHTML += '<div class="mxchat-failed-urls-list">';
                
                // Create table for failed URLs
                errorHTML += '<table class="widefat striped">';
                errorHTML += '<thead><tr><th>URL</th><th>Error</th><th>Retries</th><th>Time</th></tr></thead>';
                errorHTML += '<tbody>';
                
                // Sort failed URLs by most recent
                const sortedFailedUrls = [...status.failed_urls_list].sort((a, b) => b.time - a.time);
                
                // Show up to 50 failed URLs
                const displayUrls = sortedFailedUrls.slice(0, 50);
                
                displayUrls.forEach(item => {
                    const timeAgo = formatTimeAgo(item.time);
                    const retries = item.retries || 'N/A';
                    errorHTML += '<tr>';
                    errorHTML += '<td style="word-break: break-all;">';
                    errorHTML += '<a href="' + item.url + '" target="_blank" rel="noopener noreferrer">';
                    errorHTML += truncateUrl(item.url) + '</a></td>';
                    errorHTML += '<td style="word-break: break-word;">' + item.error + '</td>';
                    errorHTML += '<td>' + retries + '</td>';
                    errorHTML += '<td>' + timeAgo + '</td>';
                    errorHTML += '</tr>';
                });
                
                errorHTML += '</tbody></table>';
                
                if (status.failed_urls_list.length > 50) {
                    errorHTML += '<div class="mxchat-failed-urls-more">+ ' + 
                                 (status.failed_urls_list.length - 50) + 
                                 ' more failed URLs not shown</div>';
                }
                
                errorHTML += '</div>'; // End of failed-urls-list
                errorHTML += '</details>';
                errorHTML += '</div>'; // End of failed-urls-container
            }
            
            $errorContainer.html(errorHTML);
            
            // Additionally, add a click handler to pause refreshes when viewing details
            $sitemapCard.find('.mxchat-failed-urls-container details').on('toggle', function() {
                if (this.open) {
                    // User opened the details - set a flag
                    $(this).data('user-opened', true);
                } else {
                    // User closed the details - remove the flag
                    $(this).data('user-opened', false);
                }
            });
        }
    }
}

function createFailedPagesHtml(failedPagesList) {
    let html = '<div class="mxchat-error-notice">';
    html += '<div class="mxchat-failed-pages-container">';
    html += '<h5>Failed Pages (' + failedPagesList.length + ')</h5>';
    html += '<details>';
    html += '<summary>Show Failed Pages</summary>';
    html += '<div class="mxchat-failed-pages-list">';
    
    // Create table for failed pages
    html += '<table class="widefat striped">';
    html += '<thead><tr><th>Page</th><th>Error</th><th>Retries</th><th>Time</th></tr></thead>';
    html += '<tbody>';
    
    // Sort failed pages by most recent
    const sortedFailedPages = [...failedPagesList].sort((a, b) => b.time - a.time);
    
    sortedFailedPages.forEach(item => {
        const timeAgo = formatTimeAgo(item.time);
        html += '<tr>';
        html += '<td>Page ' + item.page + '</td>';
        html += '<td style="word-break: break-word;">' + item.error + '</td>';
        html += '<td>' + item.retries + '</td>';
        html += '<td>' + timeAgo + '</td>';
        html += '</tr>';
    });
    
    html += '</tbody></table>';
    html += '</div>'; // End of failed-pages-list
    html += '</details>';
    html += '</div>'; // End of failed-pages-container
    html += '</div>'; // End of error-notice
    
    return html;
}

// NEW: Update failed pages list in existing card
function updateFailedPagesList($pdfCard, failedPagesList) {
    // Check if details is already open before updating
    const isDetailsOpen = $pdfCard.find('.mxchat-failed-pages-container details').prop('open');
    
    let $errorContainer = $pdfCard.find('.mxchat-failed-pages-container').parent();
    
    if ($errorContainer.length === 0) {
        // Create new failed pages container
        $pdfCard.find('.mxchat-status-details').append(createFailedPagesHtml(failedPagesList));
    } else {
        // Update existing container
        $errorContainer.html(createFailedPagesHtml(failedPagesList));
        
        // Restore open state if it was open before
        if (isDetailsOpen) {
            $pdfCard.find('.mxchat-failed-pages-container details').prop('open', true);
        }
    }
}

    
    // Create a new sitemap status card
    function createSitemapStatusCard(status) {
        let html = '<div class="mxchat-status-card">';
        html += '<div class="mxchat-status-header">';
        html += '<h4>Sitemap Processing Status</h4>';
        
        // Add stop processing form if processing
        if (status.status === 'processing') {
            html += '<form method="post" class="mxchat-stop-form" action="' + 
                   mxchatAdmin.admin_url + 'admin-post.php?action=mxchat_stop_processing">';
            html += '<input type="hidden" name="mxchat_stop_processing_nonce" value="' + 
                   mxchatAdmin.stop_nonce + '">';
            html += '<button type="submit" name="stop_processing" class="mxchat-button-secondary">';
            html += 'Stop Processing</button></form>';
        }
        
        // Add error badge if error
        if (status.status === 'error') {
            html += '<span class="mxchat-status-badge mxchat-status-failed">Error</span>';
        }
        
        html += '</div>'; // End header
        
        // Progress bar
        html += '<div class="mxchat-progress-bar">';
        html += '<div class="mxchat-progress-fill" style="width: ' + status.percentage + '%"></div>';
        html += '</div>';
        
        // Status details
        html += '<div class="mxchat-status-details">';
        html += '<p>Progress: ' + status.processed_urls + ' of ' + 
                status.total_urls + ' URLs (' + status.percentage + '%)</p>';
        
        // Add error message if any
        if ((status.error || status.last_error) && status.status === 'error') {
            html += '<div class="mxchat-error-notice">';
            
            if (status.error) {
                html += '<p class="error">' + status.error + '</p>';
            }
            
            if (status.last_error) {
                html += '<p class="last-error">Last error: ' + status.last_error + '</p>';
            }
            
            html += '</div>';
        }
        
        html += '</div>'; // End details
        html += '</div>'; // End card
        
        // Try to find the import tab content to insert the status card into
        let $importTabContent = $('#mxchat-kb-tab-import');
        if ($importTabContent.length > 0) {
            // For the tabbed interface, add to the import tab
            let $pdfCard = $importTabContent.find('.mxchat-status-card:contains("PDF Processing")');
            if ($pdfCard.length > 0) {
                $pdfCard.after($(html));
            } else {
                $importTabContent.find('.mxchat-import-section').after($(html));
            }
        } else {
            // Fallback to the old method
            let $pdfCard = $('.mxchat-status-card:contains("PDF Processing")');
            if ($pdfCard.length > 0) {
                $pdfCard.after($(html));
            } else {
                $('.mxchat-import-section').after($(html));
            }
        }
    }
    
    // Update single URL status
    function updateSingleUrlStatus(status) {
        // Check if container exists
        let $container = $('#mxchat-single-url-status-container');
        
        if ($container.length === 0) {
            // Create container
            $container = $('<div id="mxchat-single-url-status-container"></div>');
            
            // Try to find the import tab content to insert the status card into
            let $importTabContent = $('#mxchat-kb-tab-import');
            if ($importTabContent.length > 0) {
                // For the tabbed interface, add to the import tab
                let $lastStatusCard = $importTabContent.find('.mxchat-status-card').last();
                if ($lastStatusCard.length > 0) {
                    $lastStatusCard.after($container);
                } else {
                    $importTabContent.find('.mxchat-import-section').after($container);
                }
            } else {
                // Fallback to the old method
                let $lastStatusCard = $('.mxchat-status-card').last();
                if ($lastStatusCard.length > 0) {
                    $lastStatusCard.after($container);
                } else {
                    $('.mxchat-import-section').after($container);
                }
            }
        }
        
        // Update container content
        let html = '<div class="mxchat-status-card">';
        html += '<div class="mxchat-status-header">';
        html += '<h4>Last URL Submission</h4>';
        
        if (status.status === 'failed') {
            html += '<span class="mxchat-status-badge mxchat-status-failed">Failed</span>';
        } else {
            html += '<span class="mxchat-status-badge mxchat-status-success">Success</span>';
        }
        
        html += '</div>'; // End header
        
        html += '<div class="mxchat-status-details">';
        html += '<p><strong>URL:</strong> ';
        html += '<a href="' + status.url + '" target="_blank">';
        
        // Truncate URL if needed
        const displayUrl = status.url.length > 60 ? status.url.substring(0, 57) + '...' : status.url;
        html += displayUrl;
        
        html += '</a></p>';
        html += '<p><strong>Submitted:</strong> ' + status.human_time + '</p>';
        
        if (status.status === 'failed' && status.error) {
            html += '<div class="mxchat-error-notice">';
            html += '<p class="error">' + status.error + '</p>';
            html += '</div>';
        }
        
        if (status.status === 'complete') {
            html += '<p><strong>Content Length:</strong> ' + status.content_length + ' characters</p>';
            html += '<p><strong>Embedding Dimensions:</strong> ' + status.embedding_dimensions + '</p>';
        }
        
        html += '</div>'; // End details
        html += '</div>'; // End card
        
        $container.html(html).show();
    }
    
    // Helper function to format time ago
    function formatTimeAgo(timestamp) {
        const now = Math.floor(Date.now() / 1000);
        const seconds = now - timestamp;
        
        if (seconds < 60) {
            return seconds + ' seconds ago';
        } else if (seconds < 3600) {
            return Math.floor(seconds / 60) + ' minutes ago';
        } else if (seconds < 86400) {
            return Math.floor(seconds / 3600) + ' hours ago';
        } else {
            return Math.floor(seconds / 86400) + ' days ago';
        }
    }
    
    // Helper function to truncate long URLs
    function truncateUrl(url) {
        const maxLength = 50;
        if (url.length <= maxLength) return url;
        
        // Remove protocol
        let displayUrl = url.replace(/^https?:\/\//, '');
        
        if (displayUrl.length <= maxLength) return displayUrl;
        
        // Keep the domain and truncate the path
        const domainMatch = displayUrl.match(/^([^\/]+)\//);
        if (domainMatch) {
            const domain = domainMatch[1];
            const path = displayUrl.substring(domain.length);
            
            if (path.length > 10) {
                return domain + path.substring(0, maxLength - domain.length - 3) + '...';
            }
        }
        
        // Final fallback for very long strings
        return displayUrl.substring(0, maxLength - 3) + '...';
    }
    
    // Manual Batch Processing Button Handler
$(document).on('click', '.mxchat-manual-batch-btn', function() {
    const $btn = $(this);
    const processType = $btn.data('process-type');
    const url = $btn.data('url');
    
    //console.log('Manual batch processing requested:', processType, url);
    
    // Disable button and show loading
    $btn.prop('disabled', true).text('Processing...');
    
    $.ajax({
        url: ajaxurl,
        type: 'POST',
        data: {
            action: 'mxchat_manual_batch_process',
            nonce: mxchatAdmin.status_nonce,
            process_type: processType,
            url: url
        },
        success: function(response) {
            //console.log('Manual batch response:', response);
            
            if (response.success) {
                // Show success message briefly
                $btn.text('✓ Processed ' + response.data.processed);
                
                // Re-enable button after 2 seconds
                setTimeout(function() {
                    $btn.prop('disabled', false).text('Process Batch');
                }, 2000);
                
                // Trigger status update to show progress
                setTimeout(function() {
                    fetchStatusUpdates();
                }, 1000); // Wait 1 second then refresh status
                
            } else {
                console.error('Manual batch failed:', response.data);
                alert('Error: ' + response.data);
                $btn.prop('disabled', false).text('Process Batch');
            }
        },
        error: function(xhr, status, error) {
            console.error('Manual batch AJAX error:', error);
            alert('Processing failed. Please try again.');
            $btn.prop('disabled', false).text('Process Batch');
        }
    });
});
});


// Handle AJAX delete for Pinecone
// Handle AJAX delete for Pinecone
jQuery(document).on('click', '.delete-button-ajax', function(e) {
    e.preventDefault();
    
    if (!confirm('Are you sure you want to delete this entry?')) {
        return;
    }
    
    var $button = jQuery(this);
    var $row = $button.closest('tr');
    var vectorId = $button.data('vector-id');
    var botId = $button.data('bot-id') || 'default'; // Get bot_id from data attribute
    var nonce = $button.data('nonce');
    
    // Disable button and show loading
    $button.prop('disabled', true);
    $button.find('.dashicons').removeClass('dashicons-trash').addClass('dashicons-update-alt');
    $row.addClass('mxchat-row-deleting');
    
    jQuery.ajax({
        url: ajaxurl,
        type: 'POST',
        data: {
            action: 'mxchat_delete_pinecone_prompt',
            nonce: nonce,
            vector_id: vectorId,
            bot_id: botId // Include bot_id in the request
        },
        success: function(response) {
            if (response.success) {
                // Immediately remove the row with animation
                $row.fadeOut(500, function() {
                    jQuery(this).remove();
                    
                    // Update record count
                    var $countSpan = jQuery('.mxchat-record-count');
                    if ($countSpan.length) {
                        var currentText = $countSpan.text();
                        var matches = currentText.match(/\((\d+)/);
                        if (matches) {
                            var currentCount = parseInt(matches[1]);
                            var newCount = Math.max(0, currentCount - 1);
                            $countSpan.text($countSpan.text().replace(/\(\d+/, '(' + newCount));
                        }
                    }
                });
                
                // Show success message
                jQuery('<div class="notice notice-success is-dismissible"><p>Entry deleted successfully from Pinecone.</p></div>')
                    .insertAfter('.mxchat-hero')
                    .delay(3000)
                    .fadeOut();
                    
            } else {
                // Re-enable button and show error
                $button.prop('disabled', false);
                $button.find('.dashicons').removeClass('dashicons-update-alt').addClass('dashicons-trash');
                $row.removeClass('mxchat-row-deleting');
                
                alert('Error: ' + response.data);
            }
        },
        error: function() {
            // Re-enable button
            $button.prop('disabled', false);
            $button.find('.dashicons').removeClass('dashicons-update-alt').addClass('dashicons-trash');
            $row.removeClass('mxchat-row-deleting');
            
            alert('Network error occurred');
        }
    });
});