/**
 * Download Queue Management - JavaScript Application
 */

class QueueManager {
    constructor() {
        this.socket = null;
        this.refreshInterval = null;
        this.pendingProgressUpdates = new Map(); // Store progress updates waiting for cards

        this.init();
    }

    init() {
        this.initSocket();
        this.bindEvents();
        this.initTheme();
        // Remove polling - use WebSocket events for real-time updates
        // this.startRefreshTimer(); // ← REMOVED
        this.loadQueueData(); // Load initial data once
    }

    initSocket() {
        this.socket = io();

        // Handle initial connection message from server
        this.socket.on('connected', (data) => {
            console.log('WebSocket connection confirmed', data);
        });

        this.socket.on('connect', () => {
            console.log('Connected to server');
            
            // Subscribe to rooms for targeted updates
            // Valid rooms: downloads, queue, scan, system, errors
            this.socket.join('downloads');
            this.socket.join('queue');
            
            this.showToast('Connected to server', 'success');
        });

        this.socket.on('disconnect', () => {
            console.log('Disconnected from server');
            this.showToast('Disconnected from server', 'warning');
        });

        // Queue update events - handle both old and new message types
        this.socket.on('queue_updated', (data) => {
            this.updateQueueDisplay(data);
        });
        this.socket.on('queue_status', (data) => {
            // New backend sends queue_status messages with nested structure
            if (data.status && data.statistics) {
                // Transform nested structure to flat structure
                const queueData = {
                    ...data.status,
                    statistics: data.statistics
                };
                this.updateQueueDisplay(queueData);
            } else if (data.queue_status) {
                this.updateQueueDisplay(data.queue_status);
            } else {
                this.updateQueueDisplay(data);
            }
        });

        // Download queue events
        this.socket.on('download_started', () => {
            this.showToast('Download queue started', 'success');
            // Full reload needed - queue structure changed
            this.loadQueueData();
        });
        this.socket.on('queue_started', () => {
            this.showToast('Download queue started', 'success');
            // Full reload needed - queue structure changed
            this.loadQueueData();
        });

        this.socket.on('download_progress', (data) => {
            // Update progress in real-time without reloading all data
            console.log('Received download progress:', data);
            this.updateDownloadProgress(data);
        });

        // Handle both old and new download completion events
        const handleDownloadComplete = (data) => {
            const serieName = data.serie_name || data.serie || 'Unknown';
            const episode = data.episode || '';
            this.showToast(`Completed: ${serieName}${episode ? ' - Episode ' + episode : ''}`, 'success');
            
            // Clear any pending progress updates for this download
            const downloadId = data.item_id || data.download_id || data.id;
            if (downloadId) {
                this.pendingProgressUpdates.delete(downloadId);
            }
            
            // Full reload needed - item moved from active to completed
            this.loadQueueData();
        };
        this.socket.on('download_completed', handleDownloadComplete);
        this.socket.on('download_complete', handleDownloadComplete);

        // Handle both old and new download error events
        const handleDownloadError = (data) => {
            const message = data.error || data.message || 'Unknown error';
            this.showToast(`Download failed: ${message}`, 'error');
            
            // Clear any pending progress updates for this download
            const downloadId = data.item_id || data.download_id || data.id;
            if (downloadId) {
                this.pendingProgressUpdates.delete(downloadId);
            }
            
            // Full reload needed - item moved from active to failed
            this.loadQueueData();
        };
        this.socket.on('download_error', handleDownloadError);
        this.socket.on('download_failed', handleDownloadError);

        this.socket.on('download_queue_completed', () => {
            this.showToast('All downloads completed!', 'success');
            // Full reload needed - queue state changed
            this.loadQueueData();
        });
        
        this.socket.on('queue_completed', () => {
            this.showToast('All downloads completed!', 'success');
            // Full reload needed - queue state changed
            this.loadQueueData();
        });

        this.socket.on('download_stop_requested', () => {
            this.showToast('Stopping downloads...', 'info');
        });

        // Handle both old and new queue stopped events
        const handleQueueStopped = () => {
            this.showToast('Download queue stopped', 'success');
            // Full reload needed - queue state changed
            this.loadQueueData();
        };
        this.socket.on('download_stopped', handleQueueStopped);
        this.socket.on('queue_stopped', handleQueueStopped);

        // Handle queue paused/resumed
        this.socket.on('queue_paused', () => {
            this.showToast('Queue paused', 'info');
            // Full reload needed - queue state changed
            this.loadQueueData();
        });

        this.socket.on('queue_resumed', () => {
            this.showToast('Queue resumed', 'success');
            // Full reload needed - queue state changed
            this.loadQueueData();
        });
    }

    bindEvents() {
        // Theme toggle
        document.getElementById('theme-toggle').addEventListener('click', () => {
            this.toggleTheme();
        });

        // Queue management actions
        document.getElementById('clear-completed-btn').addEventListener('click', () => {
            this.clearQueue('completed');
        });

        document.getElementById('clear-failed-btn').addEventListener('click', () => {
            this.clearQueue('failed');
        });

        document.getElementById('clear-pending-btn').addEventListener('click', () => {
            this.clearQueue('pending');
        });

        document.getElementById('retry-all-btn').addEventListener('click', () => {
            this.retryAllFailed();
        });

        // Download controls
        document.getElementById('start-queue-btn').addEventListener('click', () => {
            this.startDownload();
        });

        document.getElementById('stop-queue-btn').addEventListener('click', () => {
            this.stopDownloads();
        });

        // Modal events
        document.getElementById('close-confirm').addEventListener('click', () => {
            this.hideConfirmModal();
        });

        document.getElementById('confirm-cancel').addEventListener('click', () => {
            this.hideConfirmModal();
        });

        document.querySelector('#confirm-modal .modal-overlay').addEventListener('click', () => {
            this.hideConfirmModal();
        });

        // Logout functionality
        document.getElementById('logout-btn').addEventListener('click', () => {
            this.logout();
        });
    }

    initTheme() {
        const savedTheme = localStorage.getItem('theme') || 'light';
        this.setTheme(savedTheme);
    }

    setTheme(theme) {
        document.documentElement.setAttribute('data-theme', theme);
        localStorage.setItem('theme', theme);

        const themeIcon = document.querySelector('#theme-toggle i');
        themeIcon.className = theme === 'light' ? 'fas fa-moon' : 'fas fa-sun';
    }

    toggleTheme() {
        const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
        const newTheme = currentTheme === 'light' ? 'dark' : 'light';
        this.setTheme(newTheme);
    }

    startRefreshTimer() {
        // Refresh every 2 seconds
        this.refreshInterval = setInterval(() => {
            this.loadQueueData();
        }, 2000);
    }

    async loadQueueData() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/queue/status');
            if (!response) {
                return;
            }

            const data = await response.json();
            
            // API returns nested structure with 'status' and 'statistics'
            // Transform it to the expected flat structure
            const queueData = {
                ...data.status,  // includes is_running, active_downloads, pending_queue, etc.
                statistics: data.statistics
            };
            
            this.updateQueueDisplay(queueData);
            
            // Process any pending progress updates after queue is loaded
            this.processPendingProgressUpdates();

        } catch (error) {
            console.error('Error loading queue data:', error);
        }
    }

    updateQueueDisplay(data) {
        // Update statistics
        this.updateStatistics(data.statistics, data);

        // Update active downloads
        this.renderActiveDownloads(data.active_downloads || []);

        // Update pending queue
        this.renderPendingQueue(data.pending_queue || []);

        // Update completed downloads
        this.renderCompletedDownloads(data.completed_downloads || []);

        // Update failed downloads
        this.renderFailedDownloads(data.failed_downloads || []);

        // Update button states
        this.updateButtonStates(data);
    }

    updateStatistics(stats, data) {
        // Ensure stats object exists
        const statistics = stats || {};
        
        document.getElementById('total-items').textContent = statistics.total_items || 0;
        document.getElementById('pending-items').textContent = (data.pending_queue || []).length;
        document.getElementById('completed-items').textContent = statistics.completed_items || 0;
        document.getElementById('failed-items').textContent = statistics.failed_items || 0;

        // Update section counts
        document.getElementById('queue-count').textContent = (data.pending_queue || []).length;
        document.getElementById('completed-count').textContent = statistics.completed_items || 0;
        document.getElementById('failed-count').textContent = statistics.failed_items || 0;

        document.getElementById('current-speed').textContent = statistics.current_speed || '0 MB/s';
        document.getElementById('average-speed').textContent = statistics.average_speed || '0 MB/s';

        // Format ETA
        const etaElement = document.getElementById('eta-time');
        if (statistics.eta) {
            const eta = new Date(statistics.eta);
            const now = new Date();
            const diffMs = eta - now;

            if (diffMs > 0) {
                const hours = Math.floor(diffMs / (1000 * 60 * 60));
                const minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
                etaElement.textContent = `${hours}h ${minutes}m`;
            } else {
                etaElement.textContent = 'Calculating...';
            }
        } else {
            etaElement.textContent = '--:--';
        }
    }

    /**
     * Update download progress in real-time
     * @param {Object} data - Progress data from WebSocket
     */
    updateDownloadProgress(data) {
        console.log('updateDownloadProgress called with:', JSON.stringify(data, null, 2));
        
        // Extract download ID - prioritize metadata.item_id (actual item ID)
        // Progress service sends id with "download_" prefix, but we need the actual item ID
        let downloadId = null;
        
        // First try metadata.item_id (this is the actual download item ID)
        if (data.metadata && data.metadata.item_id) {
            downloadId = data.metadata.item_id;
        }
        
        // Fallback to other ID fields
        if (!downloadId) {
            downloadId = data.item_id || data.download_id;
        }
        
        // If ID starts with "download_", extract the actual ID
        if (!downloadId && data.id) {
            if (data.id.startsWith('download_')) {
                downloadId = data.id.substring(9); // Remove "download_" prefix
            } else {
                downloadId = data.id;
            }
        }
        
        // Check if data is wrapped in another 'data' property
        if (!downloadId && data.data) {
            if (data.data.metadata && data.data.metadata.item_id) {
                downloadId = data.data.metadata.item_id;
            } else if (data.data.item_id) {
                downloadId = data.data.item_id;
            } else if (data.data.id && data.data.id.startsWith('download_')) {
                downloadId = data.data.id.substring(9);
            } else {
                downloadId = data.data.id || data.data.download_id;
            }
            data = data.data; // Use nested data
        }
        
        if (!downloadId) {
            console.warn('No download ID in progress data');
            console.warn('Data structure:', data);
            console.warn('Available keys:', Object.keys(data));
            return;
        }

        console.log(`Looking for download card with ID: ${downloadId}`);

        // Find the download card in active downloads
        const card = document.querySelector(`[data-download-id="${downloadId}"]`);
        if (!card) {
            // Card not found - store update and reload queue
            console.warn(`Download card not found for ID: ${downloadId}`);
            
            // Debug: Log all existing download cards
            const allCards = document.querySelectorAll('[data-download-id]');
            console.log(`Found ${allCards.length} download cards:`);
            allCards.forEach(c => console.log(`  - ${c.getAttribute('data-download-id')}`));
            
            // Store this progress update to retry after queue loads
            console.log(`Storing progress update for ${downloadId} to retry after reload`);
            this.pendingProgressUpdates.set(downloadId, data);
            
            // Reload queue to sync state
            console.log('Reloading queue to sync state...');
            this.loadQueueData();
            return;
        }

        console.log(`Found download card for ID: ${downloadId}, updating progress`);

        // Extract progress information - handle both ProgressService and yt-dlp formats
        const progress = data.progress || data;
        const percent = progress.percent || 0;
        const metadata = progress.metadata || data.metadata || {};
        
        // Check if we have detailed yt-dlp progress (downloaded_mb, total_mb, speed_mbps)
        // or basic ProgressService progress (current, total)
        let downloaded, total, speed;
        
        if (progress.downloaded_mb !== undefined && progress.total_mb !== undefined) {
            // yt-dlp detailed format
            downloaded = progress.downloaded_mb.toFixed(1);
            total = progress.total_mb.toFixed(1);
            speed = progress.speed_mbps ? progress.speed_mbps.toFixed(1) : '0.0';
        } else if (progress.current !== undefined && progress.total !== undefined) {
            // ProgressService basic format - convert bytes to MB
            downloaded = (progress.current / (1024 * 1024)).toFixed(1);
            total = progress.total > 0 ? (progress.total / (1024 * 1024)).toFixed(1) : 'Unknown';
            // Check for speed in metadata
            speed = metadata.speed_mbps ? metadata.speed_mbps.toFixed(1) : '0.0';
        } else {
            // Fallback
            downloaded = '0.0';
            total = 'Unknown';
            speed = metadata.speed_mbps ? metadata.speed_mbps.toFixed(1) : '0.0';
        }

        // Update progress bar
        const progressFill = card.querySelector('.progress-fill');
        if (progressFill) {
            progressFill.style.width = `${percent}%`;
        }

        // Update progress text
        const progressInfo = card.querySelector('.progress-info');
        if (progressInfo) {
            const percentSpan = progressInfo.querySelector('span:first-child');
            const speedSpan = progressInfo.querySelector('.download-speed');
            
            if (percentSpan) {
                percentSpan.textContent = percent > 0 ? `${percent.toFixed(1)}%` : 'Starting...';
            }
            if (speedSpan) {
                speedSpan.textContent = `${speed} MB/s`;
            }
        }

        console.log(`Updated progress for ${downloadId}: ${percent.toFixed(1)}%`);
    }

    processPendingProgressUpdates() {
        if (this.pendingProgressUpdates.size === 0) {
            return;
        }

        console.log(`Processing ${this.pendingProgressUpdates.size} pending progress updates...`);
        
        // Process each pending update
        const processed = [];
        for (const [downloadId, data] of this.pendingProgressUpdates.entries()) {
            // Check if card now exists
            const card = document.querySelector(`[data-download-id="${downloadId}"]`);
            if (card) {
                console.log(`Retrying progress update for ${downloadId}`);
                this.updateDownloadProgress(data);
                processed.push(downloadId);
            } else {
                console.log(`Card still not found for ${downloadId}, will retry on next reload`);
            }
        }
        
        // Remove processed updates
        processed.forEach(id => this.pendingProgressUpdates.delete(id));
        
        if (processed.length > 0) {
            console.log(`Successfully processed ${processed.length} pending updates`);
        }
    }

    renderActiveDownloads(downloads) {
        const container = document.getElementById('active-downloads');

        if (downloads.length === 0) {
            container.innerHTML = `
                <div class="empty-state">
                    <i class="fas fa-pause-circle"></i>
                    <p>No active downloads</p>
                </div>
            `;
            return;
        }

        container.innerHTML = downloads.map(download => this.createActiveDownloadCard(download)).join('');
    }

    createActiveDownloadCard(download) {
        const progress = download.progress || {};
        const progressPercent = progress.percent || 0;
        const speed = progress.speed_mbps ? `${progress.speed_mbps.toFixed(1)} MB/s` : '0 MB/s';
        const downloaded = progress.downloaded_mb ? `${progress.downloaded_mb.toFixed(1)} MB` : '0.0';
        const total = progress.total_mb ? `${progress.total_mb.toFixed(1)} MB` : '0.0';

        return `
            <div class="download-card active" data-download-id="${download.id}">
                <div class="download-header">
                    <div class="download-info">
                        <h4>${this.escapeHtml(download.serie_name)}</h4>
                        <p>${this.escapeHtml(download.episode.season)}x${String(download.episode.episode).padStart(2, '0')} - ${this.escapeHtml(download.episode.title || 'Episode ' + download.episode.episode)}</p>
                    </div>
                </div>
                <div class="download-progress">
                    <div class="progress-bar">
                        <div class="progress-fill" style="width: ${progressPercent}%"></div>
                    </div>
                    <div class="progress-info">
                        <span>${progressPercent > 0 ? `${progressPercent.toFixed(1)}%` : 'Starting...'}</span>
                        <span class="download-speed">${speed}</span>
                    </div>
                </div>
            </div>
        `;
    }

    renderPendingQueue(queue) {
        const container = document.getElementById('pending-queue');

        if (queue.length === 0) {
            container.innerHTML = `
                <div class="empty-state">
                    <i class="fas fa-list"></i>
                    <p>No items in queue</p>
                    <small>Add episodes from the main page to start downloading</small>
                </div>
            `;
            return;
        }

        container.innerHTML = queue.map((item, index) => this.createPendingQueueCard(item, index)).join('');
    }

    createPendingQueueCard(download, index) {
        const addedAt = new Date(download.added_at).toLocaleString();

        return `
            <div class="download-card pending" 
                 data-id="${download.id}" 
                 data-index="${index}">
                <div class="queue-position">${index + 1}</div>
                <div class="download-header">
                    <div class="download-info">
                        <h4>${this.escapeHtml(download.serie_name)}</h4>
                        <p>${this.escapeHtml(download.episode.season)}x${String(download.episode.episode).padStart(2, '0')} - ${this.escapeHtml(download.episode.title || 'Episode ' + download.episode.episode)}</p>
                        <small>Added: ${addedAt}</small>
                    </div>
                    <div class="download-actions">
                        <button class="btn btn-small btn-secondary" onclick="queueManager.removeFromQueue('${download.id}')">
                            <i class="fas fa-trash"></i>
                        </button>
                    </div>
                </div>
            </div>
        `;
    }

    renderCompletedDownloads(downloads) {
        const container = document.getElementById('completed-downloads');

        if (downloads.length === 0) {
            container.innerHTML = `
                <div class="empty-state">
                    <i class="fas fa-check-circle"></i>
                    <p>No completed downloads</p>
                </div>
            `;
            return;
        }

        container.innerHTML = downloads.map(download => this.createCompletedDownloadCard(download)).join('');
    }

    createCompletedDownloadCard(download) {
        const completedAt = new Date(download.completed_at).toLocaleString();
        const duration = this.calculateDuration(download.started_at, download.completed_at);

        return `
            <div class="download-card completed">
                <div class="download-header">
                    <div class="download-info">
                        <h4>${this.escapeHtml(download.serie_name)}</h4>
                        <p>${this.escapeHtml(download.episode.season)}x${String(download.episode.episode).padStart(2, '0')} - ${this.escapeHtml(download.episode.title || 'Episode ' + download.episode.episode)}</p>
                        <small>Completed: ${completedAt} (${duration})</small>
                    </div>
                    <div class="download-status">
                        <i class="fas fa-check-circle text-success"></i>
                    </div>
                </div>
            </div>
        `;
    }

    renderFailedDownloads(downloads) {
        const container = document.getElementById('failed-downloads');

        if (downloads.length === 0) {
            container.innerHTML = `
                <div class="empty-state">
                    <i class="fas fa-check-circle text-success"></i>
                    <p>No failed downloads</p>
                </div>
            `;
            return;
        }

        container.innerHTML = downloads.map(download => this.createFailedDownloadCard(download)).join('');
    }

    createFailedDownloadCard(download) {
        const failedAt = new Date(download.completed_at).toLocaleString();
        const retryCount = download.retry_count || 0;

        return `
            <div class="download-card failed" data-id="${download.id}">
                <div class="download-header">
                    <div class="download-info">
                        <h4>${this.escapeHtml(download.serie_name)}</h4>
                        <p>${this.escapeHtml(download.episode.season)}x${String(download.episode.episode).padStart(2, '0')} - ${this.escapeHtml(download.episode.title || 'Episode ' + download.episode.episode)}</p>
                        <small>Failed: ${failedAt} ${retryCount > 0 ? `(Retry ${retryCount})` : ''}</small>
                        ${download.error ? `<small class="error-message">${this.escapeHtml(download.error)}</small>` : ''}
                    </div>
                    <div class="download-actions">
                        <button class="btn btn-small btn-warning" onclick="queueManager.retryDownload('${download.id}')">
                            <i class="fas fa-redo"></i>
                        </button>
                        <button class="btn btn-small btn-secondary" onclick="queueManager.removeFailedDownload('${download.id}')">
                            <i class="fas fa-trash"></i>
                        </button>
                    </div>
                </div>
            </div>
        `;
    }

    async removeFailedDownload(downloadId) {
        await this.removeFromQueue(downloadId);
    }

    updateButtonStates(data) {
        const hasActive = (data.active_downloads || []).length > 0;
        const hasPending = (data.pending_queue || []).length > 0;
        const hasFailed = (data.failed_downloads || []).length > 0;
        const hasCompleted = (data.completed_downloads || []).length > 0;

        console.log('Button states update:', {
            hasPending,
            pendingCount: (data.pending_queue || []).length,
            hasActive,
            hasFailed,
            hasCompleted
        });

        // Enable start button only if there are pending items and no active downloads
        document.getElementById('start-queue-btn').disabled = !hasPending || hasActive;

        // Show/hide start/stop buttons based on whether downloads are active
        if (hasActive) {
            document.getElementById('start-queue-btn').style.display = 'none';
            document.getElementById('stop-queue-btn').style.display = 'inline-flex';
            document.getElementById('stop-queue-btn').disabled = false;
        } else {
            document.getElementById('stop-queue-btn').style.display = 'none';
            document.getElementById('start-queue-btn').style.display = 'inline-flex';
        }

        document.getElementById('retry-all-btn').disabled = !hasFailed;
        document.getElementById('clear-completed-btn').disabled = !hasCompleted;
        document.getElementById('clear-failed-btn').disabled = !hasFailed;
        
        // Update clear pending button if it exists
        const clearPendingBtn = document.getElementById('clear-pending-btn');
        if (clearPendingBtn) {
            clearPendingBtn.disabled = !hasPending;
            console.log('Clear pending button updated:', { disabled: !hasPending, hasPending });
        } else {
            console.error('Clear pending button not found in DOM');
        }
    }

    async clearQueue(type) {
        const titles = {
            completed: 'Clear Completed Downloads',
            failed: 'Clear Failed Downloads',
            pending: 'Remove All Pending Downloads'
        };

        const messages = {
            completed: 'Are you sure you want to clear all completed downloads?',
            failed: 'Are you sure you want to clear all failed downloads?',
            pending: 'Are you sure you want to remove all pending downloads from the queue?'
        };

        const confirmed = await this.showConfirmModal(titles[type], messages[type]);
        if (!confirmed) return;

        try {
            if (type === 'completed') {
                const response = await this.makeAuthenticatedRequest('/api/queue/completed', {
                    method: 'DELETE'
                });

                if (!response) return;
                const data = await response.json();

                this.showToast(`Cleared ${data.count} completed downloads`, 'success');
                this.loadQueueData();
            } else if (type === 'failed') {
                const response = await this.makeAuthenticatedRequest('/api/queue/failed', {
                    method: 'DELETE'
                });

                if (!response) return;
                const data = await response.json();

                this.showToast(`Cleared ${data.count} failed downloads`, 'success');
                this.loadQueueData();
            } else if (type === 'pending') {
                const response = await this.makeAuthenticatedRequest('/api/queue/pending', {
                    method: 'DELETE'
                });

                if (!response) return;
                const data = await response.json();

                this.showToast(`Removed ${data.count} pending downloads`, 'success');
                this.loadQueueData();
            }

        } catch (error) {
            console.error('Error clearing queue:', error);
            this.showToast('Failed to clear queue', 'error');
        }
    }

    async retryDownload(downloadId) {
        try {
            const response = await this.makeAuthenticatedRequest('/api/queue/retry', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ item_ids: [downloadId] })  // New API expects item_ids array
            });

            if (!response) return;
            const data = await response.json();

            this.showToast(`Retried ${data.retried_count} download(s)`, 'success');
            this.loadQueueData();

        } catch (error) {
            console.error('Error retrying download:', error);
            this.showToast('Failed to retry download', 'error');
        }
    }

    async retryAllFailed() {
        const confirmed = await this.showConfirmModal('Retry All Failed Downloads', 'Are you sure you want to retry all failed downloads?');
        if (!confirmed) return;

        try {
            // Get all failed download IDs
            const failedCards = document.querySelectorAll('#failed-downloads .download-card.failed');
            const itemIds = Array.from(failedCards).map(card => card.dataset.id).filter(id => id);

            if (itemIds.length === 0) {
                this.showToast('No failed downloads to retry', 'info');
                return;
            }

            const response = await this.makeAuthenticatedRequest('/api/queue/retry', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ item_ids: itemIds })
            });

            if (!response) return;
            const data = await response.json();

            this.showToast(`Retried ${data.retried_count || itemIds.length} download(s)`, 'success');
            this.loadQueueData();

        } catch (error) {
            console.error('Error retrying failed downloads:', error);
            this.showToast('Failed to retry downloads', 'error');
        }
    }

    async removeFromQueue(downloadId) {
        try {
            const response = await this.makeAuthenticatedRequest(`/api/queue/${downloadId}`, {
                method: 'DELETE'
            });

            if (!response) return;

            if (response.status === 204) {
                this.showToast('Download removed from queue', 'success');
                this.loadQueueData();
            } else {
                this.showToast(data.message, 'error');
            }

        } catch (error) {
            console.error('Error removing from queue:', error);
            this.showToast('Failed to remove from queue', 'error');
        }
    }

    calculateDuration(startTime, endTime) {
        const start = new Date(startTime);
        const end = new Date(endTime);
        const diffMs = end - start;

        const minutes = Math.floor(diffMs / (1000 * 60));
        const seconds = Math.floor((diffMs % (1000 * 60)) / 1000);

        return `${minutes}m ${seconds}s`;
    }

    async startDownload() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/queue/start', {
                method: 'POST'
            });

            if (!response) return;
            const data = await response.json();

            if (data.status === 'success') {
                this.showToast('Queue processing started - all items will download automatically', 'success');

                // Update UI
                document.getElementById('start-queue-btn').style.display = 'none';
                document.getElementById('stop-queue-btn').style.display = 'inline-flex';
                document.getElementById('stop-queue-btn').disabled = false;
                
                this.loadQueueData(); // Refresh display
            } else {
                this.showToast(`Failed to start queue: ${data.message || 'Unknown error'}`, 'error');
            }
        } catch (error) {
            console.error('Error starting queue:', error);
            this.showToast('Failed to start queue processing', 'error');
        }
    }

    async stopDownloads() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/queue/stop', {
                method: 'POST'
            });

            if (!response) return;
            const data = await response.json();

            if (data.status === 'success') {
                this.showToast('Queue processing stopped', 'success');

                // Update UI
                document.getElementById('stop-queue-btn').style.display = 'none';
                document.getElementById('start-queue-btn').style.display = 'inline-flex';
                document.getElementById('start-queue-btn').disabled = false;
                
                this.loadQueueData(); // Refresh display
            } else {
                this.showToast(`Failed to stop queue: ${data.message}`, 'error');
            }
        } catch (error) {
            console.error('Error stopping queue:', error);
            this.showToast('Failed to stop queue', 'error');
        }
    }

    async makeAuthenticatedRequest(url, options = {}) {
        // Get JWT token from localStorage
        const token = localStorage.getItem('access_token');
        
        // Check if token exists
        if (!token) {
            window.location.href = '/login';
            return null;
        }
        
        // Include Authorization header with Bearer token
        const requestOptions = {
            credentials: 'same-origin',
            ...options,
            headers: {
                'Authorization': `Bearer ${token}`,
                ...options.headers
            }
        };

        const response = await fetch(url, requestOptions);

        if (response.status === 401) {
            // Token is invalid or expired, clear it and redirect to login
            localStorage.removeItem('access_token');
            localStorage.removeItem('token_expires_at');
            window.location.href = '/login';
            return null;
        }

        return response;
    }

    showConfirmModal(title, message) {
        return new Promise((resolve) => {
            document.getElementById('confirm-title').textContent = title;
            document.getElementById('confirm-message').textContent = message;
            document.getElementById('confirm-modal').classList.remove('hidden');

            const handleConfirm = () => {
                cleanup();
                resolve(true);
            };

            const handleCancel = () => {
                cleanup();
                resolve(false);
            };

            const cleanup = () => {
                document.getElementById('confirm-ok').removeEventListener('click', handleConfirm);
                document.getElementById('confirm-cancel').removeEventListener('click', handleCancel);
                this.hideConfirmModal();
            };

            document.getElementById('confirm-ok').addEventListener('click', handleConfirm);
            document.getElementById('confirm-cancel').addEventListener('click', handleCancel);
        });
    }

    hideConfirmModal() {
        document.getElementById('confirm-modal').classList.add('hidden');
    }

    showToast(message, type = 'info') {
        const container = document.getElementById('toast-container');
        const toast = document.createElement('div');

        toast.className = `toast ${type}`;
        toast.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: center;">
                <span>${this.escapeHtml(message)}</span>
                <button onclick="this.parentElement.parentElement.remove()" style="background: none; border: none; color: var(--color-text-secondary); cursor: pointer; padding: 0; margin-left: 1rem;">
                    <i class="fas fa-times"></i>
                </button>
            </div>
        `;

        container.appendChild(toast);

        setTimeout(() => {
            if (toast.parentElement) {
                toast.remove();
            }
        }, 5000);
    }

    escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    async logout() {
        try {
            const response = await fetch('/api/auth/logout', { method: 'POST' });
            const data = await response.json();

            if (data.status === 'success') {
                this.showToast('Logged out successfully', 'success');
                setTimeout(() => {
                    window.location.href = '/login';
                }, 1000);
            } else {
                this.showToast('Logout failed', 'error');
            }
        } catch (error) {
            console.error('Logout error:', error);
            this.showToast('Logout failed', 'error');
        }
    }
}

// Initialize the application when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
    window.queueManager = new QueueManager();
});

// Global reference for inline event handlers
window.queueManager = null;