// === GLOBAL VARIABLES ===
let psshs = chrome.extension.getBackgroundPage().psshs;
let requests = chrome.extension.getBackgroundPage().requests;
let pageURL = chrome.extension.getBackgroundPage().pageURL;
let targetIds = chrome.extension.getBackgroundPage().targetIds;
let clearkey = chrome.extension.getBackgroundPage().clearkey;
let userInputs = {}; // IMPORTANT: Cette variable était manquante!

// === WIDEVINE KEY EXTRACTION ===
class WidevineExtractor {
    static async extractKeys() {
        const guessButton = document.getElementById("guess");
        const resultTextarea = document.getElementById('result');
        
        try {
            // Vérifier que userInputs.license est défini
            if (userInputs.license === undefined || !requests[userInputs.license]) {
                throw new Error('License not selected. Please wait for auto-selection or select manually.');
            }
            
            // UI feedback
            UIHelpers.setLoadingState(guessButton, true);
            document.body.style.cursor = "wait";
            
            // Initialize Pyodide
            const pyodide = await loadPyodide();
            await pyodide.loadPackage([
                "certifi-2024.2.2-py3-none-any.whl",
                "charset_normalizer-3.3.2-py3-none-any.whl", 
                "construct-2.8.8-py2.py3-none-any.whl",
                "idna-3.6-py3-none-any.whl",
                "packaging-23.2-py3-none-any.whl",
                "protobuf-4.24.4-cp312-cp312-emscripten_3_1_52_wasm32.whl",
                "pycryptodome-3.20.0-cp35-abi3-emscripten_3_1_52_wasm32.whl",
                "pymp4-1.4.0-py3-none-any.whl",
                "pyodide_http-0.2.1-py3-none-any.whl",
                "pywidevine-1.8.0-py3-none-any.whl",
                "requests-2.31.0-py3-none-any.whl",
                "urllib3-2.2.1-py3-none-any.whl"
            ].map(e => "/libs/wheels/" + e));

            // Configure Guesser
            pyodide.globals.set("pssh", document.getElementById('pssh').value);
            pyodide.globals.set("licUrl", requests[userInputs['license']]['url']);
            pyodide.globals.set("licHeaders", requests[userInputs['license']]['headers']);
            pyodide.globals.set("licBody", requests[userInputs['license']]['body']);

            // Load Python scripts
            const [pre, after, scheme] = await Promise.all([
                fetch('/python/pre.py').then(res => res.text()),
                fetch('/python/after.py').then(res => res.text()),
                Promise.resolve(document.getElementById("schemeCode").value)
            ]);

            // Execute Python script
            const result = await pyodide.runPythonAsync([pre, scheme, after].join("\n"));
            resultTextarea.value = result;

            // Save to history
            this.saveToHistory(result);
            
            // Auto-update CrawlFlix integration
            CrawlFlixIntegration.updateAfterKeyExtraction();
            
            StatusManager.show('Keys extracted successfully!', 'success');
            
        } catch (error) {
            console.error('Key extraction failed:', error);
            StatusManager.show(`Key extraction failed: ${error.message}`, 'error');
        } finally {
            // Reset UI
            UIHelpers.setLoadingState(guessButton, false);
            document.body.style.cursor = "auto";
        }
    }

    static saveToHistory(result) {
        const historyData = {
            PSSH: document.getElementById('pssh').value,
            KEYS: result.split("\n").slice(0, -1)
        };
        chrome.storage.local.set({[pageURL]: historyData}, null);
    }

    static async autoSelect() {
        userInputs["license"] = 0;
        document.getElementById("license").value = requests[0]['url'];
        document.getElementById('pssh').value = psshs[0];
        
        try {
            const selectRules = await fetch("/selectRules.conf").then(r => r.text());
            const rules = selectRules
                .replace(/\n^\s*$|\s*\/\/.*|\s*$/gm, "")
                .split("\n")
                .map(row => row.split("$$"));

            for (const item of rules) {
                const search = requests.map(r => r['url']).findIndex(e => e.includes(item[0]));
                if (search >= 0) {
                    if (item[1]) document.getElementById("schemeSelect").value = item[1];
                    userInputs["license"] = search;
                    document.getElementById("license").value = requests[search]['url'];
                    break;
                }
            }

            document.getElementById("schemeSelect").dispatchEvent(new Event("input"));
        } catch (error) {
            console.error('Auto-select failed:', error);
        }
    }
}

class MPDCache {
    constructor() {
        this.cachedMPDs = new Map();
        this.validationPromises = new Map();
    }

    hasChanged(newMPDs) {
        const currentUrls = Array.from(this.cachedMPDs.keys()).sort();
        const newUrls = newMPDs.sort();
        
        return JSON.stringify(currentUrls) !== JSON.stringify(newUrls);
    }

    setCachedMPD(url, data) {
        this.cachedMPDs.set(url, {
            ...data,
            lastValidated: Date.now()
        });
    }

    // Récupère un MPD du cache
    getCachedMPD(url) {
        return this.cachedMPDs.get(url);
    }

    // Supprime un MPD invalide du cache
    removeMPD(url) {
        this.cachedMPDs.delete(url);
        this.validationPromises.delete(url);
    }

    // Récupère tous les MPDs valides triés par score/durée
    getValidMPDs() {
        return Array.from(this.cachedMPDs.entries())
            .map(([url, data]) => ({ url, ...data }))
            .sort((a, b) => {
                // Prioriser d'abord par durée si disponible
                if (a.duration && b.duration) {
                    return b.duration - a.duration;
                }
                // Sinon par score
                return b.score - a.score;
            });
    }

    cleanup(maxAge = 5 * 60 * 1000) {
        const now = Date.now();
        for (const [url, data] of this.cachedMPDs.entries()) {
            if (now - data.lastValidated > maxAge) {
                this.removeMPD(url);
            }
        }
    }
}

class MPDValidator {
    static async validateMPD(url) {
        const API_URL = 'http://192.168.1.230:6080/api/processMpd';
        
        try {
            const response = await fetch(API_URL, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    mp4Filename: "validation_test",
                    mpdUrl: url
                })
            });

            if (!response.ok) {
                throw new Error(`API returned ${response.status}: ${response.statusText}`);
            }

            const result = await response.json();
            
            // Valider la structure de la réponse
            if (!result.videoTracks || !Array.isArray(result.videoTracks)) {
                throw new Error('Invalid response structure: missing videoTracks array');
            }

            // Calculer la durée maximale parmi les tracks
            const maxDuration = result.videoTracks.reduce((max, track) => {
                const duration = track.duration || 0;
                return Math.max(max, duration);
            }, 0);

            return {
                valid: true,
                duration: maxDuration,
                videoTracks: result.videoTracks,
                raw: result
            };

        } catch (error) {
            console.error(`MPD validation failed for ${url}:`, error);
            return {
                valid: false,
                error: error.message,
                duration: 0
            };
        }
    }

    static async validateMPDWithCache(url, cache) {
        // Vérifier si on a déjà une promesse en cours pour cette URL
        if (cache.validationPromises.has(url)) {
            return await cache.validationPromises.get(url);
        }

        // Créer une nouvelle promesse de validation
        const validationPromise = this.validateMPD(url);
        cache.validationPromises.set(url, validationPromise);

        try {
            const result = await validationPromise;
            return result;
        } finally {
            // Nettoyer la promesse une fois terminée
            cache.validationPromises.delete(url);
        }
    }
}

class SmartMPDSelector {
	static scoreAndRankMPDs(mpdUrls) {
		const scoredMPDs = mpdUrls.map(url => ({
			url,
			score: this.calculateMPDScore(url),
			reason: this.getSelectionReason(url)
		}));

		// Trier par score décroissant
		return scoredMPDs.sort((a, b) => b.score - a.score);
	}

	static calculateMPDScore(url) {
		let score = 0;
		const urlLower = url.toLowerCase();

		// === CRITÈRES NÉGATIFS (à éviter) ===
		
		// Éliminer les URLs non-MPD
		if (urlLower.includes('github.com') || urlLower.includes('manifest.json')) {
			return -1000; // Score très négatif
		}
		
		// Éviter les URLs avec trop de redirections/proxies
		if (urlLower.includes('routemeup') || urlLower.includes('route=')) {
			score -= 200;
		}
		
		// Éviter les URLs avec double-encoding ou trop complexes
		if (url.includes('__token__') && url.includes('%')) {
			score -= 100;
		}

		// === CRITÈRES POSITIFS (à privilégier) ===
		
		// Privilégier les URLs directes CDN
		if (urlLower.includes('cdn.net') || urlLower.includes('vod-')) {
			score += 300;
		}
		
		// Privilégier les URLs avec .mpd explicite
		if (url.endsWith('.mpd') || urlLower.includes('.mpd?')) {
			score += 200;
		}
		
		// Privilégier les URLs courtes (moins de proxies)
		if (url.length < 300) {
			score += 100;
		} else if (url.length > 500) {
			score -= 50;
		}
		
		// Privilégier les tokens JWT simples vs double tokens
		const tokenCount = (url.match(/token=/g) || []).length;
		if (tokenCount === 1) {
			score += 50;
		} else if (tokenCount > 1) {
			score -= 100;
		}
		
		// Privilégier les URLs sans encoding excessif
		const encodingScore = url.length - decodeURIComponent(url).length;
		if (encodingScore < 50) {
			score += 50;
		} else {
			score -= encodingScore;
		}

		// === CRITÈRES SPÉCIFIQUES CANAL+ ===
		
		// Détecter le pattern Canal+/Paramount+
		if (urlLower.includes('paramountplus') || urlLower.includes('viacom')) {
			score += 100;
			
			// Privilégier les edge servers directs
			if (urlLower.includes('p-cdnvod-edge') && !urlLower.includes('routemeup')) {
				score += 150;
			}
		}

		return score;
	}

	static getSelectionReason(url) {
		const urlLower = url.toLowerCase();
		
		if (urlLower.includes('github.com')) {
			return 'Excluded: Not a media manifest';
		}
		
		if (urlLower.includes('routemeup')) {
			return 'Router/proxy URL (lower priority)';
		}
		
		if (urlLower.includes('p-cdnvod-edge') && !urlLower.includes('routemeup')) {
			return 'Direct CDN edge server (optimal)';
		}
		
		if (url.includes('__token__')) {
			return 'Tokenized CDN URL';
		}
		
		return 'Standard MPD URL';
	}

	static getBestMPD(mpdUrls) {
		if (!mpdUrls || mpdUrls.length === 0) return null;
		if (mpdUrls.length === 1) return mpdUrls[0];

		const rankedMPDs = this.scoreAndRankMPDs(mpdUrls);
		const best = rankedMPDs[0];
		
		console.log('MPD Selection Results:', rankedMPDs);
		
		// Ne retourner que si le score est positif
		return best.score > 0 ? best.url : null;
	}

	static analyzeAndDisplayMPDs(mpdUrls) {
		const rankedMPDs = this.scoreAndRankMPDs(mpdUrls);
		
		// Afficher l'analyse dans la console pour debug
		console.table(rankedMPDs.map(mpd => ({
			URL: this.truncateUrl(mpd.url),
			Score: mpd.score,
			Reason: mpd.reason
		})));

		return rankedMPDs;
	}

	static truncateUrl(url, maxLength = 60) {
		if (url.length <= maxLength) return url;
		
		try {
			const urlObj = new URL(url);
			const domain = urlObj.hostname;
			const filename = urlObj.pathname.split('/').pop();
			return `${domain}/.../${filename}`;
		} catch {
			return url.substring(0, maxLength) + '...';
		}
	}

	// Fonction pour mettre à jour l'UI avec le meilleur MPD
	static updateUIWithBestMPD(mpdUrls) {
		const bestMPD = this.getBestMPD(mpdUrls);
		
		if (bestMPD) {
			// Auto-sélectionner le meilleur MPD
			const selects = ['mpdSelect', 'mpdSelectCK'];
			const inputs = ['mpdUrl', 'mpdUrlCK'];
			
			selects.forEach((selectId, index) => {
				const select = document.getElementById(selectId);
				const input = document.getElementById(inputs[index]);
				
				if (select && input) {
					select.value = bestMPD;
					input.value = bestMPD;
					
					// Ajouter une classe pour indiquer la sélection auto
					select.classList.add('border-success');
					setTimeout(() => select.classList.remove('border-success'), 3000);
				}
			});

			const analysis = this.analyzeAndDisplayMPDs(mpdUrls);
			const bestAnalysis = analysis[0];
			
			StatusManager.show(
				`Auto-selected best MPD: ${bestAnalysis.reason}`, 
				'success'
			);
		}
	}
}

class MPDDetector {
    constructor() {
        this.cache = new MPDCache();
        this.isUpdating = false;
    }

    static detectMPDUrls() {
        const backgroundPage = chrome.extension.getBackgroundPage();
        const detectedMPDs = backgroundPage.detectedMPDs || [];
        
        console.log('Raw detected MPDs:', detectedMPDs);
        
        return detectedMPDs
            .filter((url, index, arr) => arr.indexOf(url) === index) // Remove duplicates
            .filter(url => url && url.length > 0) // Remove empty URLs
            .filter(url => !url.includes('/chunk-') && !url.includes('/segment-')); // Filter segments
    }

    async updateDropdowns() {
        // Éviter les mises à jour simultanées
        if (this.isUpdating) {
            console.log('MPD update already in progress, skipping...');
            return;
        }

        this.isUpdating = true;
        
        try {
            const rawMPDs = MPDDetector.detectMPDUrls();
            
            // Vérifier si la liste a changé
            if (!this.cache.hasChanged(rawMPDs)) {
                console.log('MPD list unchanged, using cache');
                this.renderDropdowns();
                return;
            }

            console.log('MPD list changed, updating cache...');
            
            // Nettoyer le cache des URLs qui ne sont plus détectées
            const currentCachedUrls = Array.from(this.cache.cachedMPDs.keys());
            currentCachedUrls.forEach(url => {
                if (!rawMPDs.includes(url)) {
                    this.cache.removeMPD(url);
                }
            });

            // Traiter les nouvelles URLs
            const newUrls = rawMPDs.filter(url => !this.cache.getCachedMPD(url));
            
            if (newUrls.length > 0) {
                StatusManager.show(
                    `Validating ${newUrls.length} new MPD(s)...`, 
                    'info'
                );

                await this.processNewMPDs(newUrls);
            }

            // Rendre les dropdowns
            this.renderDropdowns();
            
            // Nettoyer le cache périodiquement
            this.cache.cleanup();

        } catch (error) {
            console.error('MPD update failed:', error);
            StatusManager.show(`MPD update failed: ${error.message}`, 'error');
        } finally {
            this.isUpdating = false;
        }
    }

    async processNewMPDs(urls) {
        const validationPromises = urls.map(async (url) => {
            try {
                // Calculer le score initial (logique existante)
                const initialScore = SmartMPDSelector.calculateMPDScore(url);
                const reason = SmartMPDSelector.getSelectionReason(url);

                // Valider via API
                const validationResult = await MPDValidator.validateMPDWithCache(url, this.cache);
                
                if (validationResult.valid) {
                    // Ajuster le score basé sur la durée
                    let finalScore = initialScore;
                    if (validationResult.duration > 0) {
                        // Bonus pour les durées plus longues
                        finalScore += Math.min(validationResult.duration / 10, 500); // Max +500 points
                    }

                    this.cache.setCachedMPD(url, {
                        score: finalScore,
                        reason: `${reason} | Duration: ${validationResult.duration}s`,
                        duration: validationResult.duration,
                        valid: true,
                        videoTracks: validationResult.videoTracks
                    });

                    console.log(`✅ MPD validated: ${url} (duration: ${validationResult.duration}s)`);
                } else {
                    // MPD invalide, ne pas l'ajouter au cache
                    console.log(`❌ MPD invalid: ${url} (${validationResult.error})`);
                }
            } catch (error) {
                console.error(`Error processing MPD ${url}:`, error);
            }
        });

        await Promise.allSettled(validationPromises);
    }

    renderDropdowns() {
        const validMPDs = this.cache.getValidMPDs();
        const selects = ['mpdSelect', 'mpdSelectCK'];
        
        selects.forEach(selectId => {
            const select = document.getElementById(selectId);
            if (!select) return;

            select.innerHTML = '<option value="">-- Validated MPDs --</option>';
            
            validMPDs.forEach((mpdInfo, index) => {
                const option = document.createElement('option');
                option.value = mpdInfo.url;
                
                // Indicateurs visuels améliorés
                let prefix = '';
                if (index === 0) {
                    prefix = `🏆 [${mpdInfo.duration}s] `;
                } else if (mpdInfo.duration > 0) {
                    prefix = `⏱️ [${mpdInfo.duration}s] `;
                } else if (mpdInfo.score > 0) {
                    prefix = '✅ ';
                } else {
                    prefix = '⚠️ ';
                }
                
                option.textContent = prefix + this.formatUrlForDisplay(mpdInfo.url);
                option.title = `Score: ${mpdInfo.score} | ${mpdInfo.reason}`;
                
                // Styling
                if (index === 0) {
                    option.style.fontWeight = 'bold';
                    option.style.color = '#28a745';
                } else if (mpdInfo.duration > 1000) { // Plus de 16 minutes
                    option.style.color = '#17a2b8';
                } else if (mpdInfo.score <= 0) {
                    option.style.color = '#dc3545';
                }
                
                select.appendChild(option);
            });
        });

        // Auto-sélection du meilleur
        if (validMPDs.length > 0) {
            this.selectBestMPD(validMPDs[0]);
        }

        // Mettre à jour le status
        const totalDetected = MPDDetector.detectMPDUrls().length;
        const validCount = validMPDs.length;
        const invalidCount = totalDetected - validCount;
        
        let statusMessage = `Found ${validCount} valid MPD(s)`;
        if (invalidCount > 0) {
            statusMessage += ` (${invalidCount} filtered out)`;
        }
        
        StatusManager.show(statusMessage, validCount > 0 ? 'success' : 'warning');
    }

    selectBestMPD(bestMPD) {
        const selects = ['mpdSelect', 'mpdSelectCK'];
        const inputs = ['mpdUrl', 'mpdUrlCK'];
        
        selects.forEach((selectId, index) => {
            const select = document.getElementById(selectId);
            const input = document.getElementById(inputs[index]);
            
            if (select && input) {
                select.value = bestMPD.url;
                input.value = bestMPD.url;
                
                // Effet visuel
                select.classList.add('border-success');
                setTimeout(() => select.classList.remove('border-success'), 3000);
            }
        });
    }

    formatUrlForDisplay(url) {
        return SmartMPDSelector.truncateUrl(url, 80);
    }

    // Méthode publique pour forcer la mise à jour
    async forceUpdate() {
        this.cache = new MPDCache(); // Reset du cache
        await this.updateDropdowns();
    }
}

const mpdDetectorInstance = new MPDDetector();
MPDDetector.updateDropdowns = () => mpdDetectorInstance.updateDropdowns();
MPDDetector.forceUpdate = () => mpdDetectorInstance.forceUpdate();

// === CRAWLFLIX INTEGRATION ===
class CrawlFlixIntegration {
    static async sendToCrawlFlix(isClearchey = false) {
        const suffix = isClearchey ? 'CK' : '';
        const crawlFlixUrl = document.getElementById(`crawlFlixUrl${suffix}`).value || 'http://localhost:4200';
        const mpdUrl = document.getElementById(`mpdUrl${suffix}`).value;
        const resultTextarea = document.getElementById(isClearchey ? 'ckResult' : 'result');
        
        // Validation
        if (!mpdUrl.trim()) {
            StatusManager.show('Please enter or select an MPD URL', 'error', suffix);
            return;
        }
        
        if (!resultTextarea.value.trim()) {
            StatusManager.show('No keys available to send', 'error', suffix);
            return;
        }
        
        try {
            StatusManager.show('Opening CrawlFlix with preloaded data...', 'info', suffix);
            
            // Parse et valide les clés pour information
            const keys = this.parseKeys(resultTextarea.value);
            if (keys.length === 0) {
                StatusManager.show('No valid keys found in the format key:value', 'error', suffix);
                return;
            }

            // Ouvrir CrawlFlix directement avec les paramètres
            this.openCrawlFlixTab(crawlFlixUrl, mpdUrl, resultTextarea.value);
            
            // Message de succès
            const contentType = isClearchey ? 'ClearKey' : 'Widevine';
            StatusManager.show(`${contentType} data sent to CrawlFlix! (${keys.length} keys, MPD URL)`, 'success', suffix);
            
        } catch (error) {
            console.error('CrawlFlix send error:', error);
            StatusManager.show(`Failed to send: ${error.message}`, 'error', suffix);
        }
    }

    static parseKeys(keysText) {
        return keysText
            .split('\n')
            .map(line => line.trim())
            .filter(line => line && line.includes(':'))
            .map(line => {
                const [key, value] = line.split(':');
                return { 
                    key: key?.trim(), 
                    value: value?.trim() 
                };
            })
            .filter(k => k.key && k.value && k.key.length > 0 && k.value.length > 0);
    }

    static async processMPD(crawlFlixUrl, mpdUrl) {
        const response = await fetch(`${crawlFlixUrl}/processMPD`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ mpdUrl })
        });
        
        if (!response.ok) {
            const errorText = await response.text().catch(() => 'Unknown error');
            throw new Error(`MPD processing failed (${response.status}): ${errorText}`);
        }
        
        return await response.json();
    }

    static openCrawlFlixTab(crawlFlixUrl, mpdUrl, keysText) {
        // Encoder les données pour l'URL
        const params = new URLSearchParams({
            mpdUrl: mpdUrl,
            keys: keysText,
            autoLoad: 'true'
        });
        
        // Ouvrir CrawlFlix avec les paramètres pré-remplis
        const crawlFlixTab = `${crawlFlixUrl}?${params.toString()}`;
        chrome.tabs.create({ url: crawlFlixTab });
        
        console.log('Opening CrawlFlix with preloaded data:', crawlFlixTab);
    }

    static copyKeys(resultTextareaId) {
        const textarea = document.getElementById(resultTextareaId);
        if (!textarea || !textarea.value.trim()) {
            StatusManager.show('No keys to copy', 'error');
            return;
        }

        navigator.clipboard.writeText(textarea.value).then(() => {
            StatusManager.show('Keys copied to clipboard!', 'success');
        }).catch(err => {
            console.error('Copy failed:', err);
            StatusManager.show('Failed to copy keys', 'error');
        });
    }

    static updateAfterKeyExtraction() {
        // Auto-refresh MPD detection after key extraction
        setTimeout(() => {
            MPDDetector.updateDropdowns();
        }, 1000);
    }

    static loadSavedSettings() {
        chrome.storage.local.get(['crawlFlixUrl'], (result) => {
            if (result.crawlFlixUrl) {
                const inputs = ['crawlFlixUrl', 'crawlFlixUrlCK'];
                inputs.forEach(id => {
                    const input = document.getElementById(id);
                    if (input && !input.value) {
                        input.value = result.crawlFlixUrl;
                    }
                });
            }
        });
    }

    static saveSettings() {
        const inputs = ['crawlFlixUrl', 'crawlFlixUrlCK'];
        inputs.forEach(id => {
            const input = document.getElementById(id);
            if (input) {
                input.addEventListener('change', (e) => {
                    chrome.storage.local.set({ crawlFlixUrl: e.target.value });
                });
            }
        });
    }
}

// === STATUS MANAGER ===
class StatusManager {
    static show(message, type, suffix = '') {
        const statusDiv = document.getElementById(`crawlFlixStatus${suffix}`);
        if (!statusDiv) return;

        // Clear any existing content
        statusDiv.innerHTML = '';

        // Create alert element
        const alert = document.createElement('div');
        alert.className = `alert alert-${this.getBootstrapClass(type)} alert-dismissible fade show`;
        alert.innerHTML = `
            <i class="fas ${this.getIcon(type)} me-2"></i>
            ${message.replace(/\n/g, '<br>')}
            <button type="button" class="btn-close btn-close-sm" data-bs-dismiss="alert"></button>
        `;
        
        statusDiv.appendChild(alert);

        // Auto-dismiss after delay
        if (type === 'success' || type === 'info') {
            setTimeout(() => {
                if (alert.parentNode) {
                    alert.classList.remove('show');
                    setTimeout(() => alert.remove(), 300);
                }
            }, 5000);
        }
    }

    static getBootstrapClass(type) {
        const mapping = {
            success: 'success',
            error: 'danger', 
            info: 'info',
            warning: 'warning'
        };
        return mapping[type] || 'secondary';
    }

    static getIcon(type) {
        const mapping = {
            success: 'fa-check-circle',
            error: 'fa-exclamation-triangle',
            info: 'fa-info-circle',
            warning: 'fa-exclamation-triangle'
        };
        return mapping[type] || 'fa-info';
    }
}

// === UI HELPERS ===
class UIHelpers {
    static setLoadingState(button, isLoading) {
        if (!button) return;
        
        if (isLoading) {
            button.disabled = true;
            const originalText = button.innerHTML;
            button.dataset.originalText = originalText;
            button.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Extracting Keys...';
        } else {
            button.disabled = false;
            button.innerHTML = '<i class="fas fa-magic me-2"></i> Extract Widevine Keys';
        }
    }

    static copyToClipboard(text) {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand('copy');
        document.body.removeChild(textarea);
    }
}

// === EVENT LISTENERS ===
class EventManager {
    static init() {
        this.setupWidevineListeners();
        this.setupCrawlFlixListeners();
        this.setupUIListeners();
    }

    static setupWidevineListeners() {
        const guessButton = document.getElementById('guess');
        const resultTextarea = document.getElementById('result');
        
        if (guessButton) {
            guessButton.addEventListener('click', () => WidevineExtractor.extractKeys());
        }
        
        if (resultTextarea) {
            resultTextarea.addEventListener('click', function() {
                this.select();
                navigator.clipboard.writeText(this.value);
            });
        }
    }

    static setupCrawlFlixListeners() {
        // Dropdown selections
        ['mpdSelect', 'mpdSelectCK'].forEach(selectId => {
            const select = document.getElementById(selectId);
            const urlInput = document.getElementById(selectId.replace('Select', 'Url'));
            if (select && urlInput) {
                select.addEventListener('change', (e) => {
                    if (e.target.value) {
                        urlInput.value = e.target.value;
                    }
                });
            }
        });

        // Refresh buttons
        ['refreshMPDs', 'refreshMPDsCK'].forEach(buttonId => {
            const button = document.getElementById(buttonId);
            if (button) {
                button.addEventListener('click', async () => {
                    button.disabled = true;
                    button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Refreshing...';
                    
                    try {
                        await MPDDetector.forceUpdate();
                    } finally {
                        button.disabled = false;
                        button.innerHTML = '<i class="fas fa-sync"></i> Refresh';
                    }
                });
            }
        });

        // Send buttons
        const sendButton = document.getElementById('sendToCrawlFlix');
        if (sendButton) {
            sendButton.addEventListener('click', () => CrawlFlixIntegration.sendToCrawlFlix(false));
        }

        const sendButtonCK = document.getElementById('sendToCrawlFlixCK'); 
        if (sendButtonCK) {
            sendButtonCK.addEventListener('click', () => CrawlFlixIntegration.sendToCrawlFlix(true));
        }

        // Copy buttons
        const copyButton = document.getElementById('copyKeys');
        if (copyButton) {
            copyButton.addEventListener('click', () => CrawlFlixIntegration.copyKeys('result'));
        }

        const copyButtonCK = document.getElementById('copyKeysCK');
        if (copyButtonCK) {
            copyButtonCK.addEventListener('click', () => CrawlFlixIntegration.copyKeys('ckResult'));
        }
    }

    static setupUIListeners() {
        // ClearKey result click handler
        const ckResult = document.getElementById('ckResult');
        if (ckResult) {
            ckResult.addEventListener('click', function() {
                this.select();
                navigator.clipboard.writeText(this.value);
            });
        }
    }
}

// === CORS FETCH HELPER ===
window.corsFetch = (u, m, h, b) => {
    return new Promise((resolve, reject) => {
        chrome.tabs.sendMessage(targetIds[0], {
            type: "FETCH", 
            u: u, 
            m: m, 
            h: h, 
            b: b
        }, {frameId: targetIds[1]}, res => {
            resolve(res);
        });
    });
};

// === INITIALIZATION ===
document.addEventListener('DOMContentLoaded', () => {
    EventManager.init();
    CrawlFlixIntegration.loadSavedSettings();
    CrawlFlixIntegration.saveSettings();
});

// Main initialization logic
if (clearkey) {
    // ClearKey detected
    document.getElementById('noEME').style.display = 'none';
    document.getElementById('ckHome').style.display = 'block';
    document.getElementById('ckResult').value = clearkey;
    
    MPDDetector.updateDropdowns();
    StatusManager.show('ClearKey content detected', 'success');
    
} else if (psshs.length) {
    // Widevine detected  
    document.getElementById('noEME').style.display = 'none';
    document.getElementById('home').style.display = 'block';
    
    WidevineExtractor.autoSelect().then(async () => {
        EventManager.init();
        await MPDDetector.updateDropdowns();
        StatusManager.show('Widevine content detected and configured', 'success');
    });
    
    // Réduire la fréquence de refresh automatique
    setInterval(() => {
        MPDDetector.updateDropdowns(); // Ne se met à jour que si nécessaire
    }, 60000); // Augmenté à 10 secondes au lieu de 3
}