import { getFromDB } from './db.js';
import { debounce, showNotification, _ } from './utils.js';
import { getMusicUrlsFromPlex } from './api.js';

export class MusicPlayer {
    constructor() {
        this.cancionesActuales = [];
        this.displayedSongs = [];
        this.indiceActual = -1;
        this.isPlaying = false;
        this.audioPlayer = document.getElementById("audioPlayer");
        this.currentArtist = "";
        this.currentAlbumId = null;
        this.currentSongId = null;
        this.currentArtistId = null;
        this.currentSongArtistId = null;
        this.db = null;
        this.artistListScrollPosition = 0;
        this.artistsData = [];
        this.artistsPageSize = 20;
        this.currentPage = 0;
        this.shuffleMode = false;
        this.tokens = [];
        this.isPlayerVisible = false;
        this.isReady = false;
        this.isInitializing = false;
        this.miniplayerManuallyClosed = false;
    }

    setDB(databaseInstance) {
        if (databaseInstance && this.db !== databaseInstance) {
            this.db = databaseInstance;
            if (!this.isReady && !this.isInitializing) {
                this.asyncInitialize();
            }
        }
    }

    async asyncInitialize() {
        if (this.isReady || this.isInitializing || !this.db) return;
        this.isInitializing = true;
        try {
            this.setupEventHandlers();
            await this.loadMusicData();
            this.updateArtistCounter();
            this.markCurrentArtist();
            this.setupIndexedDBUpdateListener();
            this.isReady = true;
        } catch (error) {
            showNotification(_('errorInitializingMusicPlayer'), "error");
            this.isReady = false;
        } finally {
            this.isInitializing = false;
        }
    }

    async loadMusicData() {
        if (!this.db) {
            document.getElementById('artistList').innerHTML = `<div class="list-item-empty">${_('dbUnavailableError')}</div>`;
            this.artistsData = []; this.tokens = []; this.updateArtistCounter();
            return;
        }
        try {
            const rawArtistData = await getFromDB('artists');
            this.artistsData = rawArtistData || [];
            this.loadTokens();
            const initialArtistList = this._generateFullArtistListForToken('all');
            this.loadArtists(initialArtistList, this.currentPage);
        } catch (error) {
            showNotification(_('criticalErrorLoadingMusic'), "error");
            this.artistsData = []; this.tokens = [];
            document.getElementById('artistList').innerHTML = `<div class="list-item-empty">${_('errorLoadingArtists')}</div>`;
            this.updateTokenSelectorUI();
            this.updateArtistCounter();
            throw error;
        }
    }

    setupEventHandlers() {
        document.querySelectorAll('#openMusicPlayerMobile, #openMusicPlayerDesktop, #openMusicPlayerFromMiniplayer').forEach(btn => {
            btn.addEventListener('click', () => this.togglePlayerVisibility());
        });
        document.getElementById('closeSideNavBtn').addEventListener('click', () => this.hidePlayer());
        document.getElementById('closeMiniplayerBtn').addEventListener('click', () => this.closeMiniplayer());
        document.getElementById('fab-music-player').addEventListener('click', () => this.openMiniplayer());
        document.getElementById('searchArtist').addEventListener("input", debounce(() => this.filterArtists(), 300));
        document.getElementById('searchSong').addEventListener("input", debounce(() => this.filterSongs(), 300));
        document.getElementById('backBtn').addEventListener('click', () => this.showArtistList());
        document.getElementById('playPauseBtn').addEventListener('click', () => this.togglePlayPause());
        document.getElementById('nextBtn').addEventListener('click', () => this.playNext());
        document.getElementById('prevBtn').addEventListener('click', () => this.playPrevious());
        document.getElementById('shuffleBtn').addEventListener('click', () => this.toggleShuffle());
        
        document.getElementById('volumeSlider').addEventListener("input", (event) => this.updateVolume(event));
        document.getElementById('volume-icon-btn').addEventListener('click', (e) => {
            e.stopPropagation();
            document.querySelector('.volume-slider-wrapper').classList.toggle('active');
            this.audioPlayer.muted = false;
            if (this.audioPlayer.volume === 0) {
                this.audioPlayer.volume = 0.5;
                this.updateVolumeIcon(0.5);
            }
        });
        document.addEventListener('click', (e) => {
            if (!document.getElementById('volumeControl').contains(e.target)) {
                document.querySelector('.volume-slider-wrapper').classList.remove('active');
            }
        });


        document.getElementById('downloadAlbumBtn').addEventListener('click', () => this.downloadAlbum());
        document.getElementById('downloadBtn').addEventListener('click', () => {
            if (this.indiceActual >= 0 && this.cancionesActuales[this.indiceActual]) {
                const currentSong = this.cancionesActuales[this.indiceActual];
                this.downloadSong(currentSong.url, currentSong.titulo, currentSong.extension);
            }
        });
        this.audioPlayer.addEventListener("ended", () => this.handleAudioEnded());
        this.audioPlayer.addEventListener("timeupdate", () => this.updateProgressBar());
        this.audioPlayer.addEventListener("error", () => this.handleAudioErrorEvent());
        
        const progressBarContainer = document.getElementById('progressBarContainer');
        progressBarContainer.addEventListener('click', (event) => this.seek(event));
        progressBarContainer.addEventListener('mousemove', (event) => this.updateSeekHover(event));
        progressBarContainer.addEventListener('mouseleave', () => this.hideSeekHover());

        document.getElementById('artistList').addEventListener("click", (event) => {
            const card = event.target.closest('.artist-card');
            if(card) this.loadArtistSongs(card);
        });
        document.getElementById('listaCanciones').addEventListener("click", (event) => {
            const item = event.target.closest('.song-item');
            if(item) {
                const index = parseInt(item.dataset.index, 10);
                if (!isNaN(index) && this.displayedSongs[index]) {
                    this.cancionesActuales = [...this.displayedSongs];
                    if (this.shuffleMode) {
                        this.shuffleArray(this.cancionesActuales);
                        const newIndex = this.cancionesActuales.findIndex(s => s.id === this.displayedSongs[index].id);
                        this.playSong(this.cancionesActuales[newIndex], newIndex);
                    } else {
                        this.playSong(this.cancionesActuales[index], index);
                    }
                }
            }
        });
        document.getElementById('prevArtistsBtn').addEventListener('click', () => this.loadPreviousArtists());
        document.getElementById('nextArtistsBtn').addEventListener('click', () => this.loadNextArtists());
        
        const tokenSelectorContainer = document.getElementById('tokenSelectorContainer');
        tokenSelectorContainer.addEventListener('click', e => {
            const target = e.target;
            const selectItems = tokenSelectorContainer.querySelector('.select-items');
            if (target.closest('.select-selected')) {
                selectItems.classList.toggle('select-hide');
                target.closest('.select-selected').classList.toggle('select-arrow-active');
            } else if (target.classList.contains('select-option')) {
                const selectedText = tokenSelectorContainer.querySelector('.select-selected span');
                selectedText.textContent = target.textContent;
                selectedText.dataset.value = target.dataset.value;
                selectItems.classList.add('select-hide');
                tokenSelectorContainer.querySelector('.select-selected').classList.remove('select-arrow-active');
                
                this.currentPage = 0;
                this.loadArtistsByToken(target.dataset.value);
            }
        });

        document.addEventListener('click', (e) => {
            if (!tokenSelectorContainer.contains(e.target)) {
                tokenSelectorContainer.querySelector('.select-items').classList.add('select-hide');
                tokenSelectorContainer.querySelector('.select-selected').classList.remove('select-arrow-active');
            }
        });

        document.getElementById('trackInfo').addEventListener('click', (event) => {
            if (event.target.closest('#albumCover')) {
                if (this.indiceActual >= 0 && this.cancionesActuales[this.indiceActual]) {
                    this.showInfoModal(this.cancionesActuales[this.indiceActual]);
                }
            }
        });
    }

    _getCurrentTokenFilter() {
        return document.querySelector("#tokenSelectorContainer .select-selected span").dataset.value;
    }
    
    handleAudioEnded() { this.playNext(); }
    handleAudioErrorEvent() { this.handleAudioError(_('playbackError')); }

    togglePlayerVisibility() {
        if (this.isPlayerVisible) this.hidePlayer();
        else this.showPlayer();
    }

    async showPlayer() {
        if (this.isPlayerVisible) return;
        
        gsap.to('#musicPlayerContainer', { x: 0, duration: 0.5, ease: 'power3.out' });
        this.isPlayerVisible = true;

        if (!this.isReady) await this.asyncInitialize();
        if (!this.isReady) {
            document.getElementById('artistList').innerHTML = `<div class="list-item-empty">${_('errorInitializingMusicPlayer')}</div>`;
            this.updateArtistCounter();
            return;
        }
        if (this.artistsData.length === 0 && this.isReady) {
            try { await this.loadMusicData(); } catch (error) {
                document.getElementById('artistList').innerHTML = `<div class="list-item-empty">${_('errorLoadingArtists')}</div>`;
                this.updateArtistCounter();
            }
        }
        this.markCurrentArtist();
        this.markCurrentSong();
    }

    hidePlayer() {
        if (!this.isPlayerVisible) return;
        gsap.to('#musicPlayerContainer', { x: '-100%', duration: 0.4, ease: 'power3.in' });
        this.isPlayerVisible = false;
    }

    closeMiniplayer() {
        this.miniplayerManuallyClosed = true;
        const miniplayer = document.getElementById('miniplayer');
        gsap.to(miniplayer, { y: '110%', duration: 0.5, ease: 'power3.in', onComplete: () => {
            miniplayer.style.display = 'none';
            document.body.classList.remove('miniplayer-active');
            if (this.indiceActual >= 0) {
                document.getElementById('fab-music-player').style.display = 'flex';
                gsap.fromTo('#fab-music-player', { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: 0.3, ease: 'back.out(1.7)' });
            }
        }});
    }

    openMiniplayer() {
        this.miniplayerManuallyClosed = false;
        const miniplayer = document.getElementById('miniplayer');
        const fab = document.getElementById('fab-music-player');
        gsap.to(fab, { scale: 0, opacity: 0, duration: 0.3, ease: 'back.in(1.7)', onComplete: () => {
            fab.style.display = 'none';
            miniplayer.style.display = 'grid';
            document.body.classList.add('miniplayer-active');
            gsap.fromTo(miniplayer, { y: '110%' }, { y: '0%', duration: 0.5, ease: 'power3.out' });
        }});
    }

    async handleDatabaseUpdate() {
        if (!this.isReady) await this.asyncInitialize();
        if (!this.isReady) return;
        showNotification(_('updatingMusicData'), "info", 1500);
        const currentTokenFilter = this._getCurrentTokenFilter();
        const songListPanel = document.getElementById("songListContainer");
        const wasSongListVisible = songListPanel.style.visibility === 'visible' && songListPanel.style.opacity === '1';
        const wasArtistId = this.currentArtistId;
        
        await this.loadMusicData();
        
        this.loadArtistsByToken(currentTokenFilter);
        
        if (wasSongListVisible && wasArtistId) {
            const artistCard = document.querySelector(`.artist-card[data-id='${wasArtistId}']`);
            if (artistCard) {
                try {
                    const canciones = await getMusicUrlsFromPlex(artistCard.dataset.token, artistCard.dataset.protocolo, artistCard.dataset.ip, artistCard.dataset.puerto, wasArtistId);
                    this.handleSongsLoaded(canciones, wasArtistId);
                    this.markCurrentSong();
                    
                    const tl = gsap.timeline();
                    tl.set("#artistListContainer", { x: "-100%", autoAlpha: 0 });
                    tl.set("#songListContainer", { x: "0%", autoAlpha: 1 });

                } catch (error) { this.showArtistList(); }
            } else this.showArtistList();
        } else {
            this.loadArtistsByToken(currentTokenFilter);
            this.markCurrentArtist();
        }
        showNotification(_('musicDataUpdated'), "success", 1500);
    }

    setupIndexedDBUpdateListener() {
        window.removeEventListener('indexedDBUpdated', this.boundHandleDatabaseUpdate);
        this.boundHandleDatabaseUpdate = this.handleDatabaseUpdate.bind(this);
        window.addEventListener('indexedDBUpdated', this.boundHandleDatabaseUpdate);
    }

    loadTokens() {
        const tokenMap = new Map();
        (this.artistsData || []).forEach(servidor => {
            if (!servidor) return;
            const primaryToken = servidor.tokenPrincipal;
            const serverToken = servidor.token;
            const serverName = servidor.serverName || servidor.ip || `Token Desconocido`;
            if (primaryToken && !tokenMap.has(primaryToken)) tokenMap.set(primaryToken, serverName);
            else if (serverToken && !tokenMap.has(serverToken) && !primaryToken) tokenMap.set(serverToken, serverName);
        });
        this.tokens = Array.from(tokenMap, ([value, name]) => ({ value, name }));
        this.updateTokenSelectorUI();
    }
    
    updateTokenSelectorUI() {
        const selectItems = document.querySelector('#tokenSelectorContainer .select-items');
        const selectedText = document.querySelector('#tokenSelectorContainer .select-selected span');
        const previousValue = selectedText.dataset.value;

        selectItems.innerHTML = `<div class="select-option" data-value="all">${_('musicAllServers')}</div>`;

        this.tokens.forEach(token => {
            const optionDiv = document.createElement('div');
            optionDiv.classList.add('select-option');
            optionDiv.dataset.value = token.value;
            optionDiv.textContent = token.name;
            selectItems.appendChild(optionDiv);
        });

        const currentSelection = this.tokens.find(t => t.value === previousValue);
        if (currentSelection) {
            selectedText.textContent = currentSelection.name;
            selectedText.dataset.value = currentSelection.value;
        } else {
            selectedText.textContent = _('musicAllServers');
            selectedText.dataset.value = 'all';
        }
    }

    _generateFullArtistListForToken(token) {
        let filteredSourceData = (token === "all" || !token) ? this.artistsData : (this.artistsData || []).filter(s => s && (s.tokenPrincipal === token || (!s.tokenPrincipal && s.token === token)));
        const artistMap = new Map();
        (filteredSourceData || []).forEach(servidor => {
            if (servidor && Array.isArray(servidor.titulos)) {
                servidor.titulos.forEach(artista => {
                    if (artista && typeof artista.id !== 'undefined' && artista.id !== null && !artistMap.has(artista.id)) {
                        artistMap.set(artista.id, {
                            id: artista.id, title: artista.title || 'Artista Desconocido',
                            token: servidor.token, ip: servidor.ip, puerto: servidor.puerto,
                            protocolo: servidor.protocolo, serverName: servidor.serverName || servidor.ip || 'Servidor Desconocido',
                            thumb: artista.thumb
                        });
                    }
                });
            }
        });
        return Array.from(artistMap.values()).sort((a, b) => (a.title || '').localeCompare(b.title || ''));
    }

    loadArtists(fullArtistListForFilter, page) {
        if (!this.isReady) return;
        const totalArtists = fullArtistListForFilter.length;
        const start = page * this.artistsPageSize;
        const end = Math.min(start + this.artistsPageSize, totalArtists);
        const artistGrid = document.getElementById("artistList");
        artistGrid.innerHTML = '';

        if (totalArtists === 0) {
            artistGrid.innerHTML = `<div class="list-item-empty" style="grid-column: 1 / -1;">${_('noArtistsFound')}</div>`;
            document.getElementById('prevArtistsBtn').style.display = 'none';
            document.getElementById('nextArtistsBtn').style.display = 'none';
            this.updateArtistCounter(0, 0, 0); return;
        }

        const artistsToDisplay = fullArtistListForFilter.slice(start, end);
        artistsToDisplay.forEach((artista) => {
            if (artista && typeof artista.id !== 'undefined' && artista.id !== null && artista.title) {
                const card = document.createElement('div');
                card.className = 'artist-card';

                const thumbUrl = artista.thumb 
                    ? `${artista.protocolo}://${artista.ip}:${artista.puerto}${artista.thumb}?X-Plex-Token=${artista.token}` 
                    : null;

                card.innerHTML = `
                    <div class="artist-thumb-wrapper">
                        ${thumbUrl 
                            ? `<img src="${thumbUrl}" class="artist-thumb" alt="${artista.title}" loading="lazy">` 
                            : '<i class="fas fa-user-music artist-thumb-placeholder"></i>'}
                    </div>
                    <div class="artist-card-title">${artista.title}</div>
                `;
                card.dataset.id = artista.id;
                card.dataset.token = artista.token;
                card.dataset.ip = artista.ip;
                card.dataset.puerto = artista.puerto;
                card.dataset.protocolo = artista.protocolo;
                card.dataset.thumb = artista.thumb || '';
                card.title = `${artista.title} en ${artista.serverName || 'Servidor Desconocido'}`;
                artistGrid.appendChild(card);
            }
        });
        gsap.from(".artist-card", {
            duration: 0.5,
            opacity: 0,
            y: 20,
            stagger: 0.05,
            ease: "power3.out"
        });
        document.getElementById('prevArtistsBtn').style.display = page > 0 ? 'inline-flex' : 'none';
        document.getElementById('nextArtistsBtn').style.display = end < totalArtists ? 'inline-flex' : 'none';
        this.markCurrentArtist();
        this.updateArtistCounter(start + 1, end, totalArtists);
    }

    loadArtistsByToken(token) {
        if (!this.isReady) return;
        this.currentPage = 0;
        this.loadArtists(this._generateFullArtistListForToken(token), this.currentPage);
    }

    loadPreviousArtists() {
        if (!this.isReady || this.currentPage <= 0) return;
        this.currentPage--;
        this.loadArtists(this._generateFullArtistListForToken(this._getCurrentTokenFilter()), this.currentPage);
    }

    loadNextArtists() {
        if (!this.isReady) return;
        const fullList = this._generateFullArtistListForToken(this._getCurrentTokenFilter());
        if ((this.currentPage + 1) * this.artistsPageSize < fullList.length) {
            this.currentPage++;
            this.loadArtists(fullList, this.currentPage);
        }
    }

    updateArtistCounter(start = 0, end = 0, total = 0) {
        const counter = document.getElementById('artistCounter');
        if (!this.isReady) counter.textContent = _('artistsCounterLoading');
        else if (total === 0) counter.textContent = _('artistsCounterSingle', '0');
        else counter.textContent = _('artistsCounter', [start, end, total]);
    }

    async loadArtistSongs(selectedCard) {
        if (!this.isReady) return;
        const { token, protocolo, ip, puerto, id: artistaId, thumb } = selectedCard.dataset;
        this.currentArtist = selectedCard.querySelector('.artist-card-title').textContent;
        this.currentArtistId = artistaId;
        if (!artistaId) return;

        const thumbUrl = thumb ? `${protocolo}://${ip}:${puerto}${thumb}?X-Plex-Token=${token}` : 'img/no-profile.png';
        document.getElementById('artist-header-thumb').src = thumbUrl;
        document.getElementById('artist-header-title').textContent = this.currentArtist;
        
        const tl = gsap.timeline();
        tl.to("#artistListContainer", { x: "-100%", autoAlpha: 0, duration: 0.5, ease: "power3.inOut" })
          .fromTo("#songListContainer", { x: "100%", autoAlpha: 0 }, { x: "0%", autoAlpha: 1, duration: 0.5, ease: "power3.inOut" }, "-=0.5");

        document.getElementById('loader').style.display = 'block';
        document.getElementById('listaCanciones').innerHTML = '';

        try {
            let canciones = await getMusicUrlsFromPlex(token, protocolo, ip, puerto, artistaId);
            this.handleSongsLoaded(canciones, artistaId);
        } catch (error) {
            showNotification(_('errorFetchingArtistSongs'), "error");
            document.getElementById('listaCanciones').innerHTML = `<div class="list-item-empty">${_('errorLoadingSongs')}</div>`;
            this.showArtistList();
        } finally {
            document.getElementById('loader').style.display = 'none';
        }
    }

    handleSongsLoaded(canciones, artistId) {
        if (!this.isReady) return;
        if (!Array.isArray(canciones)) canciones = [];
        
        canciones.sort((a, b) => {
            const albumCompare = (a.album || '').localeCompare(b.album || '');
            if (albumCompare !== 0) return albumCompare;
            const trackIndexA = a.trackIndex !== undefined ? a.trackIndex : (a.title || '');
            const trackIndexB = b.trackIndex !== undefined ? b.trackIndex : (b.title || '');
            return trackIndexA - trackIndexB;
        });

        this.displayedSongs = canciones;
        this.currentAlbumId = artistId;
        this.displaySongList(this.displayedSongs);
        this.markCurrentSong();
    }

    shuffleArray(array) {
        for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [array[i], array[j]] = [array[j], array[i]];
        }
    }

    displaySongList(songsToDisplay) {
        if (!this.isReady) return;
        const lista = document.getElementById("listaCanciones");
        lista.innerHTML = '';
        if (!Array.isArray(songsToDisplay) || songsToDisplay.length === 0) {
            lista.innerHTML = `<div class="list-item-empty">${_('noSongsFound')}</div>`;
            return;
        }

        const albums = songsToDisplay.reduce((acc, cancion) => {
            const albumTitle = cancion.album || 'Otras Canciones';
            if (!acc[albumTitle]) acc[albumTitle] = [];
            acc[albumTitle].push(cancion);
            return acc;
        }, {});

        const fragment = document.createDocumentFragment();
        let songCounter = 0;
        for (const albumTitle in albums) {
            const albumWrapper = document.createElement('div');
            albumWrapper.className = 'album-group';
            const albumHeader = document.createElement('h6');
            albumHeader.className = 'album-group-title';
            albumHeader.textContent = albumTitle;
            albumWrapper.appendChild(albumHeader);

            albums[albumTitle].forEach(cancion => {
                if (cancion && cancion.titulo) {
                    const item = document.createElement('div');
                    item.className = 'song-item';
                    item.innerHTML = `
                        <span class="song-number">${cancion.index || songCounter + 1}</span>
                        <div class="song-details">
                            <div class="item-title">${cancion.titulo}</div>
                        </div>
                        <i class="fas fa-play play-icon"></i>
                    `;
                    item.dataset.index = songCounter;
                    item.dataset.id = cancion.id;
                    item.dataset.artistId = cancion.artistId;
                    item.title = `${cancion.titulo} - ${cancion.album}`;
                    albumWrapper.appendChild(item);
                    songCounter++;
                }
            });
            fragment.appendChild(albumWrapper);
        }
        lista.appendChild(fragment);
        this.markCurrentSong();
        gsap.from(".album-group", { duration: 0.5, opacity: 0, y: 20, stagger: 0.1, ease: "power3.out" });
    }

    playSong(cancion, index) {
        if (!this.isReady || !this.audioPlayer || !cancion || !cancion.url) return;
        
        const songItemElement = document.querySelector(`.song-item[data-index='${index}']`);
        const playIconElement = songItemElement ? songItemElement.querySelector('.play-icon') : null;

        if (playIconElement) {
            playIconElement.className = 'loading-spinner';
        }

        const miniplayer = document.getElementById('miniplayer');
        if (miniplayer.style.display === 'none' && !this.miniplayerManuallyClosed) {
             gsap.fromTo(miniplayer, { y: '100%' }, { display: 'grid', y: '0%', duration: 0.5, ease: 'power3.out' });
        }
        document.body.classList.add('miniplayer-active');

        this.audioPlayer.innerHTML = '';
        const source = document.createElement('source');
        source.src = cancion.url;
        source.type = this.getMimeType(cancion.extension);
        this.audioPlayer.appendChild(source);

        const tl = gsap.timeline();
        tl.to(['#albumCover', '#trackTitle', '#trackArtist'], { opacity: 0, y: -10, duration: 0.2, ease: "power2.in", stagger: 0.05 })
          .add(() => {
                document.getElementById('albumCover').src = cancion.cover || 'img/no-poster.png';
                document.getElementById('trackTitle').textContent = cancion.titulo;
                document.getElementById('trackArtist').textContent = cancion.artista;
          })
          .to(['#albumCover', '#trackTitle', '#trackArtist'], { opacity: 1, y: 0, duration: 0.4, ease: "power2.out", stagger: 0.07 });

        this.audioPlayer.load();
        this.audioPlayer.play().then(() => {
            this.isPlaying = true;
            document.getElementById('playPauseBtn').innerHTML = '<i class="fas fa-pause"></i>';
            this.indiceActual = index;
            this.currentSongId = cancion.id;
            this.currentSongArtistId = cancion.artistId;
            this.markCurrentSong();
            this.ensureArtistVisible(cancion.artistId);
            if (playIconElement) {
                playIconElement.className = 'fas fa-play play-icon';
            }
            if (!this.miniplayerManuallyClosed) {
                document.getElementById('fab-music-player').style.display = 'none';
            }
        }).catch((error) => {
            this.handleAudioError(_('playbackError'));
            if (playIconElement) {
                playIconElement.className = 'fas fa-play play-icon';
            }
        });
    }

    getMimeType(extension) {
        const mimeTypes = { 'mp3': 'audio/mpeg', 'wav': 'audio/wav', 'ogg': 'audio/ogg', 'oga': 'audio/ogg', 'm4a': 'audio/mp4', 'mp4': 'audio/mp4', 'aac': 'audio/aac', 'flac': 'audio/flac', 'opus': 'audio/opus', 'weba': 'audio/webm', 'webm': 'audio/webm' };
        return mimeTypes[extension?.toLowerCase()] || undefined;
    }

    togglePlayPause() {
        if (!this.isReady || !this.audioPlayer || this.indiceActual < 0) return;
        const btn = document.getElementById('playPauseBtn');
        if (this.isPlaying) {
            this.audioPlayer.pause();
            btn.innerHTML = '<i class="fas fa-play"></i>';
        } else {
            this.audioPlayer.play().then(() => { btn.innerHTML = '<i class="fas fa-pause"></i>'; })
            .catch(err => { this.isPlaying = false; btn.innerHTML = '<i class="fas fa-play"></i>'; });
        }
        this.isPlaying = !this.isPlaying;
        if (this.isPlaying) {
            document.getElementById('fab-music-player').style.display = 'none';
        }
    }

    playNext() {
        if (!this.isReady || this.cancionesActuales.length === 0) return;
        let nextIndex;
        if (this.shuffleMode) {
            if (this.cancionesActuales.length <= 1) {
                nextIndex = 0;
            } else {
                do {
                    nextIndex = Math.floor(Math.random() * this.cancionesActuales.length);
                } while (nextIndex === this.indiceActual);
            }
        } else {
            nextIndex = (this.indiceActual + 1) % this.cancionesActuales.length;
        }
        if (this.cancionesActuales[nextIndex]) this.playSong(this.cancionesActuales[nextIndex], nextIndex);
    }

    playPrevious() {
        if (!this.isReady || this.cancionesActuales.length === 0) return;
        let prevIndex;
        if (this.shuffleMode) {
            if (this.cancionesActuales.length <= 1) {
                prevIndex = 0;
            } else {
                do {
                    prevIndex = Math.floor(Math.random() * this.cancionesActuales.length);
                } while (prevIndex === this.indiceActual);
            }
        } else {
            prevIndex = (this.indiceActual - 1 + this.cancionesActuales.length) % this.cancionesActuales.length;
        }
        if (this.cancionesActuales[prevIndex]) this.playSong(this.cancionesActuales[prevIndex], prevIndex);
    }

    toggleShuffle() {
        if (!this.isReady) return;
        this.shuffleMode = !this.shuffleMode;
        document.getElementById('shuffleBtn').classList.toggle("active", this.shuffleMode);
        showNotification(this.shuffleMode ? _('shuffleOn') : _('shuffleOff'), 'info', 1500);
    }

    markCurrentSong() {
        if (!this.isReady) return;
        document.querySelectorAll(".song-item").forEach(item => {
            item.classList.remove("current-song");
        });
        if (this.currentSongId !== null) {
            const songItem = document.querySelector(`.song-item[data-id='${this.currentSongId}']`);
            if (songItem) {
                songItem.classList.add("current-song");
            }
        }
    }

    markCurrentArtist() {
        if (!this.isReady) return;
        const targetArtistId = this.currentSongArtistId;
        document.querySelectorAll(".artist-card").forEach(card => {
            if (targetArtistId != null && card.dataset.id == targetArtistId) {
                card.classList.add("current-artist");
            } else {
                card.classList.remove("current-artist");
            }
        });
    }

    updateProgressBar() {
        if (!this.isReady || !this.audioPlayer) return;
        const { currentTime, duration } = this.audioPlayer;
        if (!isNaN(duration) && duration > 0) {
            const progressPercent = (currentTime / duration) * 100;
            document.getElementById("played-bar").style.width = `${progressPercent}%`;
            document.getElementById("progress-handle").style.left = `${progressPercent}%`;
            document.getElementById("elapsedTime").textContent = this.formatTime(currentTime);
            document.getElementById("remainingTime").textContent = this.formatTime(duration);
        }
    }

    updateSeekHover(event) {
        const progressBarContainer = document.getElementById("progressBarContainer");
        const rect = progressBarContainer.getBoundingClientRect();
        const hoverWidth = ((event.clientX - rect.left) / rect.width) * 100;
        document.getElementById('seek-hover-bar').style.width = `${Math.max(0, Math.min(hoverWidth, 100))}%`;
    }
    hideSeekHover() {
        document.getElementById('seek-hover-bar').style.width = `0%`;
    }
    
    handleAudioError(message = _('playbackError')) {
        if (!this.isReady || !this.audioPlayer) return;
        showNotification(message, "error");
        document.getElementById("remainingTime").textContent = _('errorLabel');
        document.getElementById('playPauseBtn').innerHTML = '<i class="fas fa-play"></i>';
        this.isPlaying = false;
    }

    seek(event) {
        if (!this.isReady || !this.audioPlayer || isNaN(this.audioPlayer.duration) || this.audioPlayer.duration <= 0) return;
        const progressBarContainer = document.getElementById("progressBarContainer");
        const rect = progressBarContainer.getBoundingClientRect();
        const seekTime = ((event.clientX - rect.left) / rect.width) * this.audioPlayer.duration;
        this.audioPlayer.currentTime = Math.max(0, Math.min(seekTime, this.audioPlayer.duration));
    }

    formatTime(seconds) {
        if (isNaN(seconds) || seconds < 0) return "0:00";
        const minutes = Math.floor(seconds / 60);
        const remainingSeconds = Math.floor(seconds % 60);
        return `${minutes}:${remainingSeconds < 10 ? "0" : ""}${remainingSeconds}`;
    }

    downloadSong(url, titulo, extension) {
        if (!this.isReady || !url || !titulo) return;
        showNotification(_('downloadingSong', titulo), "info");
        fetch(url).then(response => response.blob()).then(blob => {
            const urlBlob = window.URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.style.display = "none";
            a.href = urlBlob;
            a.download = `${titulo.replace(/[\\/:*?"<>|]/g, "_").replace(/\s+/g, '_')}.${extension || 'mp3'}`;
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(urlBlob);
            a.remove();
            showNotification(_('songDownloaded', titulo), "success");
        }).catch(err => showNotification(_('errorDownloadingSong', titulo), "error"));
    }

    downloadAlbum() {
        if (!this.isReady || this.cancionesActuales.length === 0 || !this.currentArtist) return;
        showNotification(_('generatingAlbumM3U', this.currentArtist), "info");
        const m3uContent = ["#EXTM3U", ...this.cancionesActuales.map(c => `#EXTINF:-1 tvg-name="${c.artista} - ${c.titulo}",${c.artista} - ${c.titulo}\n${c.url}`)];
        const blob = new Blob([m3uContent.join("\n")], { type: "audio/x-mpegurl;charset=utf-8" });
        const urlBlob = window.URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = urlBlob;
        a.download = `${this.currentArtist.replace(/[\\/:*?"<>|]/g, "_").replace(/\s+/g, '_')}_Album.m3u`;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(urlBlob);
        a.remove();
        showNotification(_('albumM3UGenerated', this.currentArtist), "success");
    }

    updateVolume(event) {
        if (!this.isReady || !this.audioPlayer) return;
        const volume = event.currentTarget.value;
        this.audioPlayer.volume = volume;
        this.updateVolumeIcon(volume);
    }
    
    updateVolumeIcon(volume) {
        const vol = parseFloat(volume);
        const icon = document.querySelector('#volume-icon-btn i');
        if (vol === 0) {
            icon.className = 'fas fa-volume-mute';
        } else if (vol < 0.5) {
            icon.className = 'fas fa-volume-down';
        } else {
            icon.className = 'fas fa-volume-up';
        }
    }

    filterArtists() {
        if (!this.isReady) return;
        const value = document.getElementById("searchArtist").value.toLowerCase();
        const tokenFilter = this._getCurrentTokenFilter();
        const fullList = this._generateFullArtistListForToken(tokenFilter);
        const filteredArtists = fullList.filter(a => a.title?.toLowerCase().includes(value));
        const artistGrid = document.getElementById("artistList");
        artistGrid.innerHTML = '';
        if (filteredArtists.length === 0) {
            artistGrid.innerHTML = `<div class="list-item-empty" style="grid-column: 1 / -1;">${_('noArtistsFound')}</div>`;
        } else {
            filteredArtists.forEach((artista) => {
                const card = document.createElement('div');
                card.className = 'artist-card';
                const thumbUrl = artista.thumb ? `${artista.protocolo}://${artista.ip}:${artista.puerto}${artista.thumb}?X-Plex-Token=${artista.token}` : null;
                card.innerHTML = `
                    <div class="artist-thumb-wrapper">
                        ${thumbUrl ? `<img src="${thumbUrl}" class="artist-thumb" alt="${artista.title}" loading="lazy">` : '<i class="fas fa-user-music artist-thumb-placeholder"></i>'}
                    </div>
                    <div class="artist-card-title">${artista.title}</div>
                `;
                card.dataset.id = artista.id;
                card.dataset.token = artista.token;
                card.dataset.ip = artista.ip;
                card.dataset.puerto = artista.puerto;
                card.dataset.protocolo = artista.protocolo;
                card.dataset.thumb = artista.thumb || '';
                card.title = `${artista.title} en ${artista.serverName || 'Servidor Desconocido'}`;
                artistGrid.appendChild(card);
            });
        }
        if (value === '') {
            this.loadArtists(fullList, this.currentPage);
        } else {
            document.getElementById('prevArtistsBtn').style.display = 'none';
            document.getElementById('nextArtistsBtn').style.display = 'none';
            document.getElementById('artistCounter').style.display = 'none';
            this.markCurrentArtist();
        }
    }

    filterSongs() {
        if (!this.isReady) return;
        const value = document.getElementById("searchSong").value.toLowerCase();
        const filteredSongs = this.cancionesActuales.filter(c => c.titulo?.toLowerCase().includes(value) || c.album?.toLowerCase().includes(value));
        this.displaySongList(filteredSongs);
    }

    showArtistList() {
        if (!this.isReady) return;
        
        const tl = gsap.timeline();
        tl.to("#songListContainer", { x: "100%", autoAlpha: 0, duration: 0.5, ease: "power3.inOut" })
          .to("#artistListContainer", { x: "0%", autoAlpha: 1, duration: 0.5, ease: "power3.inOut" }, "-=0.5");
        
        if (document.getElementById("searchArtist").value === '') {
            this.loadArtists(this._generateFullArtistListForToken(this._getCurrentTokenFilter()), this.currentPage);
        } else {
            this.filterArtists();
        }
        this.markCurrentArtist();
    }

    showInfoModal(cancion) {
        if (!this.isReady || !cancion) return;
        document.querySelector('#infoModalLabel').textContent = `${_('infoModalTitle')}: ${cancion.titulo}`;
        document.querySelector('#modalTitle span').textContent = cancion.titulo || 'N/A';
        document.querySelector('#modalArtist span').textContent = cancion.artista || 'N/A';
        document.querySelector('#modalAlbum span').textContent = cancion.album || 'N/A';
        document.querySelector('#modalSong span').textContent = cancion.titulo || 'N/A';
        document.querySelector('#modalYear span').textContent = cancion.year || 'N/A';
        document.querySelector('#modalGenre span').textContent = cancion.genre || 'N/A';
        const infoModal = bootstrap.Modal.getOrCreateInstance(document.getElementById('infoModal'));
        infoModal.show();
    }

    ensureArtistVisible(artistId) {
        if (!this.isReady || artistId === null) return;
        const artistCard = document.querySelector(`.artist-card[data-id='${artistId}']`);
        if (artistCard) {
            this.markCurrentArtist(artistId);
            return;
        }

        const fullList = this._generateFullArtistListForToken(this._getCurrentTokenFilter());
        const artistIndex = fullList.findIndex(a => a.id == artistId);

        if (artistIndex !== -1) {
            const targetPage = Math.floor(artistIndex / this.artistsPageSize);
            if (this.currentPage !== targetPage) {
                this.currentPage = targetPage;
                this.loadArtists(fullList, this.currentPage);
            }
        }
        this.markCurrentArtist(artistId);
    }
}