<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <title>Eventos Deportivos Movistar Plus</title>
    <style>
        /* Estilos existentes */
        body {
            text-align: center;
            background-color: #1a1a1a;
            color: #ffffff;
            transition: background-color 0.5s, color 0.5s;
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            min-height: 100vh;
        }

        iframe {
            width: 100%;
            max-width: 600px;
            height: 400px;
            border: none;
            background-color: #000;
            /* Fondo negro del iframe */
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 20px;
        }

        th,
        td {
            border: 1px solid #444;
            padding: 8px;
            text-align: left;
        }

        th {
            background-color: #333;
            font-weight: bold;
        }

        a {
            color: white;
            text-decoration: none;
        }

        /* Mantener el color original en enlaces acestream:// */
        a[href^="acestream://"] {
            color: #ff1e1e;
            /* Azul */
        }

        .table-title {
            font-size: 1.2em;
            font-weight: bold;
            margin-top: 20px;
        }

        #loading,
        #error {
            text-align: center;
            padding: 20px;
        }

        #loading {
            color: #888;
        }

        #error {
            color: red;
        }

        .button-container {
            margin-bottom: 20px;
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
        }

        button {
            padding: 5px 10px;
        }

        h1,
        h2 {
            text-align: center;
        }

        /* Nuevos estilos para el login */
        .login-container {
            max-width: 400px;
            margin: 100px auto;
            padding: 2rem;
            background-color: #2d2d2d;
            border-radius: 0.5rem;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }

        .login-title {
            color: #ffffff;
            font-size: 1.5rem;
            font-weight: bold;
            margin-bottom: 1.5rem;
            text-align: center;
        }

        .login-input {
            width: 100%;
            padding: 0.75rem;
            margin-bottom: 1rem;
            background-color: #3d3d3d;
            border: 1px solid #4a4a4a;
            border-radius: 0.375rem;
            color: #ffffff;
            outline: none;
        }

        .login-input:focus {
            border-color: #3b82f6;
        }

        .login-button {
            width: 100%;
            padding: 0.75rem;
            background-color: #3b82f6;
            color: #ffffff;
            border: none;
            border-radius: 0.375rem;
            font-weight: 500;
            cursor: pointer;
            transition: background-color 0.2s;
        }

        .login-button:hover {
            background-color: #2563eb;
        }

        .error-message {
            color: #ef4444;
            margin-top: 0.75rem;
            text-align: center;
            font-size: 0.875rem;
        }

        /* Ocultar el contenido principal inicialmente */
        #main-content {
            display: none;
        }

        /* Estilo para canales OFF */
        .channel-off {
            color: #888 !important;
            text-decoration: line-through;
            font-style: italic;
        }
    </style>
</head>

<body>
    <!-- Formulario de login -->
    <div id="login-form" class="login-container">
        <h2>Acceso Restringido</h2>
        <input type="password" id="password-input" placeholder="Introduzca la contraseña">
        <button onclick="checkPassword()">Acceder</button>
        <div id="error-message"></div>
    </div>

    <!-- Contenido principal (oculto inicialmente) -->
    <div id="main-content">
        <h1>Eventos Deportivos Movistar Plus</h1>
        <h2>ACestream 2.0</h2>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
        <div class="button-container" id="sorting-buttons"></div>
        <div id="loading">Cargando eventos...</div>
        <div id="error"></div>
        <div id="events-container"></div>
    </div>

    <script>
        // Variables globales existentes
        let globalEvents = {};
        let availableCategories = new Set();
        let validLinks = [];
        const acestreamUrls = [
            "https://api.codetabs.com/v1/proxy/?quest=http://ipfs.io/ipns/elcano.top",
            "https://ipfs.io/ipns/k51qzi5uqu5dgg9al11vomikugim0o1i3l3fxp3ym3jwaswmy9uz8pq4brg1u9",
        ];
        //             "https://s3.us.archive.org/abcd_20240416/Index.html"

        // URL para verificar la contraseña (reemplazar con tu URL real)
        // const passwordUrl = "https://ia600309.us.archive.org/8/items/abcd_20240416/password.txt";
        // URL para verificar la contraseña (reemplazar con tu URL real)
        const passwordUrl = "https://archive.org/download/abcd_20240416/password.txt";

        // Función para verificar la contraseña
        async function checkPassword() {
            const passwordInput = document.getElementById('password-input').value;
            const errorMessage = document.getElementById('error-message');
            const salt = "15uXwVjsqrufBZDJryKWzM1KgFHccXu2W3";

            try {
                // Obtener la contraseña encriptada desde la URL
                const response = await fetch(passwordUrl);

                if (!response.ok) {
                    throw new Error('No se pudo acceder al archivo de contraseña');
                }

                const encryptedPassword = await response.text();

                // Generar la clave usando el salt
                const key = CryptoJS.PBKDF2(salt, salt, {
                    keySize: 256 / 32,
                    iterations: 1000
                });

                // Intentar descifrar la contraseña almacenada usando la contraseña ingresada
                try {
                    const decrypted = CryptoJS.AES.decrypt(encryptedPassword, key.toString()).toString(CryptoJS.enc.Utf8);

                    // Comparar la contraseña descifrada con la ingresada
                    if (passwordInput.trim() === decrypted.trim()) {
                        // Contraseña correcta
                        document.getElementById('login-form').style.display = 'none';
                        document.getElementById('main-content').style.display = 'block';
                        // Iniciar carga de contenido
                        fetchSportsEvents();
                    } else {
                        errorMessage.textContent = 'Contraseña incorrecta';
                    }
                } catch (decryptError) {
                    errorMessage.textContent = 'Error al verificar la contraseña';
                    console.error('Error de descifrado:', decryptError);
                }
            } catch (error) {
                errorMessage.textContent = 'Error al verificar la contraseña. Por favor, inténtelo más tarde.';
                console.error('Error:', error);
            }
        }


        const equivalenciasCanales = {
            "La 1 (Dial 1)": ["La1", "La1 UHD"],
            "Teledeporte (Dial 75)": ["tdp 1080"],

            "M+ Copa del Rey (Dial 52)": ["Copa 1080", "Copa 720"],

            "M+ LALIGA TV 2 (Dial 57)": ["M. LaLiga 2 1080", "M. LaLiga 2 720"],

            "M+ Ellas V (Dial 66)": ["#Ellas 1080"],

            "Eurosport 1 (Dial 72)": ["EuroSport 1 1080"],
            "Eurosport 2 (Dial 73)": ["EuroSport 2 1080"],

            "M+ Deportes (Dial 63)": ["M. Deportes 1080", "M. Deportes 720"],
            "M+ Deportes 2 (Dial 64)": ["M. Deportes 2 1080", "M. Deportes 2 720"],
            "M+ Deportes 3 (Dial 65)": ["M. Deportes 3 1080", "M. Deportes 3 720"],
            "M+ Deportes 4 (Dial 191)": ["M. Deportes 4 1080", "M. Deportes 4 720"],
            "M+ Deportes 5 (Dial 192)": ["M. Deportes 5 1080", "M. Deportes 5 720"],
            "M+ Deportes 6 (Dial 193)": ["M. Deportes 6 1080", "M. Deportes 6 720"],
            "M+ Deportes 7 (Dial 194)": ["M. Deportes 7 1080", "M. Deportes 7 720"],

            "M+ Liga de Campeones (Dial 60)": ["M.L. Campeones 1080", "M.L. Campeones 720", "M.L. Campeones 1080 MultiAudio"],
            "M+ Liga de Campeones 2 (Dial 61)": ["M.L. Campeones 2 SD", "M.L. Campeones 2 1080", "M.L. Campeones 2 720"],
            "M+ Liga de Campeones 3 (Dial 62)": ["M.L. Campeones 3 1080"],
            "M+ Liga de Campeones 4 (Dial 180)": ["M.L. Campeones 4 SD", "M.L. Campeones 4 1080", "M.L. Campeones 4 720"],
            "M+ Liga de Campeones 5 (Dial 181)": ["M.L. Campeones 5 SD", "M.L. Campeones 5 1080", "M.L. Campeones 5 720"],
            "M+ Liga de Campeones 6 (Dial 182)": ["M.L. Campeones 6 SD", "M.L. Campeones 6 1080", "M.L. Campeones 6 720"],
            "M+ Liga de Campeones 7 (Dial 183)": ["M.L. Campeones 7 SD", "M.L. Campeones 7 1080", "M.L. Campeones 7 720"],
            "M+ Liga de Campeones 8 (Dial 184)": ["M.L. Campeones 8 SD", "M.L. Campeones 8 1080", "M.L. Campeones 8 720"],
            "M+ Liga de Campeones 9 (Dial 185)": ["M.L. Campeones 9 SD", "M.L. Campeones 9 1080", "M.L. Campeones 9 720"],
            "M+ Liga de Campeones 10 (Dial 186)": ["M.L. Campeones 10 SD", "M.L. Campeones 10 1080", "M.L. Campeones 10 720"],
            "M+ Liga de Campeones 11 (Dial 187)": ["M.L. Campeones 11 SD", "M.L. Campeones 11 1080", "M.L. Campeones 11 720"],
            "M+ Liga de Campeones 12 (Dial 188)": ["M.L. Campeones 12 SD", "M.L. Campeones 12 1080", "M.L. Campeones 12 720"],
            "M+ Liga de Campeones 13 (Dial 189)": ["M.L. Campeones 13 SD", "M.L. Campeones 13 1080", "M.L. Campeones 13 720"],
            "M+ Liga de Campeones 14 (Dial 169)": ["M.L. Campeones 5 SD", "M.L. Campeones 5 1080", "M.L. Campeones 5 720"],
            "M+ Liga de Campeones 15 (Dial 170)": ["M.L. Campeones 5 SD", "M.L. Campeones 5 1080", "M.L. Campeones 5 720"],
            "M+ Liga de Campeones 16 (Dial 171)": ["M.L. Campeones 5 SD", "M.L. Campeones 5 1080", "M.L. Campeones 5 720"],
            "M+ Liga de Campeones 17 (Dial 172)": ["M.L. Campeones 5 SD", "M.L. Campeones 5 1080", "M.L. Campeones 5 720"],
            "M+ Liga de Campeones 18 (Dial 173)": ["M.L. Campeones 5 SD", "M.L. Campeones 5 1080", "M.L. Campeones 5 720"],
            "M+ Liga de Campeones 19 (Dial 174)": ["M.L. Campeones 5 SD", "M.L. Campeones 5 1080", "M.L. Campeones 5 720"],

            "M+ Golf (Dial 67)": ["M. Golf 1080", "M. Golf 720"],
            "M+ Golf 2 (Dial 68)": ["M. Golf2 1080", "M. Golf2 720"],


            // Canales OFF
            "GOL PLAY (Dial 74)": ["OFF"],
            "Real Madrid TV (Dial 76)": ["OFF"],

            "TV5MONDE (Dial 137)": ["OFF"],
            "TV3 Cat (Dial 154)": ["OFF"],
            "Aragón TV Int (Dial 156)": ["OFF"],
            "Esport 3 (Dial 164)": ["OFF"],
            "LALIGA TV BAR (Dial 300)": ["OFF"],
            "LALIGA TV BAR 2 (Dial 301)": ["OFF"],
            "LALIGA TV BAR 3 (Dial 302)": ["OFF"],
            "M+ Vamos BAR (Dial 304)": ["OFF"],
            "DAZN 1 BAR (Dial 310)": ["OFF"],
            "DAZN 2 BAR (Dial 311)": ["OFF"],

        };

        //         Nombre	Content ID	Acción

        // EuroSport 1 1080	16ffa1713f42aa27317ee039a2bd0cdbc89a1580	Iniciar
        // EuroSport 2 1080	98784fa0714190de289f42eb5b84e405df7e685a	Iniciar
        // M. LaLiga 1080P	94d34491106e00394835c8cb68aa94481339b53f	Iniciar
        // M. LaLiga 1080 MultiAudio	d3de78aebe544611a2347f54d5796bd87f16c92d	Iniciar
        // M. LaLiga 1080 MultiAudio	6d05b31e5e8fdae312fbd57897363a7b10ddb163	Iniciar
        // M. LaLiga 720	1bc437bce57b4b0450f6d1f8d818b7e97000745e	Iniciar

        // M. LaLiga 3 1080	ebe14f1edeb49f2253e3b355a8beeadc9b4f0bc4	Iniciar
        // M. LaLiga 3 720	835639b89db00cc0d94660da3c10b6e38bfbcdc1	Iniciar
        // M. LaLiga 4 1080	68697ea4f261289d97bbc3418ad3cbc4180aa32f	Iniciar
        // La Liga BAR 1080	608b0faf7d3d25f6fe5dba13d5e4b4142949990e	Iniciar
        // DAZN LaLiga 1080 MultiAudio	110d441ddc9713a7452588770d2bc85504672f47	Iniciar
        // DAZN LaLiga 1080 MultiAudio	ec29289b0b14756e686c03a501bae1efa05be70c	Iniciar
        // DAZN LaLiga 1080 MultiAudio	6de4794cd02f88f14354b5996823413a59a1de0f	Iniciar
        // DAZN LaLiga 720	8c8c1e047a1c5ed213ba74722a5345dc55c3c0eb	Iniciar
        // DAZN LaLiga 2 1080 MultiAudio	97ba38d47680954be40e48bd8f43e17222fefecb	Iniciar
        // DAZN LaLiga 2 720 MultiAudio	51dbbfb42f8091e4ea7a2186b566a40e780953d9	Iniciar
        // LaLiga Smartbank 1080	b2706a7ffbea236a3b398139a3a606ada664c0eb	Iniciar
        // LaLiga Smartbank 720	121f719ebb94193c6086ef92865cf9b197750980	Iniciar
        // LaLiga Smartbank 2 1080	0cfdfde1b70623b8c210b0f7301be2a87456481d	Iniciar
        // LaLiga Smartbank 2 720	0a335406bad0b658aeddb2d38f8c0614b2e5623a	Iniciar
        // LaLiga Smartbank 3	fefd45ed6ff415e05f1341b7d9da2988eacd13ea	Iniciar
        // M.Plus 1080	56ac8e227d526e722624675ccdd91b0cc850582f	Iniciar

        // #Vamos 1080	d03c13b6723f66155d7a0df3692a3b073fe630f2	Iniciar
        // #Vamos 720	12ba546d229bc39f01c3c18988a034b215fe6adb	Iniciar

        // DAZN 1 1080	7cf0086fa7d478f51dbba952865c79e66cb9add5	Iniciar
        // DAZN 1 720	35c7f0c966ecde3390f4510bb4caded40018c07a	Iniciar
        // DAZN 2 1080	ca923c9873fd206a41c1e83ff8fc40e3cf323c9a	Iniciar
        // DAZN 2 720	a929eeec1268d69d1556a2e3ace793b2577d8810	Iniciar
        // DAZN 3 1080	19cd05c7ae26f22737ae5728b571ca36abd8a2e8	Iniciar
        // DAZN 4 1080	4e83f23945ab3e43982045f88ec31daaa4683102	Iniciar
        // DAZN F1 1080 (Fórmula 1)	d6281d4e6310269b416180442a470d23a4a99dc9	Iniciar
        // DAZN F1 1080 (Fórmula 1)	2c6e4c897661e6b0257bfe931b66d20b2ec763b6	Iniciar
        // DAZN F1 1080 (Fórmula 1)	71eef80158aa8b37f3dc59f6793c6696df9a2dfa	Iniciar
        // DAZN F1 720 (Fórmula 1)	268289e7a3c5209960b53b4d43c8c65fab294b85	Iniciar
        // Telecinco 1080	66a7e4727bccce8ccc04e54861b06b62d89452fa	Iniciar
        // Telecinco 1080	47e6dd48dd7c9705d07b13139b80e44683fd5eb1	Iniciar
        // PPVP 1	6994af284ecab2996f9b140ef44b8da8bfee0006	Iniciar
        // PPVP 2	7cf437be950f3525e735be57c63f7824cab822c9	Iniciar
        // PPVP 3	ad6f4e8e329d6a97c7e7d7b0b8e5d04d8dd0bb48	Iniciar
        // NBA TV	e72d03fb9694164317260f684470be9ab781ed95	Iniciar

        async function fetchAceStreamLinks() {
            const fetchPromises = acestreamUrls.map(async (url) => {
                try {
                    const response = await fetch(url);
                    const htmlText = await response.text();

                    // Extract links from the HTML using the linksData object
                    const parser = new DOMParser();
                    const doc = parser.parseFromString(htmlText, 'text/html');

                    // If the page contains linksData directly in the script
                    const scriptTags = doc.getElementsByTagName('script');
                    for (let script of scriptTags) {
                        const match = script.textContent.match(/const\s+linksData\s*=\s*(\{.*?\});/s);
                        if (match) {
                            try {
                                const parsedData = JSON.parse(match[1]);
                                return parsedData.links.filter(link =>
                                    link.url &&
                                    link.url.includes('acestream://') &&
                                    link.url.replace('acestream://', '').trim() !== ''
                                );
                            } catch (parseError) {
                                console.error('Error parsing links:', parseError);
                            }
                        }
                    }

                    return [];
                } catch (error) {
                    console.error(`Error fetching from ${url}:`, error);
                    return [];
                }
            });

            const allLinks = (await Promise.all(fetchPromises)).flat();
            validLinks = Array.from(new Set(allLinks.map(JSON.stringify))).map(JSON.parse);
        }

        function getAceStreamLink(channelName) {
            // Primero buscar si el canal está en las equivalencias
            for (const [mainChannel, aliases] of Object.entries(equivalenciasCanales)) {
                if (mainChannel === channelName) {
                    // Buscar el primer enlace válido para cualquiera de los alias
                    for (const alias of aliases) {
                        const normalizedAlias = alias.toLowerCase().trim();
                        const matchingLink = validLinks.find(link =>
                            link.name.toLowerCase().trim() === normalizedAlias
                        );
                        if (matchingLink) {
                            return {
                                displayName: mainChannel,
                                streamLink: matchingLink.url
                            };
                        }
                    }

                }
            }

            // Si no se encontró en equivalencias, buscar en validLinks directamente
            const directMatch = validLinks.find(link =>
                link.name.toLowerCase().trim() === channelName.toLowerCase().trim()
            );

            return directMatch
                ? { displayName: directMatch.name, streamLink: directMatch.url }
                : { displayName: channelName, streamLink: null };
        }

        // Diccionario de iconos en base64 (SVG)
        const CATEGORY_ICONS = {
            'Deportes': 'data:file/octet-stream;base64,UklGRkoCAABXRUJQVlA4WAoAAAAQAAAAHwAAHwAAQUxQSMIAAAABgLtt2/HlzrZte/v92u3aO9rs2uzJ3Gz3P9iTbWOzn/QprhExAfiH2kbnRYuUeVOLGrojItoqseXFMGODmC+L5Tmp5J0S+wkrDuFLxHnHno3+APG5rs3gGT9J/PZCQgJwansh3r0Ao/IbErBRJv2UBB1UOSNh61ApzJYVvAQ5MgVkpoXoAIBIIcQfFNb5S8WniWxGx/YeGF5mI/C50hxTFqBiIw6MTE+LDXKVALPvJzf1IvDeRXRR6wABPWYKjfBXB1ZQOCBiAQAAcAcAnQEqIAAgAD6RQpxKJaOioagIALASCWwAtvdengbJ45XUJuAAPoDk5VLjP23RrOZ0MLDjmAtAYw/LrxeizHf5AAAA/vsIaBgeOkUIOgZF7gvj3YG/vgNBLSvoVtZGNm//LgB2lOwV3FrmdSx0c2cvnt7sv/9f64sS7Qch1PeaKDx5SaMf3E/VlCqbe1Pv+GWu5hy0wQD3om9O+X55BLS7KstRCooFJdZpBGgNByHveZXVApo25/mvOj9rb65QcZ6PS2rghNhgh2xFGrzOfEijqF/apUVHgKNh+Z0u90x59oXXgdw5b1TSDRerumXUrVA9ue7OM9ojeX0Q0MCfsFEuwbSS/sZrbHJVheas/+Rc9mJRgAi+6gibr38/Hx3RVx8WC+uqbQRX+FvyS61Uix6f66jC4iIp/Kz6F/20lJiiTX+OZgS10jiz/f9MhkBPCmBhppJg7csrQVRPnx8CAAAA',
            'Motor': 'https://static.futbolenlatv.com/img/32/20130624110336-automovilismo.webp',
            'Boxeo': 'https://static.futbolenlatv.com/img/32/20130624110538-boxeo.webp',
            'Balonmano': 'https://static.futbolenlatv.com/img/32/20130724090914-balonmano.webp',
            'Pádel': 'https://static.futbolenlatv.com/img/32/20141020014848-padel.webp',
            'Rugby': 'https://static.futbolenlatv.com/img/32/20200729125932-rugby.webp',
            'Tenis': 'https://static.futbolenlatv.com/img/32/20130618113307-tenis.webp',
            'Futbol (F)': 'https://static.futbolenlatv.com/img/32/20130618113222-futbol.webp',
            'Fútbol sala': 'https://static.futbolenlatv.com/img/32/20130627015342-futbol-sala.webp',
            'Futbol': 'https://static.futbolenlatv.com/img/32/20130618113222-futbol.webp',
            'Baloncesto (F)': 'https://static.futbolenlatv.com/img/32/20130618113234-baloncesto.webp',
            'Baloncesto': 'https://static.futbolenlatv.com/img/32/20130618113234-baloncesto.webp',
            'Fórmula 1': 'https://static.futbolenlatv.com/img/32/20130624110336-automovilismo.webp',
            'Golf': 'https://static.futbolenlatv.com/img/32/20130724083030-bola-golf.webp',
            'MotoGP': 'https://static.futbolenlatv.com/img/32/20130629041459-motociclismo.webp',
            'Motociclismo': 'https://static.futbolenlatv.com/img/32/20130629041459-motociclismo.webp',
            'Ciclismo': 'https://img.icons8.com/?size=40&id=52373&format=png',
            'Esquí alpino': 'https://img.icons8.com/?size=64&id=PGfxqJyQkXX9&format=png',
            'Esquí de fondo': 'https://img.icons8.com/?size=64&id=PGfxqJyQkXX9&format=png',
            'Saltos de esquí': 'https://img.icons8.com/?size=64&id=PGfxqJyQkXX9&format=png',
            'Fútbol americano': 'https://static.futbolenlatv.com/img/32/20200804171715-futbol-americano.webp',
            'Fútbol español': 'https://static.futbolenlatv.com/img/32/20130618113222-futbol.webp',
            'Fútbol internacional': 'https://static.futbolenlatv.com/img/32/20130618113222-futbol.webp',
            'Hockey patines': 'https://static.futbolenlatv.com/img/32/20130627053939-hockey.webp',
            'Hípica': 'https://img.icons8.com/?size=48&id=qO9YrwqJ1Q8E&format=png',
            'Deportes de Invierno': 'https://img.icons8.com/?size=48&id=ZlF53OGmXYz0&format=png',
            'Snooker': 'https://img.icons8.com/?size=80&id=yPe4ubFtlXAJ&format=png',
            'Snowboard': 'https://img.icons8.com/?size=80&id=IJxvBf04TJNs&format=png',
            'Patinaje artístico': 'https://img.icons8.com/?size=48&id=dyzqB3gQxHZB&format=png',
            'Hockey hierba': 'https://img.icons8.com/?size=48&id=xiJoMljLsOXb&format=png',
            'Waterpolo': 'https://img.icons8.com/?size=80&id=kXpbglkjezxc&format=png',
            'Vela': 'https://img.icons8.com/?size=40&id=24145&format=png',
            // 
            // Mantener el default en base64 ya que es el icono de respaldo
            'default': 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTEyIDJDNi40OCAyIDIgNi40OCAyIDEyczQuNDggMTAgMTAgMTAgMTAtNC40OCAxMC0xMFMxNy41MiAyIDEyIDJ6bTEgMTVoLTJ2LTZoMnY2em0wLThoLTJWN2gydjJ6Ii8+PC9zdmc+'
        };

        function getCurrentSystemDate() {
            const days = ['lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo'];
            const months = ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'];

            const today = new Date();
            const dayName = days[today.getDay()];
            const monthName = months[today.getMonth()];

            return `${dayName} ${today.getDate()} de ${monthName} de ${today.getFullYear()}`;
        }

        // Primero, añadimos una variable global para almacenar el orden original de las fechas
        let originalDateOrder = [];

        function parseEvents(htmlContent) {
            const parser = new DOMParser();
            const doc = parser.parseFromString(htmlContent, 'text/html');
            const eventsByDate = {};
            originalDateOrder = []; // Reiniciamos el array

            console.log('Starting to parse HTML content');

            const dateSections = doc.querySelectorAll('.fecha-bar');
            console.log(`Found ${dateSections.length} date sections`);

            dateSections.forEach((dateSection, dateIndex) => {
                const currentDate = dateSection.textContent.trim();
                console.log(`\nProcessing date section ${dateIndex + 1}:`, currentDate);

                // Guardamos el orden original de las fechas
                originalDateOrder.push(currentDate);
                eventsByDate[currentDate] = [];

                const parentSection = dateSection.closest('.brick.info-bares');
                const categorySections = parentSection.querySelectorAll('.content-bares > li');
                console.log(`Found ${categorySections.length} category sections for ${currentDate}`);

                categorySections.forEach((section, categoryIndex) => {
                    if (section.querySelector('.fecha-bar')) {
                        console.log('Skipping nested date section');
                        return;
                    }

                    const categoryElement = section.querySelector('.box-medium');
                    const category = categoryElement?.textContent?.trim() || 'Categoría Desconocida';
                    console.log(`\nProcessing category ${categoryIndex + 1}:`, category);

                    availableCategories.add(category);

                    const eventListItems = section.querySelectorAll('li');
                    console.log(`Found ${eventListItems.length} events in category ${category}`);

                    eventListItems.forEach((eventItem, eventIndex) => {
                        const eventLink = eventItem.querySelector('a');
                        const timeBar = eventItem.querySelector('.time-bar');

                        if (eventLink && timeBar) {
                            const canal = timeBar.childNodes[0].textContent.trim();
                            const evento = eventLink.textContent.trim();
                            const hora = timeBar.querySelector('span')?.textContent?.trim() || 'Hora no especificada';

                            console.log(`\nEvent ${eventIndex + 1}:`);
                            console.log('- Evento:', evento);
                            console.log('- Canal:', canal);
                            console.log('- Canal length:', canal.length);
                            console.log('- Canal hex:', [...canal].map(c => c.charCodeAt(0).toString(16).padStart(2, '0')).join(' '));
                            console.log('- Hora:', hora);

                            // Verificar si el canal está en las equivalencias
                            const canalEnEquivalencias = Object.keys(equivalenciasCanales).includes(canal);
                            console.log('- ¿Canal en equivalencias?:', canalEnEquivalencias);

                            if (canalEnEquivalencias) {
                                console.log('- Alias disponibles:', equivalenciasCanales[canal]);
                                const tieneEnlaces = equivalenciasCanales[canal].some(alias => {
                                    return validLinks.some(link =>
                                        link.name.toLowerCase().trim() === alias.toLowerCase().trim()
                                    );
                                });
                                console.log('- ¿Tiene enlaces acestream?:', tieneEnlaces);
                            }

                            eventsByDate[currentDate].push({
                                fecha: currentDate,
                                categoria: category,
                                evento: evento,
                                canal: canal,
                                hora: hora
                            });

                            console.log('Event successfully added to eventsByDate');
                        } else {
                            if (!eventLink) console.log('Warning: No event link found');
                            if (!timeBar) console.log('Warning: No time bar found');
                        }
                    });
                });
            });

            console.log('\nFinal parsing results:');
            console.log('- Total dates:', originalDateOrder.length);
            console.log('- Total categories:', availableCategories.size);
            console.log('- Events by date:', Object.entries(eventsByDate).map(([date, events]) =>
                `${date}: ${events.length} events`
            ).join(', '));

            return eventsByDate;
        }

        function getCategoryIcon(category) {
            return CATEGORY_ICONS[category] || CATEGORY_ICONS['default'];
        }

        function createSortingButtons(categories) {
            const buttonContainer = document.getElementById('sorting-buttons');
            buttonContainer.innerHTML = '';

            // Crear contenedor para botones principales
            const mainButtonsContainer = document.createElement('div');
            mainButtonsContainer.style.marginBottom = '10px';
            buttonContainer.appendChild(mainButtonsContainer);

            // Botones principales
            const mainButtons = [
                { text: 'Original', onClick: () => renderEventsByDate() },
                { text: 'Hora', onClick: () => renderEventsByTime() },
                { text: 'Evento', onClick: () => renderEventsByEvent() },
                { text: 'Canal', onClick: () => renderEventsByChannel() }
            ];

            mainButtons.forEach(({ text, onClick }) => {
                const button = document.createElement('button');
                button.textContent = text;
                button.onclick = onClick;
                mainButtonsContainer.appendChild(button);
            });

            // Crear contenedor para botones de categorías
            const categoryButtonsContainer = document.createElement('div');
            buttonContainer.appendChild(categoryButtonsContainer);

            // Botones de categorías
            categories.forEach(category => {
                const categoryButton = document.createElement('button');
                categoryButton.textContent = category;
                categoryButton.onclick = () => renderEventsBySpecificCategory(category);
                categoryButtonsContainer.appendChild(categoryButton);
            });
        }

        // Modificamos las funciones de renderizado para usar originalDateOrder
        // Ejemplo con renderEventsByTime:
        function renderEventsByTime() {
            const container = document.getElementById('events-container');
            container.innerHTML = '';

            // Usamos originalDateOrder en lugar de Object.keys(globalEvents).sort()
            originalDateOrder.forEach(date => {
                if (!globalEvents[date] || globalEvents[date].length === 0) return;

                const dateTitle = document.createElement('div');
                dateTitle.className = 'table-title';
                dateTitle.textContent = date;
                container.appendChild(dateTitle);

                const table = document.createElement('table');
                const thead = document.createElement('thead');
                thead.innerHTML = `
                <tr>
                        <th>Hora</th>
                        <th>Categoría</th>
                        <th>Evento</th>
                        <th>Canal</th>
                    </tr>
                `;
                table.appendChild(thead);

                const tbody = document.createElement('tbody');
                const sortedEvents = [...globalEvents[date]].sort((a, b) => {
                    const parseTime = (timeStr) => {
                        // Maneja casos donde timeStr es undefined o null
                        if (!timeStr) return 0;

                        // Normaliza el formato de la hora
                        let formattedTime = timeStr
                            .toLowerCase()
                            .replace('h', ':')
                            .replace('.', ':')
                            .trim();

                        // Si solo hay horas sin minutos, añade ":00"
                        if (!formattedTime.includes(':')) {
                            formattedTime += ':00';
                        }

                        // Extrae horas y minutos, con valor por defecto 0
                        const [hours = 0, minutes = 0] = formattedTime.split(':').map(num => {
                            const parsed = parseInt(num, 10);
                            return isNaN(parsed) ? 0 : parsed;
                        });

                        return hours * 60 + minutes;
                    };

                    return parseTime(a.hora) - parseTime(b.hora);
                });

                sortedEvents.forEach(event => {
                    const row = document.createElement('tr');
                    const iconUrl = getCategoryIcon(event.categoria);
                    row.innerHTML = `
                        <td>${event.hora}</td>
                        <td>
                            <div style="display: flex; align-items: center;">
                                <img src="${iconUrl}" alt="${event.categoria}" style="width: 24px; height: 24px; margin-right: 8px;">
                                ${event.categoria}
                            </div>
                        </td>
                        <td>${event.evento}</td>
                        <td>${getChannelDisplayWithLinks(event.canal)}</td>
                    `;
                    tbody.appendChild(row);
                });

                table.appendChild(tbody);
                container.appendChild(table);
            });
        }

        // De manera similar, debes modificar las otras funciones de renderizado 
        // (renderEventsByEvent, renderEventsByChannel, etc.) 
        // para usar originalDateOrder en lugar de Object.keys(globalEvents).sort()


        function getChannelDisplayWithLinks(channelName) {
            // Verificar si es un canal OFF
            const isOffChannel = Object.entries(equivalenciasCanales).some(
                ([mainChannel, aliases]) =>
                    mainChannel === channelName &&
                    aliases.length === 1 &&
                    aliases[0] === "OFF"
            );

            if (isOffChannel) {
                return `<span class="channel-off">${channelName} (OFF)</span>`;
            }
            // Normalizar el nombre del canal eliminando espacios múltiples
            const normalizedChannelName = channelName.replace(/\s+/g, ' ').trim();

            // Añadir al debug info
            const debugInfo = document.getElementById('debug-info');
            if (debugInfo) {
                debugInfo.textContent += `\nProcessing channel: "${channelName}"\n`;
                debugInfo.textContent += `Normalized channel: "${normalizedChannelName}"\n`;
                debugInfo.textContent += `Channel name length: ${channelName.length}\n`;
                debugInfo.textContent += `Channel name hex: ${[...channelName].map(c => c.charCodeAt(0).toString(16).padStart(2, '0')).join(' ')}\n`;
            }

            // Buscar en las equivalencias usando el nombre normalizado
            for (const [mainChannel, aliases] of Object.entries(equivalenciasCanales)) {
                const normalizedMainChannel = mainChannel.replace(/\s+/g, ' ').trim();
                if (normalizedMainChannel === normalizedChannelName) {
                    if (debugInfo) {
                        debugInfo.textContent += `Match found in equivalencias: "${mainChannel}"\n`;
                        debugInfo.textContent += `Aliases: ${JSON.stringify(aliases)}\n`;
                    }

                    const validStreamLinks = aliases.map(alias => {
                        const normalizedAlias = alias.toLowerCase().trim();
                        const matchingLink = validLinks.find(link =>
                            link.name.toLowerCase().trim() === normalizedAlias
                        );

                        if (matchingLink) {
                            return `<a href="${matchingLink.url}" target="_blank">${alias}</a>`;
                        }
                        return null;
                    }).filter(link => link !== null);

                    if (validStreamLinks.length > 0) {
                        return validStreamLinks.join(' | ');
                    }
                }
            }

            // Búsqueda directa con nombre normalizado
            const directMatch = validLinks.find(link =>
                link.name.toLowerCase().trim() === normalizedChannelName.toLowerCase().trim()
            );

            if (debugInfo) {
                debugInfo.textContent += `Direct match result: ${directMatch ? directMatch.url : 'not found'}\n`;
            }

            return directMatch ?
                `<a href="${directMatch.url}" target="_blank">${directMatch.name}</a>` :
                channelName;
        }

        // Modificar la función fetchSportsEvents para que solo se ejecute después de la autenticación
        async function fetchSportsEvents() {
            const debug = createDebugIframe();
            const proxyUrl = 'https://api.codetabs.com/v1/proxy/?quest=';
            const targetUrl = 'https://www.movistarplus.es/deportesendirectobar';

            try {
                debug.debugInfo.textContent += 'Fetching AceStream Links...\n';
                await fetchAceStreamLinks();
                debug.debugInfo.textContent += `Fetched ${validLinks.length} valid links\n`;

                debug.updateChannelsInfo();

                debug.debugInfo.textContent += '\nFetching Sports Events...\n';
                const response = await fetch(proxyUrl + targetUrl);
                const htmlContent = await response.text();

                globalEvents = parseEvents(htmlContent);
                debug.debugInfo.textContent += `Parsed ${Object.values(globalEvents).flat().length} events\n`;

                createSortingButtons(Array.from(availableCategories));
                renderEventsByDate();

                document.getElementById('loading').style.display = 'none';
            } catch (error) {
                const errorDiv = document.getElementById('error');
                errorDiv.textContent = `Error: ${error.message}`;
                debug.debugInfo.textContent += `Full Error: ${error.stack}\n`;
                document.getElementById('loading').style.display = 'none';
            }
        }

        // Modificar todas las funciones de renderizado para usar getChannelDisplayWithLinks

        function renderEventsByDate() {
            const container = document.getElementById('events-container');
            container.innerHTML = '';

            originalDateOrder.forEach(date => {
                const events = globalEvents[date];
                if (!events || events.length === 0) return;

                const dateTitle = document.createElement('div');
                dateTitle.className = 'table-title';
                dateTitle.textContent = date;
                container.appendChild(dateTitle);

                const table = document.createElement('table');
                const thead = document.createElement('thead');
                thead.innerHTML = `
                    <tr>
                        <th>Hora</th>
                        <th>Categoría</th>
                        <th>Evento</th>
                        <th>Canal</th>
                    </tr>
                `;
                table.appendChild(thead);

                const tbody = document.createElement('tbody');
                events.forEach(event => {
                    const row = document.createElement('tr');
                    const iconUrl = getCategoryIcon(event.categoria);
                    row.innerHTML = `
                        <td>${event.hora}</td>
                        <td>
                            <div style="display: flex; align-items: center;">
                                <img src="${iconUrl}" alt="${event.categoria}" style="width: 24px; height: 24px; margin-right: 8px;">
                                ${event.categoria}
                            </div>
                        </td>
                        <td>${event.evento}</td>
                        <td>${getChannelDisplayWithLinks(event.canal)}</td>
                    `;
                    tbody.appendChild(row);
                });

                table.appendChild(tbody);
                container.appendChild(table);
            });
        }

        function renderEventsByGeneralCategory() {
            const container = document.getElementById('events-container');
            container.innerHTML = '';

            // Use originalDateOrder instead of sorting
            originalDateOrder.forEach(date => {
                const eventsOnDate = globalEvents[date];
                if (!eventsOnDate || eventsOnDate.length === 0) return;

                const dateTitle = document.createElement('div');
                dateTitle.className = 'table-title';
                dateTitle.textContent = date;
                container.appendChild(dateTitle);

                const table = document.createElement('table');
                const thead = document.createElement('thead');
                thead.innerHTML = `
                    <tr>
                        <th>Hora</th>
                        <th>Categoría</th>
                        <th>Evento</th>
                        <th>Canal</th>
                    </tr>
                `;
                table.appendChild(thead);

                const tbody = document.createElement('tbody');
                const sortedEvents = [...eventsOnDate].sort((a, b) => a.categoria.localeCompare(b.categoria));

                sortedEvents.forEach(event => {
                    const row = document.createElement('tr');
                    const iconUrl = getCategoryIcon(event.categoria);
                    row.innerHTML = `
                        <td>${event.hora}</td>
                        <td>
                            <div style="display: flex; align-items: center;">
                                <img src="${iconUrl}" alt="${event.categoria}" style="width: 24px; height: 24px; margin-right: 8px;">
                                ${event.categoria}
                            </div>
                        </td>
                        <td>${event.evento}</td>
                        <td>${getChannelDisplayWithLinks(event.canal)}</td>
                    `;
                    tbody.appendChild(row);
                });

                table.appendChild(tbody);
                container.appendChild(table);
            });
        }

        function renderEventsByEvent() {
            const container = document.getElementById('events-container');
            container.innerHTML = '';

            originalDateOrder.forEach(date => {
                const eventsOnDate = globalEvents[date];
                if (!eventsOnDate || eventsOnDate.length === 0) return;

                const dateTitle = document.createElement('div');
                dateTitle.className = 'table-title';
                dateTitle.textContent = date;
                container.appendChild(dateTitle);

                const table = document.createElement('table');
                const thead = document.createElement('thead');
                thead.innerHTML = `
                    <tr>
                        <th>Hora</th>
                        <th>Evento</th>
                        <th>Categoría</th>
                        <th>Canal</th>
                </tr>
                `;
                table.appendChild(thead);

                const tbody = document.createElement('tbody');
                const sortedEvents = [...Object.values(globalEvents).flat()]
                    .filter(event => event.fecha === date)
                    .sort((a, b) => a.evento.localeCompare(b.evento));

                sortedEvents.forEach(event => {
                    const row = document.createElement('tr');
                    const iconUrl = getCategoryIcon(event.categoria);
                    row.innerHTML = `
                        <td>${event.hora}</td>
                        <td>${event.evento}</td>
                        <td>
                            <div style="display: flex; align-items: center;">
                                <img src="${iconUrl}" alt="${event.categoria}" style="width: 24px; height: 24px; margin-right: 8px;">
                                ${event.categoria}
                            </div>
                        </td>
                        <td>${getChannelDisplayWithLinks(event.canal)}</td>
                    `;
                    tbody.appendChild(row);
                });

                table.appendChild(tbody);
                container.appendChild(table);
            });
        }

        function renderEventsByChannel() {
            const container = document.getElementById('events-container');
            container.innerHTML = '';

            originalDateOrder.forEach(date => {
                const eventsOnDate = globalEvents[date];
                if (!eventsOnDate || eventsOnDate.length === 0) return;

                const dateTitle = document.createElement('div');
                dateTitle.className = 'table-title';
                dateTitle.textContent = date;
                container.appendChild(dateTitle);

                const table = document.createElement('table');
                const thead = document.createElement('thead');
                thead.innerHTML = `
                    <tr>
                        <th>Hora</th>
                        <th>Canal</th>
                        <th>Evento</th>
                        <th>Categoría</th>
                    </tr>
                `;
                table.appendChild(thead);

                const tbody = document.createElement('tbody');
                const sortedEvents = [...eventsOnDate].sort((a, b) => a.canal.localeCompare(b.canal));

                sortedEvents.forEach(event => {
                    const row = document.createElement('tr');
                    const iconUrl = getCategoryIcon(event.categoria);
                    row.innerHTML = `
                        <td>${event.hora}</td>
                        <td>${getChannelDisplayWithLinks(event.canal)}</td>
                        <td>${event.evento}</td>
                        <td>
                            <div style="display: flex; align-items: center;">
                                <img src="${iconUrl}" alt="${event.categoria}" style="width: 24px; height: 24px; margin-right: 8px;">
                                ${event.categoria}
                            </div>
                        </td>
                    `;
                    tbody.appendChild(row);
                });

                table.appendChild(tbody);
                container.appendChild(table);
            });
        }

        function renderEventsBySpecificCategory(targetCategory) {
            const container = document.getElementById('events-container');
            container.innerHTML = '';

            originalDateOrder.forEach(date => {
                const eventsForCategory = globalEvents[date].filter(event => event.categoria === targetCategory);
                if (eventsForCategory.length === 0) return;

                const dateTitle = document.createElement('div');
                dateTitle.className = 'table-title';
                dateTitle.textContent = date;
                container.appendChild(dateTitle);

                const table = document.createElement('table');
                const thead = document.createElement('thead');
                thead.innerHTML = `
                    <tr>
                        <th>Hora</th>
                        <th>Evento</th>
                        <th>Canal</th>
                    </tr>
                `;
                table.appendChild(thead);

                const tbody = document.createElement('tbody');
                const sortedEvents = [...eventsForCategory].sort((a, b) => a.hora.localeCompare(b.hora));

                sortedEvents.forEach(event => {
                    const row = document.createElement('tr');
                    row.innerHTML = `
                        <td>${event.hora}</td>
                        <td>${event.evento}</td>
                        <td>${getChannelDisplayWithLinks(event.canal)}</td>
                    `;
                    tbody.appendChild(row);
                });

                table.appendChild(tbody);
                container.appendChild(table);
            });
        }

        // Debug container y getChannelDisplayWithLinks 
        function createDebugIframe() {
            const debugContainer = document.createElement('div');
            debugContainer.id = 'debug-container';
            debugContainer.style.marginTop = '20px';
            debugContainer.style.border = '2px solid red';
            debugContainer.style.padding = '10px';
            debugContainer.style.display = 'none'; // Oculto por defecto

            // Añadir botón de toggle
            const toggleButton = document.createElement('button');
            toggleButton.textContent = 'Toggle Debug Info';
            toggleButton.onclick = toggleDebugInfo;
            document.body.appendChild(toggleButton);

            // Título principal
            const debugTitle = document.createElement('h3');
            debugTitle.textContent = 'Debug Information';
            debugContainer.appendChild(debugTitle);

            // Sección de información general
            const debugInfo = document.createElement('pre');
            debugInfo.id = 'debug-info';
            debugInfo.style.whiteSpace = 'pre-wrap';
            debugInfo.style.wordWrap = 'break-word';
            debugContainer.appendChild(debugInfo);

            // Sección de canales
            const channelsTitle = document.createElement('h4');
            channelsTitle.textContent = 'Canales Disponibles';
            debugContainer.appendChild(channelsTitle);

            const channelsInfo = document.createElement('pre');
            channelsInfo.id = 'channels-info';
            channelsInfo.style.whiteSpace = 'pre-wrap';
            channelsInfo.style.wordWrap = 'break-word';
            channelsInfo.style.maxHeight = '200px';
            channelsInfo.style.overflow = 'auto';
            channelsInfo.style.backgroundColor = '#f5f5f5';
            channelsInfo.style.padding = '10px';
            debugContainer.appendChild(channelsInfo);

            document.body.appendChild(debugContainer);

            // Definimos updateChannelsInfo como una constante
            const updateChannelsInfo = () => {
                const channelsInfo = document.getElementById('channels-info');
                if (channelsInfo) {
                    let content = 'Equivalencias de Canales:\n\n';
                    for (const [mainChannel, aliases] of Object.entries(equivalenciasCanales)) {
                        content += `${mainChannel} (length: ${mainChannel.length}, hex: ${[...mainChannel].map(c => c.charCodeAt(0).toString(16).padStart(2, '0')).join(' ')}):\n`;
                        aliases.forEach(alias => {
                            const matchingLinks = validLinks.filter(link => {
                                const normalizedAlias = alias.toLowerCase().trim();
                                const normalizedLinkName = link.name.toLowerCase().trim();
                                return normalizedLinkName === normalizedAlias;
                            });

                            content += `  - ${alias} (length: ${alias.length}, hex: ${[...alias].map(c => c.charCodeAt(0).toString(16).padStart(2, '0')).join(' ')})\n`;
                            if (matchingLinks.length > 0) {
                                matchingLinks.forEach(link => {
                                    content += `    → ${link.url} (link name: "${link.name}")\n`;
                                });
                            } else {
                                content += `    (sin enlace)\n`;
                            }
                        });
                        content += '\n';
                    }
                    channelsInfo.textContent = content;
                }
            };

            return {
                debugInfo: debugInfo,
                updateChannelsInfo: updateChannelsInfo
            };
        }

        function toggleDebugInfo() {
            const debugContainer = document.getElementById('debug-container');
            debugContainer.style.display = debugContainer.style.display === 'none' ? 'block' : 'none';
        }

        // También necesitamos actualizar fetchSportsEvents para que no use el iframe
        async function fetchSportsEvents() {
            const debug = createDebugIframe();

            const proxyUrl = 'https://api.codetabs.com/v1/proxy/?quest=';
            const targetUrl = 'https://www.movistarplus.es/deportesendirectobar';

            try {
                debug.debugInfo.textContent += 'Fetching AceStream Links...\n';
                await fetchAceStreamLinks();
                debug.debugInfo.textContent += `Fetched ${validLinks.length} valid links\n`;

                // Actualizar información de canales
                debug.updateChannelsInfo();

                debug.debugInfo.textContent += '\nFetching Sports Events...\n';
                const response = await fetch(proxyUrl + targetUrl);
                const htmlContent = await response.text();

                globalEvents = parseEvents(htmlContent);
                debug.debugInfo.textContent += `Parsed ${Object.values(globalEvents).flat().length} events\n`;
                debug.debugInfo.textContent += 'Categories Found:\n';
                Array.from(availableCategories).forEach(category => {
                    debug.debugInfo.textContent += `- ${category}\n`;
                });

                createSortingButtons(Array.from(availableCategories));
                renderEventsByDate();

                document.getElementById('loading').style.display = 'none';
            } catch (error) {
                const errorDiv = document.getElementById('error');
                errorDiv.textContent = `Error: ${error.message}`;
                debug.debugInfo.textContent += `Full Error: ${error.stack}\n`;
                document.getElementById('loading').style.display = 'none';
            }
        }

    </script>
</body>

</html>