// === 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 = {};

// === WIDEVINE KEY EXTRACTION ===
class WidevineExtractor {
	static async extractKeys() {
		const guessButton = document.getElementById("guess");
		const resultTextarea = document.getElementById('result');
		
		try {
			// 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);
		}
	}
}

// === SMART MPD SELECTOR ===
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 {
	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
	}

	static updateBadgeFromPopup() {
		const backgroundPage = chrome.extension.getBackgroundPage();
		if (backgroundPage && backgroundPage.updateExtensionBadge) {
			backgroundPage.updateExtensionBadge();
		}
	}

	static updateDropdowns() {
		const mpdUrls = this.detectMPDUrls();
		const selects = ['mpdSelect', 'mpdSelectCK'];
		
		selects.forEach(selectId => {
			const select = document.getElementById(selectId);
			if (!select) return;

			select.innerHTML = '<option value="">-- Auto-detected MPDs --</option>';
			
			// Utiliser le smart selector pour trier les MPDs
			const rankedMPDs = SmartMPDSelector.scoreAndRankMPDs(mpdUrls);
			
			rankedMPDs.forEach((mpdInfo, index) => {
				const option = document.createElement('option');
				option.value = mpdInfo.url;
				
				// Ajouter des indicateurs visuels
				const prefix = index === 0 ? '⭐ [BEST] ' : 
							 mpdInfo.score > 0 ? '✓ ' : '⚠ ';
				
				option.textContent = prefix + this.formatUrlForDisplay(mpdInfo.url);
				
				// Ajouter des classes CSS pour styling
				if (index === 0) {
					option.style.fontWeight = 'bold';
					option.style.color = '#28a745';
				} else if (mpdInfo.score <= 0) {
					option.style.color = '#dc3545';
				}
				
				select.appendChild(option);
			});
		});

		// Auto-sélection intelligente
		if (mpdUrls.length > 0) {
			SmartMPDSelector.updateUIWithBestMPD(mpdUrls);
		}

		// Mettre à jour le status avec l'analyse
		StatusManager.show(
			`Found ${mpdUrls.length} MPD(s) - Auto-selected best candidate`, 
			'info'
		);
	}

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

// === CRAWLFLIX INTEGRATION ===
class CrawlFlixIntegration {
	static async sendToCrawlFlix(isClearchey = false) {
		const suffix = isClearchey ? 'CK' : '';
		const crawlFlixUrl = document.getElementById(`crawlFlixUrl${suffix}`).value || 'http://localhost:3000';
		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('Processing MPD and sending to CrawlFlix...', 'info', suffix);
			
			// Parse and validate keys
			const keys = this.parseKeys(resultTextarea.value);
			if (keys.length === 0) {
				StatusManager.show('No valid keys found in the format key:value', 'error', suffix);
				return;
			}

			// Test CrawlFlix connection and process MPD
			const mpdData = await this.processMPD(crawlFlixUrl, mpdUrl);
			
			// Create success message
			const message = `✓ Successfully sent to CrawlFlix!
${keys.length} key(s) • ${mpdData.videoTracks.length} video track(s) • ${mpdData.audioTracks.length} audio track(s) • ${mpdData.subtitles.length} subtitle(s)`;
			
			StatusManager.show(message, 'success', suffix);
			
			// Open CrawlFlix with pre-filled data
			this.openCrawlFlixTab(crawlFlixUrl, mpdUrl, resultTextarea.value);
			
		} 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) {
		const params = new URLSearchParams({
			mpdUrl: mpdUrl,
			keys: keysText,
			source: 'widevine-plugin'
		});
		
		const crawlFlixTab = `${crawlFlixUrl}?${params.toString()}`;
		chrome.tabs.create({ url: 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 = button.dataset.originalText || button.innerHTML;
		}
	}

	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', () => MPDDetector.updateDropdowns());
			}
		});

		// 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');
	MPDDetector.updateBadgeFromPopup();
} else if (psshs.length) {
	// Widevine detected  
	document.getElementById('noEME').style.display = 'none';
	document.getElementById('home').style.display = 'block';
	
	WidevineExtractor.autoSelect();
	MPDDetector.updateDropdowns();
	StatusManager.show('Widevine content detected', 'success');
	MPDDetector.updateBadgeFromPopup();
	// Auto-refresh MPD detection periodically
	setInterval(() => {
		MPDDetector.updateDropdowns();
	}, 3000);
}