/**
 * Helpers Module
 * Utility functions for the RANK Admin
 */
(function($, rank) {
    'use strict';
    
    // Store active AJAX requests
    const activeAjaxRequests = [];
    
    // Show or hide control buttons
    function showControlButtons(show = true) {
        if (rank.elements.startButton) {
            if (show) {
                rank.elements.startButton.show();
                rank.elements.autoProcessButton.show();
                rank.elements.autoApproveCheckbox.closest('label').show();
            } else {
                rank.elements.startButton.hide();
                rank.elements.autoProcessButton.hide();
                rank.elements.autoApproveCheckbox.closest('label').hide();
            }
        }
    }
    
    // Reset UI state
    function resetUIState() {
        clearNotices();
        if (rank.elements.logOutput) rank.elements.logOutput.empty();
        updateProgressBar(0);
        if (rank.elements.counts) rank.elements.counts.text('');
    }
    
    // Handle AJAX response
    function handleAjaxResponse(response, context, {
        onSuccess = () => {},
        onError = () => {},
        showButtons = true
    } = {}) {
        if (response.success) {
            onSuccess(response.data);
        } else {
            const errorMsg = response.data || `Error during ${context}`;
            showNotice(errorMsg, 'error');
            addLogMessage(`Error during ${context}: ${errorMsg}`);
            onError();
            if (showButtons) {
                showControlButtons(true);
            }
        }
    }
    
    // Handle AJAX error
    function handleAjaxError(errorData, context) {
        const { jqXHR, textStatus, errorThrown } = errorData;
        showNotice(`Error during ${context}: ${textStatus} - ${errorThrown}`, 'error');
        addLogMessage(`AJAX Error during ${context}: ${textStatus} - ${errorThrown}`);
    }
    
    // Update progress bar
    function updateProgressBar(percentage) {
        if (rank.elements.progressBar) {
            rank.elements.progressBar.css('width', percentage + '%').attr('aria-valuenow', percentage);
            rank.elements.progressBar.text(percentage + '%');
        }
    }
    
    // Show notification
    function showNotice(message, type = 'info') {
        if (rank.elements.noticeArea) {
            const $notice = $(`<div class="notice notice-${type} is-dismissible"><p>${message}</p></div>`);
            rank.elements.noticeArea.append($notice);
            
            const $button = $('<button type="button" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span></button>');
            $notice.append($button);
            
            $button.on('click', function() {
                $notice.fadeOut(300, function() { $(this).remove(); });
            });
        }
    }
    
    // Clear all notices
    function clearNotices() {
        if (rank.elements.noticeArea) rank.elements.noticeArea.empty();
    }
    
    // Add message to log
    function addLogMessage(message) {
        if (rank.elements.logOutput) {
            // Filter out technical messages that end users don't need to see
            if (message === 'Batch auto-approval process initiated.' ||
                message === 'Cleared approval area before starting auto process.' ||
                message === 'Starting batch auto-approval process.' ||
                message === 'Preparation complete. User to choose processing mode.' ||
                message.startsWith('Auto-approving item:')) {
                // Skip these technical messages
                return;
            }
            
            const timestamp = new Date().toLocaleTimeString();
            rank.elements.logOutput.prepend(`<p>[${timestamp}] ${message}</p>`);
            
            // Limit log entries to prevent memory issues during long processing
            const maxLogEntries = 100; // Max log entries to keep before starting FIFO cleanup (oldest entries gets removed first)
            const logEntries = rank.elements.logOutput.children('p');
            if (logEntries.length > maxLogEntries) {
                // Remove oldest entries (from the end since we prepend)
                logEntries.slice(maxLogEntries).remove();
            }
        }
    }
    
    // Show processing area
    function showProcessingArea() {
        if (rank.elements.processingArea) rank.elements.processingArea.show();
        if (rank.elements.startButton) rank.elements.startButton.show().prop('disabled', false);
        if (rank.elements.autoProcessButton) rank.elements.autoProcessButton.show();
        if (rank.elements.autoApproveCheckbox) rank.elements.autoApproveCheckbox.closest('label').show();
        if (rank.elements.cancelBtn) rank.elements.cancelBtn.show();
        if (rank.elements.completeClearLogBtn) rank.elements.completeClearLogBtn.hide();
    }
    
    // Add this function
    function escapeHtml(text) {
        if (typeof text !== 'string') return String(text); // Ensure it's a string
        return text
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }
    
    /**
     * Escapes characters that have special meaning in a CSS selector.
     * @param {string} str The string to escape.
     * @return {string} The escaped string.
     */
    function escapeCssSelector(str) {
        if (typeof str !== 'string') {
            // console.warn('escapeCssSelector called with non-string value:', str);
            return String(str); // Attempt to coerce to string
        }
        // Basic escape for use in names/IDs. 
        // Replaces non-alphanumeric characters (excluding underscore and hyphen)
        // with an underscore followed by their hex character code.
        return str.replace(/[^a-zA-Z0-9_-]/g, function(match) {
            return '_' + match.charCodeAt(0).toString(16); 
        });
    }
    
    // Track AJAX requests
    function trackAjaxRequest(jqXHR) {
        activeAjaxRequests.push(jqXHR);
        
        // Remove from tracking when complete
        jqXHR.always(function() {
            const index = activeAjaxRequests.indexOf(jqXHR);
            if (index !== -1) {
                activeAjaxRequests.splice(index, 1);
            }
        });
        
        return jqXHR;
    }
    
    // Abort all active AJAX requests
    function abortAllAjaxRequests() {
        activeAjaxRequests.forEach(function(request) {
            if (request && request.abort) {
                request.abort();
            }
        });
        activeAjaxRequests.length = 0; // Clear the array
    }
    
    // Expose public methods by assigning to rank.helpers
    rank.helpers = {
        showControlButtons: showControlButtons,
        resetUIState: resetUIState,
        handleAjaxResponse: handleAjaxResponse,
        handleAjaxError: handleAjaxError,
        updateProgressBar: updateProgressBar,
        showNotice: showNotice,
        clearNotices: clearNotices,
        addLogMessage: addLogMessage,
        showProcessingArea: showProcessingArea,
        escapeHtml: escapeHtml,
        escapeCssSelector: escapeCssSelector,
        trackAjaxRequest: trackAjaxRequest,
        abortAllAjaxRequests: abortAllAjaxRequests
    };
    
    // Set up event handler to abort AJAX requests only when navigating away from the page
    $(window).on('beforeunload', function() {
        abortAllAjaxRequests();
    });
    
})(jQuery, window.rank = window.rank || {}); 