/**
 * AniWorld Manager - Main JavaScript Application
 * Implements Fluent UI design principles with modern web app functionality
 */

class AniWorldApp {
    constructor() {
        this.socket = null;
        this.selectedSeries = new Set(); // Uses 'key' as identifier
        this.seriesData = []; // Series objects with 'key' as primary identifier
        this.filteredSeriesData = [];
        this.isConnected = false;
        this.isDownloading = false;
        this.isPaused = false;
        this.localization = new Localization();
        this.showMissingOnly = false;
        this.sortAlphabetical = false;

        this.init();
    }

    async init() {
        await this.checkAuthentication();
        this.initSocket();
        this.bindEvents();
        this.loadSeries();
        this.initTheme();
        this.updateConnectionStatus();
        // Check scan status on page load (in case socket connect event is delayed)
        this.checkActiveScanStatus();
    }

    async checkAuthentication() {
        // Don't check authentication if we're already on login or setup pages
        const currentPath = window.location.pathname;
        if (currentPath === '/login' || currentPath === '/setup') {
            return;
        }

        try {
            // First check if we have a token
            const token = localStorage.getItem('access_token');
            console.log('checkAuthentication: token exists =', !!token);
            
            if (!token) {
                console.log('checkAuthentication: No token found, redirecting to /login');
                window.location.href = '/login';
                return;
            }
            
            // Build request with token
            const headers = {
                'Authorization': `Bearer ${token}`
            };
            
            const response = await fetch('/api/auth/status', { headers });
            console.log('checkAuthentication: response status =', response.status);
            
            if (!response.ok) {
                console.log('checkAuthentication: Response not OK, status =', response.status);
                throw new Error(`HTTP ${response.status}`);
            }
            
            const data = await response.json();
            console.log('checkAuthentication: data =', data);

            if (!data.configured) {
                // No master password set, redirect to setup
                console.log('checkAuthentication: Not configured, redirecting to /setup');
                window.location.href = '/setup';
                return;
            }

            if (!data.authenticated) {
                // Not authenticated, redirect to login
                console.log('checkAuthentication: Not authenticated, redirecting to /login');
                localStorage.removeItem('access_token');
                localStorage.removeItem('token_expires_at');
                window.location.href = '/login';
                return;
            }

            // User is authenticated, show logout button
            console.log('checkAuthentication: Authenticated successfully');
            const logoutBtn = document.getElementById('logout-btn');
            if (logoutBtn) {
                logoutBtn.style.display = 'block';
            }
        } catch (error) {
            console.error('Authentication check failed:', error);
            // On error, clear token and redirect to login
            localStorage.removeItem('access_token');
            localStorage.removeItem('token_expires_at');
            window.location.href = '/login';
        }
    }

    async logout() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/auth/logout', { method: 'POST' });
            
            // Clear tokens from localStorage
            localStorage.removeItem('access_token');
            localStorage.removeItem('token_expires_at');

            if (response && response.ok) {
                const data = await response.json();
                if (data.status === 'ok') {
                    this.showToast('Logged out successfully', 'success');
                } else {
                    this.showToast('Logged out', 'success');
                }
            } else {
                // Even if the API fails, we cleared the token locally
                this.showToast('Logged out', 'success');
            }
            
            setTimeout(() => {
                window.location.href = '/login';
            }, 1000);
        } catch (error) {
            console.error('Logout error:', error);
            // Clear token even on error
            localStorage.removeItem('access_token');
            localStorage.removeItem('token_expires_at');
            this.showToast('Logged out', 'success');
            setTimeout(() => {
                window.location.href = '/login';
            }, 1000);
        }
    }

    toggleMissingOnlyFilter() {
        this.showMissingOnly = !this.showMissingOnly;
        const button = document.getElementById('show-missing-only');

        button.setAttribute('data-active', this.showMissingOnly);
        button.classList.toggle('active', this.showMissingOnly);

        const icon = button.querySelector('i');
        const text = button.querySelector('span');

        if (this.showMissingOnly) {
            icon.className = 'fas fa-filter-circle-xmark';
            text.textContent = 'Show All Series';
        } else {
            icon.className = 'fas fa-filter';
            text.textContent = 'Missing Episodes Only';
        }

        this.applyFiltersAndSort();
        this.renderSeries();
        this.clearSelection(); // Clear selection when filter changes
    }

    toggleAlphabeticalSort() {
        this.sortAlphabetical = !this.sortAlphabetical;
        const button = document.getElementById('sort-alphabetical');

        button.setAttribute('data-active', this.sortAlphabetical);
        button.classList.toggle('active', this.sortAlphabetical);

        const icon = button.querySelector('i');
        const text = button.querySelector('span');

        if (this.sortAlphabetical) {
            icon.className = 'fas fa-sort-alpha-up';
            text.textContent = 'Default Sort';
        } else {
            icon.className = 'fas fa-sort-alpha-down';
            text.textContent = 'A-Z Sort';
        }

        this.applyFiltersAndSort();
        this.renderSeries();
    }

    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', () => {
            this.isConnected = true;
            console.log('Connected to server');
            
            // Subscribe to rooms for targeted updates
            // Valid rooms: downloads, queue, scan, system, errors
            this.socket.join('scan');
            this.socket.join('downloads');
            this.socket.join('queue');
            
            this.showToast(this.localization.getText('connected-server'), 'success');
            this.updateConnectionStatus();
            
            // Check if a scan is currently in progress (e.g., after page reload)
            this.checkActiveScanStatus();
        });

        this.socket.on('disconnect', () => {
            this.isConnected = false;
            console.log('Disconnected from server');
            this.showToast(this.localization.getText('disconnected-server'), 'warning');
            this.updateConnectionStatus();
        });

        // Scan events - handle new detailed scan progress overlay
        this.socket.on('scan_started', (data) => {
            console.log('Scan started:', data);
            this.showScanProgressOverlay(data);
            this.updateProcessStatus('rescan', true);
        });

        this.socket.on('scan_progress', (data) => {
            console.log('Scan progress:', data);
            this.updateScanProgressOverlay(data);
        });

        // Handle both 'scan_completed' (legacy) and 'scan_complete' (new backend)
        const handleScanComplete = (data) => {
            console.log('Scan completed:', data);
            this.hideScanProgressOverlay(data);
            this.showToast('Scan completed successfully', 'success');
            this.updateProcessStatus('rescan', false);
            this.loadSeries();
        };
        this.socket.on('scan_completed', handleScanComplete);
        this.socket.on('scan_complete', handleScanComplete);

        // Handle both 'scan_error' (legacy) and 'scan_failed' (new backend)
        const handleScanError = (data) => {
            this.hideStatus();
            this.showToast(`Scan error: ${data.message || data.error}`, 'error');
            this.updateProcessStatus('rescan', false, true);
        };
        this.socket.on('scan_error', handleScanError);
        this.socket.on('scan_failed', handleScanError);

        // Scheduled scan events
        this.socket.on('scheduled_rescan_started', () => {
            this.showToast('Scheduled rescan started', 'info');
            this.updateProcessStatus('rescan', true);
        });

        this.socket.on('scheduled_rescan_completed', (data) => {
            this.showToast('Scheduled rescan completed successfully', 'success');
            this.updateProcessStatus('rescan', false);
            this.loadSeries();
        });

        this.socket.on('scheduled_rescan_error', (data) => {
            this.showToast(`Scheduled rescan error: ${data.error}`, 'error');
            this.updateProcessStatus('rescan', false, true);
        });

        this.socket.on('scheduled_rescan_skipped', (data) => {
            this.showToast(`Scheduled rescan skipped: ${data.reason}`, 'warning');
        });

        this.socket.on('auto_download_started', (data) => {
            this.showToast('Auto-download started after scheduled rescan', 'info');
            this.updateProcessStatus('download', true);
        });

        this.socket.on('auto_download_error', (data) => {
            this.showToast(`Auto-download error: ${data.error}`, 'error');
            this.updateProcessStatus('download', false, true);
        });

        // Download events
        this.socket.on('download_started', (data) => {
            this.isDownloading = true;
            this.isPaused = false;
            this.updateProcessStatus('download', true);
            this.showDownloadQueue(data);
            this.showStatus(`Starting download of ${data.total_series} series...`, true, true);
        });

        this.socket.on('download_progress', (data) => {
            let status = '';
            let percent = 0;

            if (data.progress !== undefined) {
                percent = data.progress;
                status = `Downloading: ${percent.toFixed(1)}%`;

                // Add speed information if available
                if (data.speed_mbps && data.speed_mbps > 0) {
                    status += ` (${data.speed_mbps.toFixed(1)} Mbps)`;
                }

                // Add ETA information if available
                if (data.eta_seconds && data.eta_seconds > 0) {
                    const eta = this.formatETA(data.eta_seconds);
                    status += ` - ETA: ${eta}`;
                }
            } else if (data.total_bytes) {
                percent = ((data.downloaded_bytes || 0) / data.total_bytes * 100);
                status = `Downloading: ${percent.toFixed(1)}%`;
            } else if (data.downloaded_mb !== undefined) {
                status = `Downloaded: ${data.downloaded_mb.toFixed(1)} MB`;
            } else {
                status = `Downloading: ${data.percent || '0%'}`;
            }

            if (percent > 0) {
                this.updateProgress(percent, status);
            } else {
                this.updateStatus(status);
            }
        });

        this.socket.on('download_completed', (data) => {
            this.isDownloading = false;
            this.isPaused = false;
            this.hideDownloadQueue();
            this.hideStatus();
            this.showToast(this.localization.getText('download-completed'), 'success');
            this.loadSeries();
            this.clearSelection();
        });

        this.socket.on('download_error', (data) => {
            this.isDownloading = false;
            this.isPaused = false;
            this.hideDownloadQueue();
            this.hideStatus();
            this.showToast(`${this.localization.getText('download-failed')}: ${data.message}`, 'error');
        });

        // Download queue status events
        this.socket.on('download_queue_completed', () => {
            this.updateProcessStatus('download', false);
            this.showToast('All downloads completed!', 'success');
        });

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

        this.socket.on('download_stopped', () => {
            this.updateProcessStatus('download', false);
            this.showToast('Downloads stopped', 'success');
        });

        // Download queue events
        this.socket.on('download_queue_update', (data) => {
            this.updateDownloadQueue(data);
        });

        this.socket.on('download_episode_update', (data) => {
            this.updateCurrentEpisode(data);
        });

        this.socket.on('download_series_completed', (data) => {
            this.updateDownloadProgress(data);
        });

        // Download control events
        this.socket.on('download_paused', () => {
            this.isPaused = true;
            this.updateStatus(this.localization.getText('paused'));
        });

        this.socket.on('download_resumed', () => {
            this.isPaused = false;
            this.updateStatus(this.localization.getText('downloading'));
        });

        this.socket.on('download_cancelled', () => {
            this.isDownloading = false;
            this.isPaused = false;
            this.hideDownloadQueue();
            this.hideStatus();
            this.showToast('Download cancelled', 'warning');
        });
    }

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

        // Search functionality
        const searchInput = document.getElementById('search-input');
        const searchBtn = document.getElementById('search-btn');
        const clearSearch = document.getElementById('clear-search');

        searchBtn.addEventListener('click', () => {
            this.performSearch();
        });

        searchInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                this.performSearch();
            }
        });

        clearSearch.addEventListener('click', () => {
            searchInput.value = '';
            this.hideSearchResults();
        });

        // Series management
        document.getElementById('select-all').addEventListener('click', () => {
            this.toggleSelectAll();
        });

        document.getElementById('download-selected').addEventListener('click', () => {
            this.downloadSelected();
        });

        // Rescan
        document.getElementById('rescan-btn').addEventListener('click', () => {
            this.rescanSeries();
        });

        // Click on rescan status indicator to reopen scan overlay
        const rescanStatus = document.getElementById('rescan-status');
        if (rescanStatus) {
            rescanStatus.addEventListener('click', (e) => {
                e.stopPropagation();
                console.log('Rescan status clicked');
                this.reopenScanOverlay();
            });
        }

        // Configuration modal
        document.getElementById('config-btn').addEventListener('click', () => {
            this.showConfigModal();
        });

        document.getElementById('close-config').addEventListener('click', () => {
            this.hideConfigModal();
        });

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

        // Scheduler configuration
        document.getElementById('scheduled-rescan-enabled').addEventListener('change', () => {
            this.toggleSchedulerTimeInput();
        });

        document.getElementById('save-scheduler-config').addEventListener('click', () => {
            this.saveSchedulerConfig();
        });

        document.getElementById('test-scheduled-rescan').addEventListener('click', () => {
            this.testScheduledRescan();
        });

        // Logging configuration
        document.getElementById('save-logging-config').addEventListener('click', () => {
            this.saveLoggingConfig();
        });

        document.getElementById('test-logging').addEventListener('click', () => {
            this.testLogging();
        });

        document.getElementById('refresh-log-files').addEventListener('click', () => {
            this.loadLogFiles();
        });

        document.getElementById('cleanup-logs').addEventListener('click', () => {
            this.cleanupLogs();
        });

        // Configuration management
        document.getElementById('create-config-backup').addEventListener('click', () => {
            this.createConfigBackup();
        });

        document.getElementById('view-config-backups').addEventListener('click', () => {
            this.viewConfigBackups();
        });

        document.getElementById('export-config').addEventListener('click', () => {
            this.exportConfig();
        });

        document.getElementById('validate-config').addEventListener('click', () => {
            this.validateConfig();
        });

        document.getElementById('reset-config').addEventListener('click', () => {
            this.resetConfig();
        });

        document.getElementById('save-advanced-config').addEventListener('click', () => {
            this.saveAdvancedConfig();
        });

        // Main configuration
        document.getElementById('save-main-config').addEventListener('click', () => {
            this.saveMainConfig();
        });

        document.getElementById('reset-main-config').addEventListener('click', () => {
            this.resetMainConfig();
        });

        document.getElementById('test-connection').addEventListener('click', () => {
            this.testConnection();
        });

        document.getElementById('browse-directory').addEventListener('click', () => {
            this.browseDirectory();
        });

        // Status panel
        document.getElementById('close-status').addEventListener('click', () => {
            this.hideStatus();
        });

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

        // Series filtering and sorting
        document.getElementById('show-missing-only').addEventListener('click', () => {
            this.toggleMissingOnlyFilter();
        });

        document.getElementById('sort-alphabetical').addEventListener('click', () => {
            this.toggleAlphabeticalSort();
        });
    }

    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);
    }

    async loadSeries() {
        try {
            this.showLoading();

            const response = await this.makeAuthenticatedRequest('/api/anime');

            if (!response) {
                // makeAuthenticatedRequest returns null and handles redirect on auth failure
                return;
            }

            const data = await response.json();

            // Check if response has the expected format
            if (Array.isArray(data)) {
                // API returns array of AnimeSummary objects with full serie data
                this.seriesData = data.map(anime => {
                    // Count total missing episodes from the episode dictionary
                    const episodeDict = anime.missing_episodes || {};
                    const totalMissing = Object.values(episodeDict).reduce(
                        (sum, episodes) => sum + (Array.isArray(episodes) ? episodes.length : 0),
                        0
                    );
                    
                    return {
                        key: anime.key,
                        name: anime.name,
                        site: anime.site,
                        folder: anime.folder,
                        episodeDict: episodeDict,
                        missing_episodes: totalMissing,
                        has_missing: anime.has_missing || totalMissing > 0
                    };
                });
            } else if (data.status === 'success') {
                // Legacy format support
                this.seriesData = data.series;
            } else {
                this.showToast(`Error loading series: ${data.message || 'Unknown error'}`, 'error');
                return;
            }

            this.applyFiltersAndSort();
            this.renderSeries();
        } catch (error) {
            console.error('Error loading series:', error);
            this.showToast('Failed to load series', 'error');
        } finally {
            this.hideLoading();
        }
    }

    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;
    }

    applyFiltersAndSort() {
        let filtered = [...this.seriesData];

        // Sort based on the current sorting mode
        filtered.sort((a, b) => {
            if (this.sortAlphabetical) {
                // Pure alphabetical sorting when A-Z is enabled
                return this.getDisplayName(a).localeCompare(this.getDisplayName(b));
            } else {
                // Default sorting: missing episodes first (descending), then by name
                // Always show series with missing episodes first
                if (a.missing_episodes > 0 && b.missing_episodes === 0) return -1;
                if (a.missing_episodes === 0 && b.missing_episodes > 0) return 1;

                // If both have missing episodes, sort by count (descending)
                if (a.missing_episodes > 0 && b.missing_episodes > 0) {
                    if (a.missing_episodes !== b.missing_episodes) {
                        return b.missing_episodes - a.missing_episodes;
                    }
                }

                // For series with same missing episode status, maintain stable order
                return 0;
            }
        });

        // Apply missing episodes filter
        if (this.showMissingOnly) {
            filtered = filtered.filter(serie => serie.missing_episodes > 0);
        }

        this.filteredSeriesData = filtered;
        this.renderSeries();
    }

    renderSeries() {
        const grid = document.getElementById('series-grid');
        const dataToRender = this.filteredSeriesData.length > 0 ? this.filteredSeriesData :
            (this.seriesData.length > 0 ? this.seriesData : []);

        if (dataToRender.length === 0) {
            const message = this.showMissingOnly ?
                'No series with missing episodes found.' :
                'No series found. Try searching for anime or rescanning your directory.';

            grid.innerHTML = `
                <div class="text-center" style="grid-column: 1 / -1; padding: 2rem;">
                    <i class="fas fa-tv" style="font-size: 48px; color: var(--color-text-tertiary); margin-bottom: 1rem;"></i>
                    <p style="color: var(--color-text-secondary);">${message}</p>
                </div>
            `;
            return;
        }

        grid.innerHTML = dataToRender.map(serie => this.createSerieCard(serie)).join('');

        // Bind checkbox events - uses 'key' as identifier
        grid.querySelectorAll('.series-checkbox').forEach(checkbox => {
            checkbox.addEventListener('change', (e) => {
                this.toggleSerieSelection(e.target.dataset.key, e.target.checked);
            });
        });
    }

    createSerieCard(serie) {
        // Use 'key' as the primary identifier for selection and data operations
        const isSelected = this.selectedSeries.has(serie.key);
        const hasMissingEpisodes = serie.missing_episodes > 0;
        const canBeSelected = hasMissingEpisodes; // Only allow selection if has missing episodes

        return `
            <div class="series-card ${isSelected ? 'selected' : ''} ${hasMissingEpisodes ? 'has-missing' : 'complete'}" 
                 data-key="${serie.key}" data-folder="${serie.folder}">
                <div class="series-card-header">
                    <input type="checkbox" 
                           class="series-checkbox" 
                           data-key="${serie.key}"
                           ${isSelected ? 'checked' : ''}
                           ${!canBeSelected ? 'disabled' : ''}>
                    <div class="series-info">
                        <h3>${this.escapeHtml(this.getDisplayName(serie))}</h3>
                        <div class="series-folder">${this.escapeHtml(serie.folder)}</div>
                    </div>
                    <div class="series-status">
                        ${hasMissingEpisodes ?
                '' :
                '<i class="fas fa-check-circle status-complete" title="Complete"></i>'
            }
                    </div>
                </div>
                <div class="series-stats">
                    <div class="missing-episodes ${hasMissingEpisodes ? 'has-missing' : 'complete'}">
                        <i class="fas ${hasMissingEpisodes ? 'fa-exclamation-triangle' : 'fa-check'}"></i>
                        <span>${hasMissingEpisodes ? `${serie.missing_episodes} missing episodes` : 'Complete'}</span>
                    </div>
                    <span class="series-site">${serie.site}</span>
                </div>
            </div>
        `;
    }

    toggleSerieSelection(key, selected) {
        // Only allow selection of series with missing episodes
        // Use 'key' as the primary identifier for lookup and selection
        const serie = this.seriesData.find(s => s.key === key);
        if (!serie || serie.missing_episodes === 0) {
            // Uncheck the checkbox if it was checked for a complete series
            const checkbox = document.querySelector(`input[data-key="${key}"]`);
            if (checkbox) checkbox.checked = false;
            return;
        }

        if (selected) {
            this.selectedSeries.add(key);
        } else {
            this.selectedSeries.delete(key);
        }

        this.updateSelectionUI();
    }

    updateSelectionUI() {
        const downloadBtn = document.getElementById('download-selected');
        const selectAllBtn = document.getElementById('select-all');

        // Get series that can be selected (have missing episodes)
        // Use 'key' as the primary identifier for selection tracking
        const selectableSeriesData = this.filteredSeriesData.length > 0 ? this.filteredSeriesData : this.seriesData;
        const selectableSeries = selectableSeriesData.filter(serie => serie.missing_episodes > 0);
        const selectableKeys = selectableSeries.map(serie => serie.key);

        downloadBtn.disabled = this.selectedSeries.size === 0;

        const allSelectableSelected = selectableKeys.every(key => this.selectedSeries.has(key));

        if (this.selectedSeries.size === 0) {
            selectAllBtn.innerHTML = '<i class="fas fa-check-double"></i><span>Select All</span>';
        } else if (allSelectableSelected && selectableKeys.length > 0) {
            selectAllBtn.innerHTML = '<i class="fas fa-times"></i><span>Deselect All</span>';
        } else {
            selectAllBtn.innerHTML = '<i class="fas fa-check-double"></i><span>Select All</span>';
        }

        // Update card appearances using 'key' as identifier
        document.querySelectorAll('.series-card').forEach(card => {
            const key = card.dataset.key;
            const isSelected = this.selectedSeries.has(key);
            card.classList.toggle('selected', isSelected);
        });
    }

    toggleSelectAll() {
        // Get series that can be selected (have missing episodes)
        // Use 'key' as the primary identifier for selection
        const selectableSeriesData = this.filteredSeriesData.length > 0 ? this.filteredSeriesData : this.seriesData;
        const selectableSeries = selectableSeriesData.filter(serie => serie.missing_episodes > 0);
        const selectableKeys = selectableSeries.map(serie => serie.key);

        const allSelectableSelected = selectableKeys.every(key => this.selectedSeries.has(key));

        if (allSelectableSelected && this.selectedSeries.size > 0) {
            // Deselect all selectable series
            selectableKeys.forEach(key => this.selectedSeries.delete(key));
            document.querySelectorAll('.series-checkbox:not([disabled])').forEach(cb => cb.checked = false);
        } else {
            // Select all selectable series
            selectableKeys.forEach(key => this.selectedSeries.add(key));
            document.querySelectorAll('.series-checkbox:not([disabled])').forEach(cb => cb.checked = true);
        }

        this.updateSelectionUI();
    }

    clearSelection() {
        this.selectedSeries.clear();
        document.querySelectorAll('.series-checkbox').forEach(cb => cb.checked = false);
        this.updateSelectionUI();
    }

    async performSearch() {
        const searchInput = document.getElementById('search-input');
        const query = searchInput.value.trim();

        if (!query) {
            this.showToast('Please enter a search term', 'warning');
            return;
        }

        try {
            this.showLoading();

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

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

            // Check if response is a direct array (new format) or wrapped object (legacy)
            if (Array.isArray(data)) {
                this.displaySearchResults(data);
            } else if (data.status === 'success') {
                this.displaySearchResults(data.results);
            } else {
                this.showToast(`Search error: ${data.message || 'Unknown error'}`, 'error');
            }
        } catch (error) {
            console.error('Search error:', error);
            this.showToast('Search failed', 'error');
        } finally {
            this.hideLoading();
        }
    }

    displaySearchResults(results) {
        const resultsContainer = document.getElementById('search-results');
        const resultsList = document.getElementById('search-results-list');

        if (results.length === 0) {
            resultsContainer.classList.add('hidden');
            this.showToast('No search results found', 'warning');
            return;
        }

        resultsList.innerHTML = results.map(result => `
            <div class="search-result-item">
                <span class="search-result-name">${this.escapeHtml(this.getDisplayName(result))}</span>
                <button class="btn btn-small btn-primary" onclick="app.addSeries('${this.escapeHtml(result.link)}', '${this.escapeHtml(this.getDisplayName(result))}')">
                    <i class="fas fa-plus"></i>
                    Add
                </button>
            </div>
        `).join('');

        resultsContainer.classList.remove('hidden');
    }

    hideSearchResults() {
        document.getElementById('search-results').classList.add('hidden');
    }

    async addSeries(link, name) {
        try {
            const response = await this.makeAuthenticatedRequest('/api/anime/add', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ link, name })
            });

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

            if (data.status === 'success') {
                this.showToast(data.message, 'success');
                this.loadSeries();
                this.hideSearchResults();
                document.getElementById('search-input').value = '';
            } else {
                this.showToast(`Error adding series: ${data.message}`, 'error');
            }
        } catch (error) {
            console.error('Error adding series:', error);
            this.showToast('Failed to add series', 'error');
        }
    }

    async downloadSelected() {
        console.log('=== downloadSelected v1.2 - Using key as primary identifier ===');
        if (this.selectedSeries.size === 0) {
            this.showToast('No series selected', 'warning');
            return;
        }

        try {
            // selectedSeries now contains 'key' values (not folder)
            const selectedKeys = Array.from(this.selectedSeries);
            console.log('=== Starting download for selected series ===');
            console.log('Selected keys:', selectedKeys);
            console.log('seriesData:', this.seriesData);
            let totalEpisodesAdded = 0;
            let failedSeries = [];

            // For each selected series, get its missing episodes and add to queue
            // Use 'key' to find the series in seriesData
            for (const key of selectedKeys) {
                const serie = this.seriesData.find(s => s.key === key);
                if (!serie || !serie.episodeDict) {
                    console.error('Serie not found or has no episodeDict for key:', key, serie);
                    failedSeries.push(key);
                    continue;
                }

                // Validate required fields
                if (!serie.key) {
                    console.error('Serie missing key:', serie);
                    failedSeries.push(key);
                    continue;
                }

                // Convert episodeDict format {season: [episodes]} to episode identifiers
                const episodes = [];
                for (const [season, episodeNumbers] of Object.entries(serie.episodeDict)) {
                    if (Array.isArray(episodeNumbers)) {
                        for (const episode of episodeNumbers) {
                            episodes.push({
                                season: parseInt(season),
                                episode: episode
                            });
                        }
                    }
                }

                if (episodes.length === 0) {
                    console.log('No episodes to add for serie:', serie.name);
                    continue;
                }

                // Use folder name as fallback if serie name is empty
                const serieName = serie.name && serie.name.trim() ? serie.name : serie.folder;

                // Add episodes to download queue
                const requestBody = {
                    serie_id: serie.key,
                    serie_folder: serie.folder,
                    serie_name: serieName,
                    episodes: episodes,
                    priority: 'NORMAL'
                };
                console.log('Sending queue add request:', requestBody);

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

                if (!response) {
                    failedSeries.push(key);
                    continue;
                }

                const data = await response.json();
                console.log('Queue add response:', response.status, data);
                
                // Log validation errors in detail
                if (data.detail && Array.isArray(data.detail)) {
                    console.error('Validation errors:', JSON.stringify(data.detail, null, 2));
                }
                
                if (response.ok && data.status === 'success') {
                    totalEpisodesAdded += episodes.length;
                } else {
                    console.error('Failed to add to queue:', data);
                    failedSeries.push(key);
                }
            }

            // Show result message
            console.log('=== Download request complete ===');
            console.log('Total episodes added:', totalEpisodesAdded);
            console.log('Failed series (keys):', failedSeries);
            
            if (totalEpisodesAdded > 0) {
                const message = failedSeries.length > 0
                    ? `Added ${totalEpisodesAdded} episode(s) to queue (${failedSeries.length} series failed)`
                    : `Added ${totalEpisodesAdded} episode(s) to download queue`;
                this.showToast(message, 'success');
            } else {
                const errorDetails = failedSeries.length > 0 
                    ? `Failed series (keys): ${failedSeries.join(', ')}`
                    : 'No episodes were added. Check browser console for details.';
                console.error('Failed to add episodes. Details:', errorDetails);
                this.showToast('Failed to add episodes to queue. Check console for details.', 'error');
            }
        } catch (error) {
            console.error('Download error:', error);
            this.showToast('Failed to start download', 'error');
        }
    }

    async rescanSeries() {
        try {
            // Show the overlay immediately before making the API call
            this.showScanProgressOverlay({
                directory: 'Starting scan...',
                total_items: 0
            });
            this.updateProcessStatus('rescan', true);
            
            const response = await this.makeAuthenticatedRequest('/api/anime/rescan', {
                method: 'POST'
            });

            if (!response) {
                this.removeScanProgressOverlay();
                this.updateProcessStatus('rescan', false);
                return;
            }
            const data = await response.json();
            
            // Debug logging
            console.log('Rescan response:', data);
            console.log('Success value:', data.success, 'Type:', typeof data.success);

            // Note: The scan progress will be updated via WebSocket events
            // The overlay will be closed when scan_completed is received
            if (data.success !== true) {
                this.removeScanProgressOverlay();
                this.updateProcessStatus('rescan', false);
                this.showToast(`Rescan error: ${data.message}`, 'error');
            }
        } catch (error) {
            console.error('Rescan error:', error);
            this.removeScanProgressOverlay();
            this.updateProcessStatus('rescan', false);
            this.showToast('Failed to start rescan', 'error');
        }
    }

    showStatus(message, showProgress = false, showControls = false) {
        const panel = document.getElementById('status-panel');
        const messageEl = document.getElementById('status-message');
        const progressContainer = document.getElementById('progress-container');
        const controlsContainer = document.getElementById('download-controls');

        messageEl.textContent = message;
        progressContainer.classList.toggle('hidden', !showProgress);
        controlsContainer.classList.toggle('hidden', !showControls);

        if (showProgress) {
            this.updateProgress(0);
        }

        panel.classList.remove('hidden');
    }

    updateStatus(message) {
        document.getElementById('status-message').textContent = message;
    }

    updateProgress(percent, message = null) {
        const fill = document.getElementById('progress-fill');
        const text = document.getElementById('progress-text');

        fill.style.width = `${percent}%`;
        text.textContent = message || `${percent}%`;
    }

    hideStatus() {
        document.getElementById('status-panel').classList.add('hidden');
    }

    /**
     * Show the scan progress overlay with spinner and initial state
     * @param {Object} data - Scan started event data
     */
    showScanProgressOverlay(data) {
        // Remove existing overlay if present
        this.removeScanProgressOverlay();

        // Store total items for progress calculation
        this.scanTotalItems = data?.total_items || 0;
        
        // Store last scan data for reopening
        this._lastScanData = data;

        // Create overlay element
        const overlay = document.createElement('div');
        overlay.id = 'scan-progress-overlay';
        overlay.className = 'scan-progress-overlay';
        
        const totalDisplay = this.scanTotalItems > 0 ? this.scanTotalItems : '...';
        
        overlay.innerHTML = `
            <div class="scan-progress-container">
                <div class="scan-progress-header">
                    <h3>
                        <span class="scan-progress-spinner"></span>
                        <i class="fas fa-check-circle scan-completed-icon"></i>
                        <span class="scan-title-text">Scanning Library</span>
                    </h3>
                </div>
                <div class="scan-progress-bar-container">
                    <div class="scan-progress-bar" id="scan-progress-bar" style="width: 0%"></div>
                </div>
                <div class="scan-progress-text" id="scan-progress-text">
                    <span id="scan-current-count">0</span> / <span id="scan-total-count">${totalDisplay}</span> directories
                </div>
                <div class="scan-progress-stats">
                    <div class="scan-stat">
                        <span class="scan-stat-value" id="scan-directories-count">0</span>
                        <span class="scan-stat-label">Scanned</span>
                    </div>
                    <div class="scan-stat">
                        <span class="scan-stat-value" id="scan-files-count">0</span>
                        <span class="scan-stat-label">Series Found</span>
                    </div>
                </div>
                <div class="scan-current-directory" id="scan-current-directory">
                    <span class="scan-current-directory-label">Current:</span>
                    <span id="scan-current-path">${this.escapeHtml(data?.directory || 'Initializing...')}</span>
                </div>
                <div class="scan-elapsed-time hidden" id="scan-elapsed-time">
                    <i class="fas fa-clock"></i>
                    <span id="scan-elapsed-value">0.0s</span>
                </div>
            </div>
        `;

        document.body.appendChild(overlay);

        // Add click-outside-to-close handler
        overlay.addEventListener('click', (e) => {
            // Only close if clicking the overlay background, not the container
            if (e.target === overlay) {
                this.removeScanProgressOverlay();
            }
        });

        // Trigger animation by adding visible class after a brief delay
        requestAnimationFrame(() => {
            overlay.classList.add('visible');
        });
    }

    /**
     * Update the scan progress overlay with current progress
     * @param {Object} data - Scan progress event data
     */
    updateScanProgressOverlay(data) {
        const overlay = document.getElementById('scan-progress-overlay');
        if (!overlay) return;

        // Update total items if provided (in case it wasn't available at start)
        if (data.total_items && data.total_items > 0) {
            this.scanTotalItems = data.total_items;
            const totalCount = document.getElementById('scan-total-count');
            if (totalCount) {
                totalCount.textContent = this.scanTotalItems;
            }
        }

        // Update progress bar
        const progressBar = document.getElementById('scan-progress-bar');
        if (progressBar && this.scanTotalItems > 0 && data.directories_scanned !== undefined) {
            const percentage = Math.min(100, (data.directories_scanned / this.scanTotalItems) * 100);
            progressBar.style.width = `${percentage}%`;
        }

        // Update current/total count display
        const currentCount = document.getElementById('scan-current-count');
        if (currentCount && data.directories_scanned !== undefined) {
            currentCount.textContent = data.directories_scanned;
        }

        // Update directories count
        const dirCount = document.getElementById('scan-directories-count');
        if (dirCount && data.directories_scanned !== undefined) {
            dirCount.textContent = data.directories_scanned;
        }

        // Update files/series count
        const filesCount = document.getElementById('scan-files-count');
        if (filesCount && data.files_found !== undefined) {
            filesCount.textContent = data.files_found;
        }

        // Update current directory (truncate if too long)
        const currentPath = document.getElementById('scan-current-path');
        if (currentPath && data.current_directory) {
            const maxLength = 50;
            let displayPath = data.current_directory;
            if (displayPath.length > maxLength) {
                displayPath = '...' + displayPath.slice(-maxLength + 3);
            }
            currentPath.textContent = displayPath;
            currentPath.title = data.current_directory; // Full path on hover
        }
    }

    /**
     * Hide the scan progress overlay with completion summary
     * @param {Object} data - Scan completed event data
     */
    hideScanProgressOverlay(data) {
        const overlay = document.getElementById('scan-progress-overlay');
        if (!overlay) return;

        const container = overlay.querySelector('.scan-progress-container');
        if (container) {
            container.classList.add('completed');
        }

        // Update title
        const titleText = overlay.querySelector('.scan-title-text');
        if (titleText) {
            titleText.textContent = 'Scan Complete';
        }

        // Complete the progress bar
        const progressBar = document.getElementById('scan-progress-bar');
        if (progressBar) {
            progressBar.style.width = '100%';
        }

        // Update final stats
        if (data) {
            const dirCount = document.getElementById('scan-directories-count');
            if (dirCount && data.total_directories !== undefined) {
                dirCount.textContent = data.total_directories;
            }

            const filesCount = document.getElementById('scan-files-count');
            if (filesCount && data.total_files !== undefined) {
                filesCount.textContent = data.total_files;
            }

            // Update progress text to show final count
            const currentCount = document.getElementById('scan-current-count');
            const totalCount = document.getElementById('scan-total-count');
            if (currentCount && data.total_directories !== undefined) {
                currentCount.textContent = data.total_directories;
            }
            if (totalCount && data.total_directories !== undefined) {
                totalCount.textContent = data.total_directories;
            }

            // Show elapsed time
            const elapsedTimeEl = document.getElementById('scan-elapsed-time');
            const elapsedValueEl = document.getElementById('scan-elapsed-value');
            if (elapsedTimeEl && elapsedValueEl && data.elapsed_seconds !== undefined) {
                elapsedValueEl.textContent = `${data.elapsed_seconds.toFixed(1)}s`;
                elapsedTimeEl.classList.remove('hidden');
            }

            // Update current directory to show completion message
            const currentPath = document.getElementById('scan-current-path');
            if (currentPath) {
                currentPath.textContent = 'Scan finished successfully';
            }
        }

        // Auto-dismiss after 3 seconds
        setTimeout(() => {
            this.removeScanProgressOverlay();
        }, 3000);
    }

    /**
     * Remove the scan progress overlay from the DOM
     */
    removeScanProgressOverlay() {
        const overlay = document.getElementById('scan-progress-overlay');
        if (overlay) {
            overlay.classList.remove('visible');
            // Wait for fade out animation before removing
            setTimeout(() => {
                if (overlay.parentElement) {
                    overlay.remove();
                }
            }, 300);
        }
    }

    /**
     * Reopen the scan progress overlay if a scan is in progress
     * Called when user clicks on the rescan status indicator
     */
    async reopenScanOverlay() {
        // Check if overlay already exists
        const existingOverlay = document.getElementById('scan-progress-overlay');
        if (existingOverlay) {
            // Overlay is already open, do nothing
            return;
        }
        
        // Check if scan is running via API
        try {
            const response = await this.makeAuthenticatedRequest('/api/anime/scan/status');
            if (!response || !response.ok) {
                console.log('Could not fetch scan status');
                return;
            }
            
            const data = await response.json();
            console.log('Scan status for reopen:', data);
            
            if (data.is_scanning) {
                // A scan is in progress, show the overlay
                this.showScanProgressOverlay({
                    directory: data.directory,
                    total_items: data.total_items
                });
                
                // Update with current progress
                this.updateScanProgressOverlay({
                    directories_scanned: data.directories_scanned,
                    files_found: data.directories_scanned,
                    current_directory: data.current_directory,
                    total_items: data.total_items
                });
            }
        } catch (error) {
            console.error('Error checking scan status for reopen:', error);
        }
    }

    /**
     * Check if a scan is currently in progress (useful after page reload)
     * and show the progress overlay if so
     */
    async checkActiveScanStatus() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/anime/scan/status');
            if (!response || !response.ok) {
                console.log('Could not fetch scan status, response:', response?.status);
                return;
            }
            
            const data = await response.json();
            console.log('Scan status check result:', data);
            
            if (data.is_scanning) {
                console.log('Scan is active, updating UI indicators');
                
                // Update the process status indicator FIRST before showing overlay
                // This ensures the header icon shows the running state immediately
                this.updateProcessStatus('rescan', true);
                
                // A scan is in progress, show the overlay
                this.showScanProgressOverlay({
                    directory: data.directory,
                    total_items: data.total_items
                });
                
                // Update with current progress
                this.updateScanProgressOverlay({
                    directories_scanned: data.directories_scanned,
                    files_found: data.directories_scanned,
                    current_directory: data.current_directory,
                    total_items: data.total_items
                });
                
                // Double-check the status indicator was updated
                const statusElement = document.getElementById('rescan-status');
                if (statusElement) {
                    console.log('Rescan status element classes:', statusElement.className);
                } else {
                    console.warn('Rescan status element not found in DOM');
                }
            } else {
                console.log('No active scan detected');
                // Ensure indicator shows idle state
                this.updateProcessStatus('rescan', false);
            }
        } catch (error) {
            console.error('Error checking scan status:', error);
        }
    }

    showLoading() {
        document.getElementById('loading-overlay').classList.remove('hidden');
    }

    hideLoading() {
        document.getElementById('loading-overlay').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);

        // Auto-remove after 5 seconds
        setTimeout(() => {
            if (toast.parentElement) {
                toast.remove();
            }
        }, 5000);
    }

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

    /**
     * Get display name for anime/series object.
     * Returns name if available and not empty, otherwise returns key.
     * @param {Object} anime - Anime/series object with name and key properties
     * @returns {string} Display name
     */
    getDisplayName(anime) {
        if (!anime) return '';
        // Use name if it exists and is not empty (after trimming whitespace)
        const name = anime.name || '';
        const trimmedName = name.trim();
        if (trimmedName) {
            return trimmedName;
        }
        // Fallback to key
        return anime.key || anime.folder || '';
    }

    updateConnectionStatus() {
        const indicator = document.getElementById('connection-status-display');
        if (indicator) {
            const statusIndicator = indicator.querySelector('.status-indicator');
            const statusText = indicator.querySelector('.status-text');

            if (this.isConnected) {
                statusIndicator.classList.add('connected');
                statusText.textContent = this.localization.getText('connected');
            } else {
                statusIndicator.classList.remove('connected');
                statusText.textContent = this.localization.getText('disconnected');
            }
        }
    }

    updateProcessStatus(processName, isRunning, hasError = false) {
        const statusElement = document.getElementById(`${processName}-status`);
        if (!statusElement) {
            console.warn(`Process status element not found: ${processName}-status`);
            return;
        }

        const statusDot = statusElement.querySelector('.status-dot');
        if (!statusDot) {
            console.warn(`Status dot not found in ${processName}-status element`);
            return;
        }

        // Remove all status classes from both dot and element
        statusDot.classList.remove('idle', 'running', 'error');
        statusElement.classList.remove('running', 'error', 'idle');

        // Capitalize process name for display
        const displayName = processName.charAt(0).toUpperCase() + processName.slice(1);

        if (hasError) {
            statusDot.classList.add('error');
            statusElement.classList.add('error');
            statusElement.title = `${displayName} error - click for details`;
        } else if (isRunning) {
            statusDot.classList.add('running');
            statusElement.classList.add('running');
            statusElement.title = `${displayName} is running...`;
        } else {
            statusDot.classList.add('idle');
            statusElement.classList.add('idle');
            statusElement.title = `${displayName} is idle`;
        }
        
        console.log(`Process status updated: ${processName} = ${isRunning ? 'running' : (hasError ? 'error' : 'idle')}`);
    }

    async showConfigModal() {
        const modal = document.getElementById('config-modal');

        try {
            // Load current status
            const response = await this.makeAuthenticatedRequest('/api/anime/status');
            if (!response) return;
            const data = await response.json();

            document.getElementById('anime-directory-input').value = data.directory || '';
            document.getElementById('series-count-input').value = data.series_count || '0';

            // Load scheduler configuration
            await this.loadSchedulerConfig();

            // Load logging configuration
            await this.loadLoggingConfig();

            // Load advanced configuration
            await this.loadAdvancedConfig();

            modal.classList.remove('hidden');
        } catch (error) {
            console.error('Error loading configuration:', error);
            this.showToast('Failed to load configuration', 'error');
        }
    }

    hideConfigModal() {
        document.getElementById('config-modal').classList.add('hidden');
    }

    async loadSchedulerConfig() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/scheduler/config');
            if (!response) return;
            const data = await response.json();

            if (data.success) {
                const config = data.config || {};
                const schedulerStatus = data.status || {};

                // Update UI elements
                document.getElementById('scheduled-rescan-enabled').checked = !!config.enabled;
                document.getElementById('scheduled-rescan-time').value = config.schedule_time || '03:00';
                document.getElementById('auto-download-after-rescan').checked = !!config.auto_download_after_rescan;
                const folderScanEl = document.getElementById('folder-scan-enabled');
                if (folderScanEl) folderScanEl.checked = !!config.folder_scan_enabled;

                // Update day-of-week checkboxes
                const days = Array.isArray(config.schedule_days) ? config.schedule_days : ['mon','tue','wed','thu','fri','sat','sun'];
                ['mon','tue','wed','thu','fri','sat','sun'].forEach(day => {
                    const cb = document.getElementById(`scheduler-day-${day}`);
                    if (cb) cb.checked = days.includes(day);
                });

                // Update status display
                const nextRunEl = document.getElementById('scheduler-next-run');
                if (nextRunEl) {
                    nextRunEl.textContent = schedulerStatus.next_run
                        ? new Date(schedulerStatus.next_run).toLocaleString()
                        : 'Not scheduled';
                }
                const lastRunEl = document.getElementById('last-rescan-time');
                if (lastRunEl) {
                    lastRunEl.textContent = schedulerStatus.last_run
                        ? new Date(schedulerStatus.last_run).toLocaleString()
                        : 'Never';
                }

                const statusBadge = document.getElementById('scheduler-running-status');
                if (statusBadge) {
                    statusBadge.textContent = schedulerStatus.is_running ? 'Running' : 'Stopped';
                    statusBadge.className = `info-value status-badge ${schedulerStatus.is_running ? 'running' : 'stopped'}`;
                }

                // Enable/disable time/day inputs based on checkbox
                this.toggleSchedulerTimeInput();
            }
        } catch (error) {
            console.error('Error loading scheduler config:', error);
            this.showToast('Failed to load scheduler configuration', 'error');
        }
    }

    async saveSchedulerConfig() {
        try {
            const enabled = document.getElementById('scheduled-rescan-enabled').checked;
            const scheduleTime = document.getElementById('scheduled-rescan-time').value || '03:00';
            const autoDownload = document.getElementById('auto-download-after-rescan').checked;
            const folderScanEl = document.getElementById('folder-scan-enabled');
            const folderScan = folderScanEl ? folderScanEl.checked : false;

            // Collect checked day-of-week values
            const scheduleDays = ['mon','tue','wed','thu','fri','sat','sun']
                .filter(day => {
                    const cb = document.getElementById(`scheduler-day-${day}`);
                    return cb ? cb.checked : true;
                });

            const response = await this.makeAuthenticatedRequest('/api/scheduler/config', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    enabled: enabled,
                    schedule_time: scheduleTime,
                    schedule_days: scheduleDays,
                    auto_download_after_rescan: autoDownload,
                    folder_scan_enabled: folderScan
                })
            });

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

            if (data.success) {
                this.showToast('Scheduler configuration saved successfully', 'success');
                // Update next-run display from response
                const nextRunEl = document.getElementById('scheduler-next-run');
                if (nextRunEl && data.status && data.status.next_run) {
                    nextRunEl.textContent = new Date(data.status.next_run).toLocaleString();
                }
                // Reload config to sync the full UI
                await this.loadSchedulerConfig();
            } else {
                this.showToast(`Failed to save config: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error saving scheduler config:', error);
            this.showToast('Failed to save scheduler configuration', 'error');
        }
    }

    async testScheduledRescan() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/scheduler/trigger-rescan', {
                method: 'POST'
            });

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

            if (data.success) {
                this.showToast('Test rescan triggered successfully', 'success');
            } else {
                this.showToast(`Failed to trigger test rescan: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error triggering test rescan:', error);
            this.showToast('Failed to trigger test rescan', 'error');
        }
    }

    toggleSchedulerTimeInput() {
        const enabled = document.getElementById('scheduled-rescan-enabled').checked;
        const timeConfig = document.getElementById('rescan-time-config');
        const daysConfig = document.getElementById('rescan-days-config');
        const nextRunEl = document.getElementById('scheduler-next-run');

        if (timeConfig) {
            timeConfig.classList.toggle('enabled', enabled);
        }
        if (daysConfig) {
            daysConfig.classList.toggle('enabled', enabled);
        }
        if (nextRunEl) {
            nextRunEl.parentElement && nextRunEl.parentElement.parentElement
                ? nextRunEl.parentElement.parentElement.classList.toggle('hidden', !enabled)
                : null;
        }
    }

    async loadLoggingConfig() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/logging/config');
            if (!response) return;

            const data = await response.json();

            if (data.success) {
                const config = data.config;

                // Set form values
                document.getElementById('log-level').value = config.log_level || 'INFO';
                document.getElementById('enable-console-logging').checked = config.enable_console_logging !== false;
                document.getElementById('enable-console-progress').checked = config.enable_console_progress === true;
                document.getElementById('enable-fail2ban-logging').checked = config.enable_fail2ban_logging !== false;

                // Load log files
                await this.loadLogFiles();
            }
        } catch (error) {
            console.error('Error loading logging config:', error);
            this.showToast('Failed to load logging configuration', 'error');
        }
    }

    async loadLogFiles() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/logging/files');
            if (!response) return;

            const data = await response.json();

            if (data.success) {
                const container = document.getElementById('log-files-list');
                container.innerHTML = '';

                if (data.files.length === 0) {
                    container.innerHTML = '<div class="log-file-item"><span>No log files found</span></div>';
                    return;
                }

                data.files.forEach(file => {
                    const item = document.createElement('div');
                    item.className = 'log-file-item';

                    const info = document.createElement('div');
                    info.className = 'log-file-info';

                    const name = document.createElement('div');
                    name.className = 'log-file-name';
                    name.textContent = file.name;

                    const details = document.createElement('div');
                    details.className = 'log-file-details';
                    details.textContent = `Size: ${file.size_mb} MB • Modified: ${new Date(file.modified).toLocaleDateString()}`;

                    info.appendChild(name);
                    info.appendChild(details);

                    const actions = document.createElement('div');
                    actions.className = 'log-file-actions';

                    const downloadBtn = document.createElement('button');
                    downloadBtn.className = 'btn btn-xs btn-secondary';
                    downloadBtn.innerHTML = '<i class="fas fa-download"></i>';
                    downloadBtn.title = 'Download';
                    downloadBtn.onclick = () => this.downloadLogFile(file.name);

                    const viewBtn = document.createElement('button');
                    viewBtn.className = 'btn btn-xs btn-secondary';
                    viewBtn.innerHTML = '<i class="fas fa-eye"></i>';
                    viewBtn.title = 'View Last 100 Lines';
                    viewBtn.onclick = () => this.viewLogFile(file.name);

                    actions.appendChild(downloadBtn);
                    actions.appendChild(viewBtn);

                    item.appendChild(info);
                    item.appendChild(actions);

                    container.appendChild(item);
                });
            }
        } catch (error) {
            console.error('Error loading log files:', error);
            this.showToast('Failed to load log files', 'error');
        }
    }

    async saveLoggingConfig() {
        try {
            const config = {
                log_level: document.getElementById('log-level').value,
                enable_console_logging: document.getElementById('enable-console-logging').checked,
                enable_console_progress: document.getElementById('enable-console-progress').checked,
                enable_fail2ban_logging: document.getElementById('enable-fail2ban-logging').checked
            };

            const response = await this.makeAuthenticatedRequest('/api/logging/config', {
                method: 'POST',
                body: JSON.stringify(config)
            });

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

            if (data.success) {
                this.showToast('Logging configuration saved successfully', 'success');
                await this.loadLoggingConfig();
            } else {
                this.showToast(`Failed to save logging config: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error saving logging config:', error);
            this.showToast('Failed to save logging configuration', 'error');
        }
    }

    async testLogging() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/logging/test', {
                method: 'POST'
            });

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

            if (data.success) {
                this.showToast('Test messages logged successfully', 'success');
                setTimeout(() => this.loadLogFiles(), 1000); // Refresh log files after a second
            } else {
                this.showToast(`Failed to test logging: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error testing logging:', error);
            this.showToast('Failed to test logging', 'error');
        }
    }

    async loadAdvancedConfig() {
        // Placeholder for advanced configuration loading
        // This method is called by showConfigModal but doesn't need to do anything special yet
        console.log('Advanced configuration loaded (placeholder)');
    }

    async cleanupLogs() {
        const days = prompt('Delete log files older than how many days?', '30');
        if (!days || isNaN(days) || days < 1) {
            this.showToast('Invalid number of days', 'error');
            return;
        }

        try {
            const response = await this.makeAuthenticatedRequest('/api/logging/cleanup', {
                method: 'POST',
                body: JSON.stringify({ days: parseInt(days) })
            });

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

            if (data.success) {
                this.showToast(data.message, 'success');
                await this.loadLogFiles();
            } else {
                this.showToast(`Failed to cleanup logs: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error cleaning up logs:', error);
            this.showToast('Failed to cleanup logs', 'error');
        }
    }

    downloadLogFile(filename) {
        // Create download link
        const link = document.createElement('a');
        link.href = `/api/logging/files/${encodeURIComponent(filename)}/download`;
        link.download = filename;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }

    async viewLogFile(filename) {
        try {
            const response = await this.makeAuthenticatedRequest(`/api/logging/files/${encodeURIComponent(filename)}/tail?lines=100`);
            if (!response) return;

            const data = await response.json();

            if (data.success) {
                // Create modal to show log content
                const modal = document.createElement('div');
                modal.className = 'modal';
                modal.style.display = 'block';

                const modalContent = document.createElement('div');
                modalContent.className = 'modal-content';
                modalContent.style.maxWidth = '80%';
                modalContent.style.maxHeight = '80%';

                const header = document.createElement('div');
                header.innerHTML = `<h3>Log File: ${filename}</h3><p>Showing last ${data.showing_lines} of ${data.total_lines} lines</p>`;

                const content = document.createElement('pre');
                content.style.maxHeight = '60vh';
                content.style.overflow = 'auto';
                content.style.backgroundColor = '#f5f5f5';
                content.style.padding = '10px';
                content.style.fontSize = '12px';
                content.textContent = data.lines.join('\n');

                const closeBtn = document.createElement('button');
                closeBtn.textContent = 'Close';
                closeBtn.className = 'btn btn-secondary';
                closeBtn.onclick = () => document.body.removeChild(modal);

                modalContent.appendChild(header);
                modalContent.appendChild(content);
                modalContent.appendChild(closeBtn);
                modal.appendChild(modalContent);
                document.body.appendChild(modal);

                // Close on background click
                modal.onclick = (e) => {
                    if (e.target === modal) {
                        document.body.removeChild(modal);
                    }
                };
            } else {
                this.showToast(`Failed to view log file: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error viewing log file:', error);
            this.showToast('Failed to view log file', 'error');
        }
    }

    // Configuration Management Methods
    async loadAdvancedConfig() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/config/section/advanced');
            if (!response) return;

            const data = await response.json();

            if (data.success) {
                const config = data.config;
                document.getElementById('max-concurrent-downloads').value = config.max_concurrent_downloads || 3;
                document.getElementById('provider-timeout').value = config.provider_timeout || 30;
                document.getElementById('enable-debug-mode').checked = config.enable_debug_mode === true;
            }
        } catch (error) {
            console.error('Error loading advanced config:', error);
        }
    }

    async saveAdvancedConfig() {
        try {
            const config = {
                max_concurrent_downloads: parseInt(document.getElementById('max-concurrent-downloads').value),
                provider_timeout: parseInt(document.getElementById('provider-timeout').value),
                enable_debug_mode: document.getElementById('enable-debug-mode').checked
            };

            const response = await this.makeAuthenticatedRequest('/api/config/section/advanced', {
                method: 'POST',
                body: JSON.stringify(config)
            });

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

            if (data.success) {
                this.showToast('Advanced configuration saved successfully', 'success');
            } else {
                this.showToast(`Failed to save config: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error saving advanced config:', error);
            this.showToast('Failed to save advanced configuration', 'error');
        }
    }

    // Main Configuration Methods
    async saveMainConfig() {
        try {
            const animeDirectory = document.getElementById('anime-directory-input').value.trim();

            if (!animeDirectory) {
                this.showToast('Please enter an anime directory path', 'error');
                return;
            }

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

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

            if (data.success) {
                this.showToast('Main configuration saved successfully', 'success');
                // Refresh the status to get updated series count
                await this.refreshStatus();
            } else {
                this.showToast(`Failed to save configuration: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error saving main config:', error);
            this.showToast('Failed to save main configuration', 'error');
        }
    }

    async resetMainConfig() {
        if (confirm('Are you sure you want to reset the main configuration? This will clear the anime directory.')) {
            document.getElementById('anime-directory-input').value = '';
            document.getElementById('series-count-input').value = '0';
            this.showToast('Main configuration reset', 'info');
        }
    }

    async testConnection() {
        try {
            this.showToast('Testing connection...', 'info');

            const response = await this.makeAuthenticatedRequest('/api/diagnostics/network');
            if (!response) return;

            const data = await response.json();

            if (data.status === 'success') {
                const networkStatus = data.data;
                const connectionDiv = document.getElementById('connection-status-display');
                const statusIndicator = connectionDiv.querySelector('.status-indicator');
                const statusText = connectionDiv.querySelector('.status-text');

                if (networkStatus.aniworld_reachable) {
                    statusIndicator.className = 'status-indicator connected';
                    statusText.textContent = 'Connected';
                    this.showToast('Connection test successful', 'success');
                } else {
                    statusIndicator.className = 'status-indicator disconnected';
                    statusText.textContent = 'Disconnected';
                    this.showToast('Connection test failed', 'error');
                }
            } else {
                this.showToast('Connection test failed', 'error');
            }
        } catch (error) {
            console.error('Error testing connection:', error);
            this.showToast('Connection test failed', 'error');
        }
    }

    async browseDirectory() {
        // This would typically open a native directory browser
        // For web applications, we'll show a prompt for manual entry
        const currentPath = document.getElementById('anime-directory-input').value;
        const newPath = prompt('Enter the anime directory path:', currentPath);

        if (newPath !== null && newPath.trim() !== '') {
            document.getElementById('anime-directory-input').value = newPath.trim();
        }
    }

    async refreshStatus() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/anime/status');
            if (!response) return;
            const data = await response.json();

            document.getElementById('anime-directory-input').value = data.directory || '';
            document.getElementById('series-count-input').value = data.series_count || '0';
        } catch (error) {
            console.error('Error refreshing status:', error);
        }
    }

    async createConfigBackup() {
        const backupName = prompt('Enter backup name (optional):');

        try {
            const response = await this.makeAuthenticatedRequest('/api/config/backup', {
                method: 'POST',
                body: JSON.stringify({ name: backupName || '' })
            });

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

            if (data.success) {
                this.showToast(`Backup created: ${data.filename}`, 'success');
            } else {
                this.showToast(`Failed to create backup: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error creating backup:', error);
            this.showToast('Failed to create backup', 'error');
        }
    }

    async viewConfigBackups() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/config/backups');
            if (!response) return;

            const data = await response.json();

            if (data.success) {
                this.showBackupsModal(data.backups);
            } else {
                this.showToast(`Failed to load backups: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error loading backups:', error);
            this.showToast('Failed to load backups', 'error');
        }
    }

    async validateConfig() {
        try {
            const response = await this.makeAuthenticatedRequest('/api/config/validate', {
                method: 'POST',
                body: JSON.stringify({}) // Validate current config
            });

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

            if (data.success) {
                this.showValidationResults(data.validation);
            } else {
                this.showToast(`Validation failed: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error validating config:', error);
            this.showToast('Failed to validate configuration', 'error');
        }
    }

    showValidationResults(validation) {
        const container = document.getElementById('validation-results');
        container.innerHTML = '';
        container.classList.remove('hidden');

        if (validation.valid) {
            const success = document.createElement('div');
            success.className = 'validation-success';
            success.innerHTML = '<i class="fas fa-check-circle"></i> Configuration is valid!';
            container.appendChild(success);
        } else {
            const header = document.createElement('div');
            header.innerHTML = '<strong>Validation Issues Found:</strong>';
            container.appendChild(header);
        }

        // Show errors
        validation.errors.forEach(error => {
            const errorDiv = document.createElement('div');
            errorDiv.className = 'validation-error';
            errorDiv.innerHTML = `<i class="fas fa-times-circle"></i> Error: ${error}`;
            container.appendChild(errorDiv);
        });

        // Show warnings
        validation.warnings.forEach(warning => {
            const warningDiv = document.createElement('div');
            warningDiv.className = 'validation-warning';
            warningDiv.innerHTML = `<i class="fas fa-exclamation-triangle"></i> Warning: ${warning}`;
            container.appendChild(warningDiv);
        });
    }

    async resetConfig() {
        if (!confirm('Are you sure you want to reset all configuration to defaults? This cannot be undone (except by restoring a backup).')) {
            return;
        }

        try {
            const response = await this.makeAuthenticatedRequest('/api/config/reset', {
                method: 'POST',
                body: JSON.stringify({ preserve_security: true })
            });

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

            if (data.success) {
                this.showToast('Configuration reset to defaults', 'success');
                // Reload the config modal
                setTimeout(() => {
                    this.hideConfigModal();
                    this.showConfigModal();
                }, 1000);
            } else {
                this.showToast(`Failed to reset config: ${data.error}`, 'error');
            }
        } catch (error) {
            console.error('Error resetting config:', error);
            this.showToast('Failed to reset configuration', 'error');
        }
    }

    showDownloadQueue(data) {
        const queueSection = document.getElementById('download-queue-section');
        const queueProgress = document.getElementById('queue-progress');

        queueProgress.textContent = `0/${data.total_series} series`;
        this.updateDownloadQueue({
            queue: data.queue || [],
            current_downloading: null,
            stats: {
                completed_series: 0,
                total_series: data.total_series
            }
        });

        queueSection.classList.remove('hidden');
    }

    hideDownloadQueue() {
        const queueSection = document.getElementById('download-queue-section');
        const currentDownload = document.getElementById('current-download');

        queueSection.classList.add('hidden');
        currentDownload.classList.add('hidden');
    }

    updateDownloadQueue(data) {
        const queueList = document.getElementById('queue-list');
        const currentDownload = document.getElementById('current-download');
        const queueProgress = document.getElementById('queue-progress');

        // Update overall progress
        if (data.stats) {
            queueProgress.textContent = `${data.stats.completed_series}/${data.stats.total_series} series`;
        }

        // Update current downloading
        if (data.current_downloading) {
            currentDownload.classList.remove('hidden');
            document.getElementById('current-serie-name').textContent = this.getDisplayName(data.current_downloading);
            document.getElementById('current-episode').textContent = `${data.current_downloading.missing_episodes} episodes remaining`;
        } else {
            currentDownload.classList.add('hidden');
        }

        // Update queue list
        if (data.queue && data.queue.length > 0) {
            queueList.innerHTML = data.queue.map((serie, index) => `
                <div class="queue-item">
                    <div class="queue-item-index">${index + 1}</div>
                    <div class="queue-item-name">${this.escapeHtml(this.getDisplayName(serie))}</div>
                    <div class="queue-item-status">Waiting</div>
                </div>
            `).join('');
        } else {
            queueList.innerHTML = '<div class="queue-empty">No series in queue</div>';
        }
    }

    updateCurrentEpisode(data) {
        const currentEpisode = document.getElementById('current-episode');
        const progressFill = document.getElementById('current-progress-fill');
        const progressText = document.getElementById('current-progress-text');

        if (currentEpisode && data.episode) {
            currentEpisode.textContent = `${data.episode} (${data.episode_progress})`;
        }

        // Update mini progress bar based on overall progress
        if (data.overall_progress && progressFill && progressText) {
            const [current, total] = data.overall_progress.split('/').map(n => parseInt(n));
            const percent = total > 0 ? (current / total * 100).toFixed(1) : 0;

            progressFill.style.width = `${percent}%`;
            progressText.textContent = `${percent}%`;
        }
    }

    updateDownloadProgress(data) {
        const queueProgress = document.getElementById('queue-progress');

        if (queueProgress && data.completed_series && data.total_series) {
            queueProgress.textContent = `${data.completed_series}/${data.total_series} series`;
        }

        this.showToast(`Completed: ${data.serie}`, 'success');
    }

    initMobileAndAccessibility() {
        // Initialize Mobile Responsive Manager
        if (typeof MobileResponsiveManager !== 'undefined') {
            this.mobileResponsive = new MobileResponsiveManager();
        }

        // Initialize Touch Gesture Manager
        if (typeof TouchGestureManager !== 'undefined') {
            this.touchGestures = new TouchGestureManager();
        }

        // Initialize Accessibility Manager
        if (typeof AccessibilityManager !== 'undefined') {
            this.accessibility = new AccessibilityManager();
        }

        // Initialize Screen Reader Manager
        if (typeof ScreenReaderManager !== 'undefined') {
            this.screenReader = new ScreenReaderManager();
        }

        // Initialize Color Contrast Manager
        if (typeof ColorContrastManager !== 'undefined') {
            this.colorContrast = new ColorContrastManager();
        }

        // Initialize Multi-Screen Manager
        if (typeof MultiScreenManager !== 'undefined') {
            this.multiScreen = new MultiScreenManager();
        }

        console.log('Mobile & Accessibility features initialized');
    }

    formatETA(seconds) {
        if (!seconds || seconds <= 0) return '---';

        if (seconds < 60) {
            return `${Math.round(seconds)}s`;
        } else if (seconds < 3600) {
            const minutes = Math.round(seconds / 60);
            return `${minutes}m`;
        } else if (seconds < 86400) {
            const hours = Math.floor(seconds / 3600);
            const minutes = Math.round((seconds % 3600) / 60);
            return `${hours}h ${minutes}m`;
        } else {
            const days = Math.floor(seconds / 86400);
            const hours = Math.round((seconds % 86400) / 3600);
            return `${days}d ${hours}h`;
        }
    }
}

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

// Global functions for inline event handlers
window.app = null;