/**
 * Progress Component
 * Manages research progress display and updates via Socket.IO
 */
(function() {
    // Component state
    let currentResearchId = null;
    let pollInterval = null;
    let isCompleted = false;
    let socketErrorShown = false;
    // Keeps track of whether we've set a specific progress message or just
    // a generic one based on the status.
    let specificProgressMessage = false;

    // DOM Elements
    let progressBar = null;
    let progressPercentage = null;
    let statusText = null;
    let currentTaskText = null;
    let cancelButton = null;
    let viewResultsButton = null;

    // Socket instance
    let socket = null;
    let reconnectAttempts = 0;
    const MAX_RECONNECT_ATTEMPTS = 5;
    const RECONNECT_DELAY = 3000;

    // Current research info
    let researchCompleted = false;
    let notificationsEnabled = false;

    /**
     * Initialize the progress component
     */
    function initializeProgress() {
        // Get research ID from URL or localStorage
        currentResearchId = getResearchIdFromUrl(); // Only from URL, not localStorage

        if (!currentResearchId) {
            console.error('No research ID found');
            if (window.ui) window.ui.showError('No active research found. Please start a new research.');
            setTimeout(() => {
                window.location.href = '/';
            }, 3000);
            return;
        }

        // Get DOM elements
        progressBar = document.getElementById('progress-bar');
        progressPercentage = document.getElementById('progress-percentage');
        statusText = document.getElementById('status-text');
        currentTaskText = document.getElementById('current-task');
        cancelButton = document.getElementById('cancel-research-btn');
        viewResultsButton = document.getElementById('view-results-btn');

        // Log available elements for debugging
        console.log('Progress DOM elements:', {
            progressBar: !!progressBar,
            progressPercentage: !!progressPercentage,
            statusText: !!statusText,
            currentTaskText: !!currentTaskText,
            cancelButton: !!cancelButton,
            viewResultsButton: !!viewResultsButton
        });

        // Check for required elements
        const missingElements = [];
        if (!progressBar) missingElements.push('progress-bar');
        if (!statusText) missingElements.push('status-text');
        if (!currentTaskText) missingElements.push('current-task');

        if (missingElements.length > 0) {
            console.error('Required DOM elements not found for progress component:', missingElements.join(', '));
            // Try to create fallback elements if not found
            createFallbackElements(missingElements);
        }

        // Set up event listeners
        if (cancelButton) {
            cancelButton.addEventListener('click', handleCancelResearch);
        }

        // Keyboard navigation is now handled by the global keyboard service
        // The Enter key shortcut for viewing results is automatically registered

        // Note: Log panel is now automatically initialized by logpanel.js
        // No need to manually initialize it here

        // Make sure navigation stays working even if Socket.IO fails
        setupSafeNavigationHandling();

        // Initialize socket connection if available
        if (window.socket) {
            initializeSocket();
        } else {
            console.warn('Socket service not available, falling back to polling');
            // Set up polling as fallback
            pollInterval = setInterval(checkProgress, 3000);
        }

        // Initial progress check
        checkProgress();

        console.log('Progress component initialized for research ID:', currentResearchId);

        // Get notification preference
        notificationsEnabled = true; // Default to enabled

        // Get initial research status
        getInitialStatus();
    }

    /**
     * Set up safe navigation handling to prevent WebSocket errors from blocking navigation
     */
    function setupSafeNavigationHandling() {
        // Find all navigation links
        const navLinks = document.querySelectorAll('a, .sidebar-nav li, .mobile-tab-bar li');

        navLinks.forEach(link => {
            // Don't override existing click handlers, add our handler
            const originalClickHandler = link.onclick;

            link.onclick = function(event) {
                // If socket has errors, disconnect it before navigation
                if (window.socket && typeof window.socket.isUsingPolling === 'function' && window.socket.isUsingPolling()) {
                    console.log('Navigation with polling fallback active, ensuring clean state');
                    try {
                        // Clean up any polling intervals
                        if (window.pollIntervals) {
                            Object.keys(window.pollIntervals).forEach(id => {
                                clearInterval(window.pollIntervals[id]);
                            });
                        }
                    } catch (e) {
                        console.error('Error cleaning up before navigation:', e);
                    }
                }

                // Call the original click handler if it exists
                if (typeof originalClickHandler === 'function') {
                    return originalClickHandler.call(this, event);
                }

                // Default behavior
                return true;
            };
        });
    }

    /**
     * Create fallback elements if they're missing
     * @param {Array} missingElements - Array of missing element IDs
     */
    function createFallbackElements(missingElements) {
        const progressContainer = document.querySelector('.progress-container');
        const statusContainer = document.querySelector('.status-container');
        const taskContainer = document.querySelector('.task-container');

        if (missingElements.includes('progress-bar') && progressContainer) {
            console.log('Creating fallback progress bar');
            const progressBarContainer = document.createElement('div');
            progressBarContainer.className = 'progress-bar';
            progressBarContainer.innerHTML = '<div id="progress-bar" class="progress-fill" style="width: 0%"></div>';
            progressContainer.prepend(progressBarContainer);
            progressBar = document.getElementById('progress-bar');

            if (!progressPercentage) {
                const percentEl = document.createElement('div');
                percentEl.id = 'progress-percentage';
                percentEl.className = 'progress-percentage';
                percentEl.textContent = '0%';
                progressContainer.appendChild(percentEl);
                progressPercentage = percentEl;
            }
        }

        if (missingElements.includes('status-text') && statusContainer) {
            console.log('Creating fallback status text');
            const statusEl = document.createElement('div');
            statusEl.id = 'status-text';
            statusEl.className = 'status-indicator';
            statusEl.textContent = 'Initializing';
            statusContainer.appendChild(statusEl);
            statusText = statusEl;
        }

        if (missingElements.includes('current-task') && taskContainer) {
            console.log('Creating fallback task text');
            const taskEl = document.createElement('div');
            taskEl.id = 'current-task';
            taskEl.className = 'task-text';
            taskEl.textContent = 'Starting research...';
            taskContainer.appendChild(taskEl);
            currentTaskText = taskEl;
        }
    }

    /**
     * Extract research ID from URL
     * @returns {string|null} The research ID or null if not found
     */
    function getResearchIdFromUrl() {
        return URLBuilder.extractResearchIdFromPattern('progress');
    }

    /**
     * Initialize Socket.IO connection and listeners
     */
    function initializeSocket() {
        try {
            console.log('Initializing socket connection for research ID:', currentResearchId);

            // Check if socket service is available
            if (!window.socket) {
                console.warn('Socket service not available, falling back to polling');
                // Set up polling as fallback
                fallbackToPolling();
                return;
            }

            // Subscribe to research events
            window.socket.subscribeToResearch(currentResearchId, handleProgressUpdate);

            // Handle socket reconnection
            window.socket.onReconnect(() => {
                console.log('Socket reconnected, resubscribing to research events');
                window.socket.subscribeToResearch(currentResearchId, handleProgressUpdate);
            });

            // Check socket status after a short delay to see if we're connected
            setTimeout(() => {
                if (window.socket.isUsingPolling && window.socket.isUsingPolling()) {
                    console.log('Socket using polling fallback');
                    if (!socketErrorShown) {
                        socketErrorShown = true;
                        // Add an info message to the console log if it exists
                        if (window.addConsoleLog) {
                            window.addConsoleLog('Using polling for updates due to WebSocket connection issues', 'info');
                        }
                    }

                    // Ensure we check for updates right away
                    checkProgress();
                } else {
                    console.log('Socket using WebSockets successfully');
                }
            }, 2000);
        } catch (error) {
            console.error('Error initializing socket:', error);
            // Fall back to polling
            fallbackToPolling();
        }
    }

    /**
     * Fall back to polling for updates
     */
    function fallbackToPolling() {
        console.log('Setting up polling fallback for research updates');

        if (!pollInterval) {
            pollInterval = setInterval(checkProgress, 3000);

            // Add a log entry about polling
            if (window.addConsoleLog) {
                window.addConsoleLog('Using polling for research updates instead of WebSockets', 'info');
            }
        }
    }

    /**
     * Handle progress update from socket
     * @param {Object} data - The progress data
     */
    function handleProgressUpdate(data) {
        console.log('Received progress update:', data);

        // Debug: Log if this is a log_entry update
        if (data && data.log_entry) {
            console.log('Progress update contains log_entry:', {
                type: data.log_entry.type,
                message: data.log_entry.message,
                hasOtherFields: Object.keys(data).filter(k => k !== 'log_entry').length > 0
            });
        }

        if (!data) return;

        // Process progress_log if available and add to logs
        // NOTE: This is now handled by the logpanel component directly
        // We'll just ensure the panel is visible and let it manage logs
        if (data.progress_log && typeof data.progress_log === 'string') {
            try {
                // Validate that the progress_log is valid JSON
                const progressLogsCheck = JSON.parse(data.progress_log);
                if (Array.isArray(progressLogsCheck) && progressLogsCheck.length > 0) {
                    console.log(`Found ${progressLogsCheck.length} logs in progress update - forwarding to log panel`);

                    // Make the log panel visible if it exists
                    const logPanel = document.querySelector('.collapsible-log-panel');
                    if (logPanel && window.getComputedStyle(logPanel).display === 'none') {
                        logPanel.style.display = 'flex';
                    }

                    // The actual log processing is now handled by socket.js and logpanel.js
                    // We don't need to process logs here anymore
                }
            } catch (e) {
                console.error('Error checking progress_log format:', e);
            }
        }

        // Check if this is a milestone log that should update the current task
        let milestoneTask = null;
        if (data.log_entry && (data.log_entry.type === 'milestone' || data.log_entry.type === 'MILESTONE') && data.log_entry.message) {
            // Milestone logs should always update the current task
            milestoneTask = data.log_entry.message;
            console.log('Milestone task detected:', milestoneTask);
        }

        // Update progress UI (but preserve milestone task)
        updateProgressUI(data);

        // If we have a milestone task, make sure it's set after updateProgressUI
        if (milestoneTask && currentTaskText) {
            console.log('Setting milestone task:', milestoneTask);
            currentTaskText.textContent = milestoneTask;
            currentTaskText.dataset.lastMessage = milestoneTask;
            currentTaskText.dataset.isMilestone = 'true';
        }

        // Check if research is completed
        if (data.status === 'completed' || data.status === 'failed' || data.status === 'cancelled') {
            handleResearchCompletion(data);
        }

        // Update the current query text if available
        const currentQueryEl = document.getElementById('current-query');
        if (currentQueryEl && data.query) {
            currentQueryEl.textContent = data.query;
        }

        // If no task info was provided, leave the current task as is
        // This prevents tasks from being overwritten by empty updates
    }

    /**
     * Determine log level based on status
     * @param {string} status - The research status
     * @returns {string} Log level (info, milestone, error, etc)
     */
    function determineLogLevel(status) {
        if (!status) return 'info';

        if (status === 'completed' || status === 'failed' || status === 'cancelled' || status === 'error') {
            return 'milestone';
        }

        if (status === 'error' || status.includes('error')) {
            return 'error';
        }

        return 'info';
    }

    /**
     * Check research progress via API
     */
    async function checkProgress() {
        try {
            if (!window.api || !window.api.getResearchStatus) {
                console.error('API service not available');
                return;
            }

            console.log('Checking research progress for ID:', currentResearchId);
            const data = await window.api.getResearchStatus(currentResearchId);

            if (data) {
                console.log('Got research status update:', data);

                // Update progress UI
                updateProgressUI(data);

                // Check if research is completed
                if (data.status === 'completed' || data.status === 'failed' || data.status === 'cancelled') {
                    handleResearchCompletion(data);
                } else {
                    // Set up polling for status updates as backup for socket
                    if (!pollInterval && (!window.socket || (window.socket.isUsingPolling && window.socket.isUsingPolling()))) {
                        console.log('Setting up polling interval for progress updates');
                        pollInterval = setInterval(checkProgress, 5000);
                    }

                    // Log a message every 5th poll to show activity
                    if (reconnectAttempts % 5 === 0) {
                        console.log('Still monitoring research progress...');
                    }
                    reconnectAttempts++; // Just using this as a counter for logging
                }
            } else {
                console.warn('No data received from API');
            }
        } catch (error) {
            console.error('Error checking research progress:', error);
            if (statusText) {
                statusText.textContent = 'Error checking research status';
            }
        }
    }

    /**
     * Update progress bar
     * @param {HTMLElement} progressBar - The progress bar element
     * @param {number} progress - Progress percentage (0-100)
     */
    function updateProgressBar(progressBar, progress) {
        if (!progressBar) return;

        // Ensure progress is between 0-100
        const percentage = Math.max(0, Math.min(100, Math.floor(progress)));

        // Update progress bar width with transition for smooth animation
        progressBar.style.transition = 'width 0.3s ease-in-out';
        progressBar.style.width = `${percentage}%`;

        // Update percentage text if available
        if (progressPercentage) {
            progressPercentage.textContent = `${percentage}%`;
        }
    }

    /**
     * Update the progress UI with data
     * @param {Object} data - The progress data
     */
    function updateProgressUI(data) {
        console.log('Updating progress UI with data:', data);

        // Update progress bar
        if (data.progress !== undefined && data.progress !== null && progressBar) {
            updateProgressBar(progressBar, data.progress);
        }

        // Update status text with better formatting
        if (data.status && statusText) {
            let formattedStatus;
            if (window.formatting && typeof window.formatting.formatStatus === 'function') {
                formattedStatus = window.formatting.formatStatus(data.status);
            } else {
                // Manual status formatting for better display
                switch (data.status) {
                    case 'in_progress':
                        // Don't show "In Progress" at all in status text
                        formattedStatus = null; // Don't update status text for in_progress
                        break;
                    case 'completed':
                        formattedStatus = 'Completed';
                        break;
                    case 'failed':
                        formattedStatus = 'Failed';
                        break;
                    case 'cancelled':
                        formattedStatus = 'Cancelled';
                        break;
                    default:
                        formattedStatus = data.status.charAt(0).toUpperCase() +
                                        data.status.slice(1).replace(/_/g, ' ');
                }
            }

            // Only update status text if we have a non-empty formatted status
            if (formattedStatus && formattedStatus.trim() !== '') {
                statusText.textContent = formattedStatus;

                // Add status class for styling
                document.querySelectorAll('.status-indicator').forEach(el => {
                    el.className = 'status-indicator';
                    el.classList.add(`status-${data.status}`);
                });
            }
        }

        // Extract current task from progress_log
        if (currentTaskText) {
            let taskMessage = null;

            // Try to parse progress_log to get the latest task
            if (data.progress_log && typeof data.progress_log === 'string') {
                try {
                    const progressLogs = JSON.parse(data.progress_log);
                    if (Array.isArray(progressLogs) && progressLogs.length > 0) {
                        // Get the latest log entry with a non-null message
                        for (let i = progressLogs.length - 1; i >= 0; i--) {
                            if (progressLogs[i].message && progressLogs[i].message.trim() !== '') {
                                taskMessage = progressLogs[i].message;
                                specificProgressMessage = true;
                                break;
                            }
                        }
                    }
                } catch (e) {
                    console.error('Error parsing progress_log for task message:', e);
                }
            }

            // Check various fields that might contain the current task message
            if (!taskMessage) {
                // First check for milestone in log_entry
                if (data.log_entry && data.log_entry.message && (data.log_entry.type === "milestone" || data.log_entry.type === "MILESTONE")) {
                    taskMessage = data.log_entry.message;
                    specificProgressMessage = true;
                } else if (data.current_task) {
                    taskMessage = data.current_task;
                    specificProgressMessage = true;
                } else if (data.message) {
                    taskMessage = data.message;
                    specificProgressMessage = true;
                } else if (data.task) {
                    taskMessage = data.task;
                    specificProgressMessage = true;
                } else if (data.step) {
                    taskMessage = data.step;
                    specificProgressMessage = true;
                } else if (data.phase) {
                    taskMessage = `Phase: ${data.phase}`;
                    specificProgressMessage = true;
                } else {
                    specificProgressMessage = false;
                }
            }

            // Update the task text if we found a message AND it's not just "In Progress"
            if (taskMessage && taskMessage.trim() !== 'In Progress' && taskMessage.trim() !== 'in progress') {
                console.log('Updating current task text to:', taskMessage);
                currentTaskText.textContent = taskMessage;
                // Remember this message to avoid overwriting with generic messages
                currentTaskText.dataset.lastMessage = taskMessage;
            }

            // If no message but we have a status, generate a more descriptive message
            // BUT ONLY if we don't already have a meaningful message displayed
            if (!specificProgressMessage && data.status &&
                (!currentTaskText.dataset.lastMessage || currentTaskText.textContent === 'In Progress')) {
                let statusMsg;
                switch (data.status) {
                    case 'starting':
                        statusMsg = 'Starting research process...';
                        break;
                    case 'searching':
                        statusMsg = 'Searching for information...';
                        break;
                    case 'processing':
                        statusMsg = 'Processing search results...';
                        break;
                    case 'analyzing':
                        statusMsg = 'Analyzing gathered information...';
                        break;
                    case 'writing':
                        statusMsg = 'Writing research report...';
                        break;
                    case 'reviewing':
                        statusMsg = 'Reviewing and finalizing report...';
                        break;
                    case 'in_progress':
                        // Don't overwrite existing content with generic "In Progress" message
                        if (!currentTaskText.dataset.lastMessage || currentTaskText.textContent === '') {
                            statusMsg = 'Performing research...';
                        } else {
                            statusMsg = null; // Skip update
                        }
                        break;
                    default:
                        statusMsg = `${data.status.charAt(0).toUpperCase() + data.status.slice(1).replace('_', ' ')}...`;
                }

                // Only update if we have a new message
                if (statusMsg) {
                    console.log('Using enhanced status-based message:', statusMsg);
                    currentTaskText.textContent = statusMsg;
                    // Don't remember generic messages
                    delete currentTaskText.dataset.lastMessage;
                }
            }
        }

        // Update page title with progress
        if (data.progress !== undefined) {
            document.title = `Research (${Math.floor(data.progress)}%) - Local Deep Research`;
        }

        // Update favicon based on status
        if (window.ui && typeof window.ui.updateFavicon === 'function') {
            window.ui.updateFavicon(data.status || 'in_progress');
        }

        // Show notification if enabled
        if (data.status === 'completed' && notificationsEnabled) {
            showNotification('Research Completed', 'Your research has been completed successfully.');
        }

        // Ensure log entry is added if message exists but no specific log_entry
        if (data.message && window.addConsoleLog && !data.log_entry) {
            console.log('Adding message to console log:', data.message);
            window.addConsoleLog(data.message, determineLogLevel(data.status));
        }
    }

    /**
     * Handle research completion
     * @param {Object} data - The completion data
     */
    function handleResearchCompletion(data) {
        if (isCompleted) return;
        isCompleted = true;

        // Clear polling interval
        if (pollInterval) {
            clearInterval(pollInterval);
            pollInterval = null;
        }

        // Update UI for completion
        if (data.status === 'completed') {
            // Show view results button
            if (viewResultsButton) {
                viewResultsButton.style.display = 'inline-block';
                viewResultsButton.href = URLBuilder.resultsPage(currentResearchId);
            }

            // Hide cancel button
            if (cancelButton) {
                cancelButton.style.display = 'none';
            }
        } else if (data.status === 'failed' || data.status === 'cancelled') {
            // For failed research, try to show the error report if available
            if (data.status === 'failed') {
                if (viewResultsButton) {
                    viewResultsButton.textContent = 'View Error Report';
                    viewResultsButton.href = URLBuilder.resultsPage(currentResearchId);
                    viewResultsButton.style.display = 'inline-block';
                }
            } else {
                // For cancelled research, go back to home
                if (viewResultsButton) {
                    viewResultsButton.textContent = 'Start New Research';
                    viewResultsButton.href = '/';
                    viewResultsButton.style.display = 'inline-block';
                }
            }

            // Hide cancel button
            if (cancelButton) {
                cancelButton.style.display = 'none';
            }
        }
    }


    /**
     * Handle research cancellation
     */
    async function handleCancelResearch() {
        if (!confirm('Are you sure you want to cancel this research?')) {
            return;
        }

        // Disable cancel button
        if (cancelButton) {
            cancelButton.disabled = true;
            cancelButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Cancelling...';
        }

        try {
            if (!window.api || !window.api.terminateResearch) {
                throw new Error('API service not available');
            }

            await window.api.terminateResearch(currentResearchId);

            // Update status manually (in case socket fails)
            if (statusText) {
                statusText.textContent = 'Cancelled';
                document.querySelectorAll('.status-indicator').forEach(el => {
                    el.className = 'status-indicator status-cancelled';
                });
            }

            // Show message
            if (window.ui) {
                window.ui.showMessage('Research has been cancelled.');
            }

            // Update cancel button
            if (cancelButton) {
                cancelButton.style.display = 'none';
            }

            // Show go home button
            if (viewResultsButton) {
                viewResultsButton.textContent = 'Start New Research';
                viewResultsButton.href = '/';
                viewResultsButton.style.display = 'inline-block';
            }

        } catch (error) {
            console.error('Error cancelling research:', error);

            // Re-enable cancel button
            if (cancelButton) {
                cancelButton.disabled = false;
                cancelButton.innerHTML = '<i class="fas fa-stop-circle"></i> Cancel Research';
            }

            // Show error message
            if (window.ui) {
                window.ui.showError('Failed to cancel research. Please try again.');
            }
        }
    }

    /**
     * Show a notification to the user
     * @param {string} title - Notification title
     * @param {string} message - Notification message
     * @param {string} type - Notification type ('info', 'warning', 'error')
     * @param {number} duration - Duration in ms to show in-app notification (0 to not auto-hide)
     */
    function showNotification(title, message, type = 'info', duration = 5000) {
        // First attempt browser notification if enabled
        if ('Notification' in window) {
            // Check if permission is already granted
            if (Notification.permission === 'granted') {
                try {
                    const notification = new Notification(title, {
                        body: message,
                        icon: type === 'error' ? '/static/img/error-icon.png' : '/static/img/favicon.png'
                    });

                    // Auto-close after 10 seconds
                    setTimeout(() => notification.close(), 10000);
                } catch (e) {
                    console.warn('Browser notification failed, falling back to in-app notification', e);
                }
            }
            // Otherwise, request permission (only if it's not been denied)
            else if (Notification.permission !== 'denied') {
                Notification.requestPermission().then(permission => {
                    if (permission === 'granted') {
                        new Notification(title, {
                            body: message,
                            icon: type === 'error' ? '/static/img/error-icon.png' : '/static/img/favicon.png'
                        });
                    }
                });
            }
        }

        // Also show in-app notification
        try {
            // Create or get notification container
            let notificationContainer = document.getElementById('notification-container');
            if (!notificationContainer) {
                notificationContainer = document.createElement('div');
                notificationContainer.id = 'notification-container';
                notificationContainer.style.position = 'fixed';
                notificationContainer.style.top = '20px';
                notificationContainer.style.right = '20px';
                notificationContainer.style.zIndex = '9999';
                notificationContainer.style.width = '350px';
                document.body.appendChild(notificationContainer);
            }

            // Create notification element
            const notificationEl = document.createElement('div');
            notificationEl.className = 'alert alert-dismissible fade show';

            // Set type-specific styling
            switch(type) {
                case 'error':
                    notificationEl.classList.add('alert-danger');
                    break;
                case 'warning':
                    notificationEl.classList.add('alert-warning');
                    break;
                default:
                    notificationEl.classList.add('alert-info');
            }

            // Add title and message
            notificationEl.innerHTML = `
                <strong>${title}</strong>
                <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                <hr>
                <p>${message}</p>
            `;

            // Add to container
            notificationContainer.appendChild(notificationEl);

            // Set up auto-dismiss if duration is provided
            if (duration > 0) {
                setTimeout(() => {
                    notificationEl.classList.remove('show');
                    setTimeout(() => {
                        notificationContainer.removeChild(notificationEl);
                    }, 300); // Wait for fade animation
                }, duration);
            }

            // Set up click to dismiss
            notificationEl.querySelector('.btn-close').addEventListener('click', () => {
                notificationEl.classList.remove('show');
                setTimeout(() => {
                    if (notificationContainer.contains(notificationEl)) {
                        notificationContainer.removeChild(notificationEl);
                    }
                }, 300);
            });

        } catch (e) {
            console.error('Failed to show in-app notification', e);
        }

        // Also log to console
        const logMethod = type === 'error' ? console.error :
                          type === 'warning' ? console.warn : console.log;
        logMethod(`${title}: ${message}`);
    }

    /**
     * Get initial research status from API
     */
    async function getInitialStatus() {
        try {
            const status = await window.api.getResearchStatus(currentResearchId);

            // Process status
            if (status) {
                // If complete, show complete UI
                if (status.status === 'completed') {
                    handleResearchComplete({ research_id: currentResearchId });
                }
                // If error, show error UI
                else if (status.status === 'error') {
                    handleResearchError({
                        research_id: currentResearchId,
                        error: status.message || 'Unknown error'
                    });
                }
                // Otherwise update progress
                else {
                    updateProgressUI(status);
                }
            }
        } catch (error) {
            console.error('Error getting initial status:', error);
            setErrorState('Error loading research status. Please refresh the page to try again.');
        }
    }

    /**
     * Handle research complete event
     * @param {Object} data - Complete event data
     */
    function handleResearchComplete(data) {
        console.log('Research complete received:', data);

        if (data.research_id != currentResearchId) {
            console.warn('Received complete event for different research ID');
            return;
        }

        // Update UI
        setProgressValue(100);
        setStatus('completed');
        setCurrentTask('Research completed successfully');

        // Hide cancel button
        if (cancelButton) {
            cancelButton.style.display = 'none';
        }

        // Show results button
        showResultsButton();

        // Show notification if enabled
        showNotification('Research Complete', 'Your research has been completed successfully.');

        // Update favicon
        updateFavicon(100);

        // Set flag
        researchCompleted = true;
    }

    /**
     * Handle research error event
     * @param {Object} data - Error event data
     */
    function handleResearchError(data) {
        console.error('Research error received:', data);

        if (data.research_id != currentResearchId) {
            console.warn('Received error event for different research ID');
            return;
        }

        // Update UI to error state
        setProgressValue(100);
        setStatus('error');
        setCurrentTask(`Error: ${data.error || 'Unknown error'}`);

        // Add error class to progress bar
        if (progressBar) {
            progressBar.classList.remove('bg-primary', 'bg-success');
            progressBar.classList.add('bg-danger');
        }

        // Hide cancel button
        if (cancelButton) {
            cancelButton.style.display = 'none';
        }

        // Show error report button
        if (viewResultsButton) {
            viewResultsButton.textContent = 'View Error Report';
            viewResultsButton.href = URLBuilder.resultsPage(currentResearchId);
            viewResultsButton.style.display = 'inline-block';
        }

        // Show notification if enabled
        showNotification('Research Error', `There was an error with your research: ${data.error}`);

        // Update favicon
        updateFavicon(100, true);
    }

    /**
     * Set progress bar value
     * @param {number} value - Progress value (0-100)
     */
    function setProgressValue(value) {
        if (!progressBar) return;

        // Ensure value is in range
        value = Math.min(Math.max(value, 0), 100);

        // Update progress bar
        progressBar.style.width = `${value}%`;
        progressBar.setAttribute('aria-valuenow', value);

        // Update classes based on progress
        if (value >= 100) {
            progressBar.classList.remove('bg-primary');
            progressBar.classList.add('bg-success');
        } else {
            progressBar.classList.remove('bg-success', 'bg-danger');
            progressBar.classList.add('bg-primary');
        }
    }

    /**
     * Set status text
     * @param {string} status - Status string
     */
    function setStatus(status) {
        if (!statusText) return;

        let statusDisplay = 'Unknown';

        // Map status to display text
        switch (status) {
            case 'not_started':
                statusDisplay = 'Not Started';
                break;
            case 'in_progress':
                statusDisplay = 'In Progress';
                break;
            case 'completed':
                statusDisplay = 'Completed';
                break;
            case 'cancelled':
                statusDisplay = 'Cancelled';
                break;
            case 'error':
                statusDisplay = 'Error';
                break;
            default:
                statusDisplay = status ? status.charAt(0).toUpperCase() + status.slice(1) : 'Unknown';
        }

        statusText.textContent = statusDisplay;
    }

    /**
     * Set current task text
     * @param {string} task - Current task description
     */
    function setCurrentTask(task) {
        if (!currentTaskText) return;
        currentTaskText.textContent = task || 'No active task';
    }

    /**
     * Set error state for the UI
     * @param {string} message - Error message
     */
    function setErrorState(message) {
        // Update progress UI
        setProgressValue(100);
        setStatus('error');
        setCurrentTask(`Error: ${message}`);

        // Add error class to progress bar
        if (progressBar) {
            progressBar.classList.remove('bg-primary', 'bg-success');
            progressBar.classList.add('bg-danger');
        }

        // Hide cancel button
        if (cancelButton) {
            cancelButton.style.display = 'none';
        }
    }

    /**
     * Show results button
     */
    function showResultsButton() {
        if (!viewResultsButton) return;

        viewResultsButton.style.display = 'inline-block';
        viewResultsButton.disabled = false;
    }

    /**
     * Update favicon with progress
     * @param {number} progress - Progress value (0-100)
     * @param {boolean} isError - Whether there is an error
     */
    function updateFavicon(progress, isError = false) {
        try {
            // Find favicon link or create it if it doesn't exist
            let link = document.querySelector("link[rel='icon']") ||
                       document.querySelector("link[rel='shortcut icon']");

            if (!link) {
                // If no favicon link exists, don't try to create it
                // This avoids error spam in the console
                console.debug('Favicon link not found, skipping dynamic favicon update');
                return;
            }

            // Create canvas for drawing the favicon
            const canvas = document.createElement('canvas');
            canvas.width = 32;
            canvas.height = 32;

            const ctx = canvas.getContext('2d');

            // Draw background
            ctx.fillStyle = '#343a40'; // Dark background
            ctx.beginPath();
            ctx.arc(16, 16, 16, 0, 2 * Math.PI);
            ctx.fill();

            // Draw progress arc
            ctx.beginPath();
            ctx.moveTo(16, 16);
            ctx.arc(16, 16, 14, -0.5 * Math.PI, (-0.5 + 2 * progress / 100) * Math.PI);
            ctx.lineTo(16, 16);

            // Color based on status
            if (isError) {
                ctx.fillStyle = '#dc3545'; // Danger red
            } else if (progress >= 100) {
                ctx.fillStyle = '#28a745'; // Success green
            } else {
                ctx.fillStyle = '#007bff'; // Primary blue
            }

            ctx.fill();

            // Draw center circle
            ctx.fillStyle = '#343a40';
            ctx.beginPath();
            ctx.arc(16, 16, 8, 0, 2 * Math.PI);
            ctx.fill();

            // Draw letter R
            ctx.fillStyle = '#ffffff';
            ctx.font = 'bold 14px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText('R', 16, 16);

            // Update favicon
            link.href = canvas.toDataURL('image/png');

        } catch (error) {
            console.error('Error updating favicon:', error);
            // Failure to update favicon is not critical, so we just log the error
        }
    }

    // Initialize on page load
    document.addEventListener('DOMContentLoaded', initializeProgress);

    // Expose components publicly for testing and debugging
    window.progressComponent = {
        checkProgress,
        handleCancelResearch
    };

    // Add global error handler for WebSocket errors
    window.addEventListener('error', function(event) {
        if (event.message && event.message.includes('WebSocket') && event.message.includes('frame header')) {
            console.warn('Caught WebSocket frame header error, suppressing');
            event.preventDefault();
            return true; // Prevent the error from showing in console
        }
    });

    // Expose notification function globally
    window.showNotification = showNotification;
})();
