let player;
let ui;
const DEBUG_MODE = false;

function debugLog(...args) {
    if (DEBUG_MODE) console.debug("[ShakaDebug]", ...args);
}

async function resolveFinalUrl(originalUrl, requestHeaders = {}) {
    debugLog(`Resolviendo URL final para: ${originalUrl}`);
    try {
        const response = await fetch(originalUrl, {
            method: 'GET',
            headers: requestHeaders,
            redirect: 'follow'
        });

        const finalUrl = response.url;
        debugLog(`URL resuelta a: ${finalUrl}`);
        
        const contentType = response.headers.get("content-type") || "";
        const isStreamContentType = contentType.includes("application/dash+xml") || contentType.includes("application/vnd.apple.mpegurl") || contentType.includes("octet-stream");

        if (!isStreamContentType && !detectMimeType(finalUrl)) {
             debugLog(`URL resuelta ${finalUrl} no parece ser un stream (Content-Type: ${contentType}). Se usará de todas formas.`);
        }
        
        return finalUrl;
    } catch (error) {
        console.error("Error al resolver URL final:", error);
        return originalUrl;
    }
}

function formatShakaError(error, channelName = 'el canal') {
    let message = `Error en "${escapeHtml(channelName)}": `;
    if (error.code) message += `(Cód: ${error.code}) `;
    if (error.message) message += error.message;
    if (error.data && error.data.length > 0) message += ` Detalles: ${error.data.join(', ')}`;
    if (error.category) message += ` (Categoría: ${error.category})`;

    switch (error.code) {
        case shaka.util.Error.Code.LOAD_FAILED:
        case shaka.util.Error.Code.HTTP_ERROR:
            message += " Posibles causas: URL incorrecta, red, CORS, o servidor no responde.";
            break;
        default:
            if (error.category === shaka.util.Error.Category.DRM) {
                message += " Problema DRM: licencia inválida, servidor inaccesible o contenido protegido.";
            }
    }
    return message.length > 300 ? message.slice(0, 300) + '...' : message;
}

function validateShakaConfig(config) {
    if (!config || !config.streaming || !config.manifest) {
        throw new Error("Configuración de Shaka inválida: faltan claves esenciales (streaming, manifest).");
    }
    return true;
}

async function applyHttpHeaders(headersObject, urlFilter = null, initiatorDomain = null) {
    if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.sendMessage) {
        const dnrHeaders = [];
        for (const key in headersObject) {
            if (Object.hasOwnProperty.call(headersObject, key)) {
                dnrHeaders.push({ header: key, operation: 'set', value: String(headersObject[key]) });
            }
        }
        try {
            await new Promise((resolve, reject) => {
                const messagePayload = {
                    cmd: "updateHeadersRules",
                    requestHeaders: dnrHeaders
                };
                if (urlFilter) {
                    messagePayload.urlFilter = urlFilter;
                }
                if (initiatorDomain) {
                    messagePayload.initiatorDomain = initiatorDomain;
                }
                chrome.runtime.sendMessage(messagePayload, (response) => {
                    if (chrome.runtime.lastError) {
                        reject(chrome.runtime.lastError);
                    } else if (response && response.success) {
                        resolve(response);
                    } else {
                        reject(response ? response.error : 'Respuesta desconocida o fallida del background script');
                    }
                });
            });
            debugLog("Cabeceras DNR aplicadas:", dnrHeaders);
        } catch (error) {
            console.error("[Shaka ApplyHeaders] Error al actualizar las reglas de cabecera:", error);
            if (typeof showNotification === 'function') showNotification("Error al aplicar cabeceras de red: " + (error.message || error), "error");
        }
    } else {
        console.warn("[Shaka ApplyHeaders] API de Chrome runtime no disponible. Las cabeceras no serán aplicadas por la extensión.");
    }
}

function buildShakaConfig(channel, isPreview = false) {
    const kodiProps = channel.kodiProps || {};

    let config = {
        drm: {
            servers: {},
            clearKeys: {},
            advanced: {
                'com.widevine.alpha': { videoRobustness: ['SW_SECURE_CRYPTO'], audioRobustness: ['SW_SECURE_CRYPTO'] },
                'com.microsoft.playready': { videoRobustness: ['SW'], audioRobustness: ['SW'] }
            }
        },
        manifest: {
            retryParameters: {
                maxAttempts: isPreview ? 1 : safeParseInt(userSettings.manifestRetryMaxAttempts, 2),
                timeout: isPreview ? 5000 : safeParseInt(userSettings.manifestRetryTimeout, 15000)
            },
            dash: { defaultPresentationDelay: parseFloat(userSettings.shakaDefaultPresentationDelay) },
            hls: { ignoreTextStreamFailures: true }
        },
        streaming: {
            retryParameters: {
                maxAttempts: isPreview ? 1 : safeParseInt(userSettings.segmentRetryMaxAttempts, 2),
                timeout: isPreview ? 5000 : safeParseInt(userSettings.segmentRetryTimeout, 15000)
            },
            lowLatencyMode: userSettings.lowLatencyMode,
            liveSync: { enabled: userSettings.liveCatchUpMode },
            ignoreTextStreamFailures: true
        },
        abr: {
            enabled: !isPreview && userSettings.abrEnabled,
            defaultBandwidthEstimate: isPreview ? 500000 : safeParseInt(userSettings.abrDefaultBandwidthEstimate, 1000) * 1000,
            restrictions: {}
        },
        preferredAudioLanguage: userSettings.preferredAudioLanguage,
        preferredTextLanguage: userSettings.preferredTextLanguage,
    };

    if (isPreview) {
        config.abr.restrictions.maxHeight = 480;
        config.streaming.bufferingGoal = 5;
    } else {
        const channelBuffer = channel.attributes ? parseFloat(channel.attributes['player-buffer']) : NaN;
        config.streaming.bufferingGoal = !isNaN(channelBuffer) && channelBuffer >= 0 ? channelBuffer : safeParseInt(userSettings.playerBuffer, 30);
        const maxVideoHeight = safeParseInt(userSettings.maxVideoHeight, 0);
        if (maxVideoHeight > 0) {
            config.abr.restrictions.maxHeight = maxVideoHeight;
        }
    }
     if(Object.keys(config.abr.restrictions).length === 0) {
         delete config.abr.restrictions;
    }

    const licenseType = kodiProps['inputstream.adaptive.license_type']?.toLowerCase().trim();
    const licenseKey = kodiProps['inputstream.adaptive.license_key']?.trim();
    const serverCertB64 = kodiProps['inputstream.adaptive.server_certificate']?.trim();

    if (licenseType && licenseKey) {
        if (licenseType.includes('clearkey')) {
            const parsedClearKeys = parseClearKey(licenseKey);
            if (parsedClearKeys) config.drm.clearKeys = parsedClearKeys;
        } else if (licenseType.includes('widevine') || licenseType.includes('playready')) {
            const drmSystem = licenseType.includes('widevine') ? 'com.widevine.alpha' : 'com.microsoft.playready';
            if (licenseKey.match(/^https?:\/\//)) {
                config.drm.servers[drmSystem] = licenseKey;
                if (serverCertB64 && config.drm.advanced[drmSystem]) {
                    try {
                        config.drm.advanced[drmSystem].serverCertificate = shaka.util.Uint8ArrayUtils.fromBase64(serverCertB64);
                    } catch (e) { console.error(`[Shaka Play] Error parseando certificado ${drmSystem} (Base64): ${e.message}`); }
                }
            }
        }
    }

    if (Object.keys(config.drm.servers).length === 0 && Object.keys(config.drm.clearKeys).length === 0) {
        delete config.drm;
    }

    debugLog("Configuración de Shaka generada:", config);
    return config;
}

function updatePlayerConfigFromSettings(playerInstance) {
    if (!playerInstance) return;
    const channel = playerInstances[activePlayerId]?.channel || {};
    const config = buildShakaConfig(channel, false);
    validateShakaConfig(config);
    playerInstance.configure(config);

    const ui = playerInstances[activePlayerId]?.ui;
    if (ui) {
        ui.configure({
            fadeDelay: userSettings.persistentControls ? Infinity : 0
        });
    }
}

function getChannelHeaders(channel) {
    const requestHeaders = {};
    const kodiProps = channel.kodiProps || {};
    const vlcOpts = channel.vlcOptions || {};
    const extHttpHeaders = channel.extHttp || {};

    if (channel.sourceOrigin && channel.sourceOrigin.toLowerCase().startsWith('xtream')) {
        requestHeaders['User-Agent'] = 'VLC/3.0.20 (Linux; x86_64)';
    }

    if (vlcOpts['http-user-agent']) requestHeaders['User-Agent'] = vlcOpts['http-user-agent'];
    else if (userSettings.globalUserAgent && !requestHeaders['User-Agent']) requestHeaders['User-Agent'] = userSettings.globalUserAgent;

    if (vlcOpts['http-referrer']) requestHeaders['Referer'] = vlcOpts['http-referrer'];
    else if (userSettings.globalReferrer) requestHeaders['Referer'] = userSettings.globalReferrer;
    
    if (vlcOpts['http-origin']) requestHeaders['Origin'] = vlcOpts['http-origin'];

    try {
        const globalExtra = JSON.parse(userSettings.additionalGlobalHeaders || '{}');
        Object.assign(requestHeaders, globalExtra);
    } catch (e) { console.warn("Error parsing global headers", e); }
    
    Object.assign(requestHeaders, extHttpHeaders);
    
    const kodiStreamHeadersRaw = kodiProps['inputstream.adaptive.stream_headers'];
    if (kodiStreamHeadersRaw) {
        kodiStreamHeadersRaw.split('|').forEach(part => {
            const eqIndex = part.indexOf('=');
            if (eqIndex > 0) requestHeaders[part.substring(0, eqIndex).trim()] = part.substring(eqIndex + 1).trim();
        });
    }
    
    return requestHeaders;
}

async function playChannelInShaka(channel, windowId) {
    const instance = playerInstances[windowId];
    if (!instance || !instance.player) {
        if (typeof showNotification === 'function') showNotification('Instancia de reproductor no encontrada.', 'error');
        return;
    }
    if (!channel || typeof channel.url !== 'string') {
        console.warn("Canal inválido o sin URL:", channel);
        if (typeof showNotification === 'function') showNotification('Datos del canal inválidos.', 'error');
        return;
    }

    instance.channel = channel; 

    const player = instance.player;
    const videoElement = instance.videoElement;
    videoElement.poster = channel['tvg-logo'] || '';

    if (typeof showLoading === 'function') showLoading(true, `Cargando ${escapeHtml(channel.name)}...`);
    
    try {
        if (player.getMediaElement()) {
            await player.unload(true);
        }
        
        const requestHeadersForDNR = getChannelHeaders(channel);
        await applyHttpHeaders(requestHeadersForDNR, "*://*/*", chrome.runtime.id);
        
        const playerConfig = buildShakaConfig(channel, false);
        validateShakaConfig(playerConfig);
        player.configure(playerConfig);

        if (instance.errorHandler) {
            player.removeEventListener('error', instance.errorHandler);
        }
        const newErrorHandler = (e) => onShakaPlayerError(e, windowId);
        player.addEventListener('error', newErrorHandler);
        instance.errorHandler = newErrorHandler;

        const resolvedUrl = await resolveFinalUrl(channel.url, requestHeadersForDNR);
        if (!resolvedUrl) {
            throw new Error("No se pudo resolver la URL final del stream.");
        }
        channel.resolvedUrl = resolvedUrl;

        const mimeType = detectMimeType(resolvedUrl);
        await player.load(resolvedUrl, null, mimeType);
        
        if (typeof showPlayerInfobar === 'function') {
            showPlayerInfobar(channel, instance.container.querySelector('.player-infobar'));
        }
        
        if (typeof highlightCurrentChannelInList === 'function' && instance.isChannelListVisible) {
            highlightCurrentChannelInList(windowId);
        }

        if (typeof addToHistory === 'function') {
            addToHistory(channel);
        }

    } catch (e) {
        onShakaPlayerError({ detail: e, channelName: channel.name }, windowId);
    } finally {
        if (typeof showLoading === 'function') showLoading(false);
    }
}

function onShakaPlayerError(event, windowId) {
    const instance = playerInstances[windowId];
    const channelName = instance ? instance.channel.name : 'el canal';
    const error = event.detail;

    const finalMessage = formatShakaError(error, channelName);
    
    console.error("Player Error Event:", finalMessage, "Full error object:", event.detail);
    if (typeof showNotification === 'function') showNotification(finalMessage, 'error');
    if (typeof showLoading === 'function') showLoading(false);
}

async function playChannelInCardPreview(channel, videoContainerElement) {
    if (activeCardPreviewPlayer) {
        await destroyActiveCardPreviewPlayer();
    }
    if (!channel || !channel.url || !videoContainerElement) {
        return;
    }

    const videoElement = document.createElement('video');
    videoElement.className = 'card-preview-video';
    videoElement.muted = true;
    videoElement.autoplay = true;
    videoElement.playsInline = true;
    videoContainerElement.innerHTML = '';
    videoContainerElement.appendChild(videoElement);
    
    activeCardPreviewPlayer = new shaka.Player();
    try {
        await activeCardPreviewPlayer.attach(videoElement);

        const requestHeadersForDNR = getChannelHeaders(channel);
        await applyHttpHeaders(requestHeadersForDNR, "*://*/*", chrome.runtime.id);
        
        const previewConfig = buildShakaConfig(channel, true);
        validateShakaConfig(previewConfig);
        await activeCardPreviewPlayer.configure(previewConfig);

        const resolvedUrl = await resolveFinalUrl(channel.url, requestHeadersForDNR);
        if (!resolvedUrl) {
            throw new Error("No se pudo resolver la URL final del stream para la previsualización.");
        }
        
        const mimeType = detectMimeType(resolvedUrl);
        await activeCardPreviewPlayer.load(resolvedUrl, null, mimeType);

        videoElement.play().catch(e => {
            console.warn("Error al iniciar previsualización automática:", e);
             destroyActiveCardPreviewPlayer();
        });

    } catch (error) {
        console.error("Error al cargar previsualización:", error);
        if (activeCardPreviewElement) activeCardPreviewElement.removeClass('is-playing-preview');
        activeCardPreviewElement = null;
        destroyActiveCardPreviewPlayer();
    }
}

async function destroyActiveCardPreviewPlayer() {
    if (activeCardPreviewPlayer) {
        try {
            await activeCardPreviewPlayer.destroy();
        } catch (e) {
            console.warn("Error destruyendo reproductor de previsualización:", e);
        }
        activeCardPreviewPlayer = null;
    }
    if (activeCardPreviewElement) {
        activeCardPreviewElement.removeClass('is-playing-preview');
        const previewContainer = activeCardPreviewElement.find('.card-video-preview-container');
        if(previewContainer.length) previewContainer.empty();
        activeCardPreviewElement = null;
    }
     await applyHttpHeaders([], "*://*/*", null);
}