//js/events.js
import {
    REPEAT_MODE,
    trackDataStore,
    formatTime,
    getTrackArtists,
    positionMenu,
    getShareUrl,
    escapeHtml,
} from './utils.js';
import {
    lastFMStorage,
    libreFmSettings,
    listenBrainzSettings,
    waveformSettings,
    keyboardShortcuts,
} from './storage.js';
import { showNotification, downloadTrackWithMetadata, downloadAlbum, downloadPlaylist } from './downloads.js';
import { downloadQualitySettings } from './storage.js';
import { updateTabTitle, navigate } from './router.js';
import { db } from './db.js';
import { syncManager } from './accounts/pocketbase.js';
import { waveformGenerator } from './waveform.js';
import { audioContextManager } from './audio-context.js';
import { hapticLongPress, hapticMedium, hapticLight } from './haptics.js';
import { SVG_BIN, SVG_MUTE, SVG_PAUSE, SVG_PLAY, SVG_VOLUME, SVG_CHECKBOX, SVG_CHECKBOX_CHECKED } from './icons.js';
import { partyManager } from './listening-party.js';
import { MusicAPI } from './music-api.js';
import { LyricsManager } from './lyrics.js';
import { Player } from './player.js';

let currentTrackIdForWaveform = null;

const trackSelection = {
    selectedIds: new Set(),
    lastClickedId: null,
    isSelecting: false,
};

let longPressTimer = null;
let isLongPress = false;
let longPressTrackItem = null;
const LONG_PRESS_DURATION = 500;

function handleTrackTouchStart(e) {
    if (!('ontouchstart' in window)) return;
    const trackItem = e.target.closest('.track-item');
    if (!trackItem || trackItem.classList.contains('unavailable')) return;

    isLongPress = false;
    longPressTrackItem = trackItem;

    longPressTimer = setTimeout(async () => {
        isLongPress = true;
        toggleTrackSelection(trackItem, true, false);
        await hapticLongPress();
    }, LONG_PRESS_DURATION);
}

function handleTrackTouchMove(_e) {
    if (longPressTimer) {
        clearTimeout(longPressTimer);
        longPressTimer = null;
    }
}

function handleTrackTouchEnd(_e) {
    if (longPressTimer) {
        clearTimeout(longPressTimer);
        longPressTimer = null;
    }
    setTimeout(() => {
        isLongPress = false;
        longPressTrackItem = null;
    }, 100);
}

function isMultiSelectToggle(e) {
    const shortcut = keyboardShortcuts.getShortcutForAction('multiSelectToggle');
    if (!shortcut) return e.ctrlKey || e.metaKey;
    const key = e.key?.toLowerCase();
    const shortcutKey = shortcut.key?.toLowerCase();

    if (['control', 'shift', 'alt', 'meta'].includes(shortcutKey)) {
        if (shortcut.ctrl && !(e.ctrlKey || e.metaKey)) return false;
        if (shortcut.shift && !e.shiftKey) return false;
        if (shortcut.alt && !e.altKey) return false;
        return true;
    }

    return (
        (shortcut.ctrl ? e.ctrlKey || e.metaKey : !e.ctrlKey && !e.metaKey) &&
        (shortcut.shift ? e.shiftKey : !e.shiftKey) &&
        (shortcut.alt ? e.altKey : !e.altKey) &&
        key === shortcutKey
    );
}

function isMultiSelectRange(e) {
    const shortcut = keyboardShortcuts.getShortcutForAction('multiSelectRange');
    if (!shortcut) return e.shiftKey;
    const key = e.key?.toLowerCase();
    const shortcutKey = shortcut.key?.toLowerCase();

    if (['control', 'shift', 'alt', 'meta'].includes(shortcutKey)) {
        if (shortcut.ctrl && !(e.ctrlKey || e.metaKey)) return false;
        if (shortcut.shift && !e.shiftKey) return false;
        if (shortcut.alt && !e.altKey) return false;
        return true;
    }

    return (
        (shortcut.ctrl ? e.ctrlKey || e.metaKey : !e.ctrlKey && !e.metaKey) &&
        (shortcut.shift ? e.shiftKey : !e.shiftKey) &&
        (shortcut.alt ? e.altKey : !e.altKey) &&
        key === shortcutKey
    );
}

function getSelectedTracks() {
    return Array.from(trackSelection.selectedIds);
}

function updateCheckbox(checkbox, checked) {
    if (checkbox) {
        checkbox.innerHTML = checked ? SVG_CHECKBOX_CHECKED(18) : SVG_CHECKBOX(18);
        checkbox.classList.toggle('checked', checked);
    }
}

function toggleTrackSelection(trackItem, ctrlHeld, shiftHeld) {
    const trackId = trackItem.dataset.trackId;
    const isSelected = trackSelection.selectedIds.has(trackId);

    if (ctrlHeld) {
        if (isSelected) {
            trackSelection.selectedIds.delete(trackId);
            trackItem.classList.remove('selected');
            updateCheckbox(trackItem.querySelector('.track-checkbox'), false);
        } else {
            trackSelection.selectedIds.add(trackId);
            trackItem.classList.add('selected');
            updateCheckbox(trackItem.querySelector('.track-checkbox'), true);
        }
        trackSelection.lastClickedId = trackId;
    } else if (shiftHeld && trackSelection.lastClickedId && trackSelection.lastClickedId !== trackId) {
        const parentList = trackItem.closest('.track-list') || trackItem.closest('#main-content');
        const allTrackElements = Array.from(parentList.querySelectorAll('.track-item'));
        const lastIndex = allTrackElements.findIndex((el) => el.dataset.trackId === trackSelection.lastClickedId);
        const currentIndex = allTrackElements.findIndex((el) => el.dataset.trackId === trackId);

        if (lastIndex !== -1 && currentIndex !== -1) {
            const start = Math.min(lastIndex, currentIndex);
            const end = Math.max(lastIndex, currentIndex);
            for (let i = start; i <= end; i++) {
                const el = allTrackElements[i];
                trackSelection.selectedIds.add(el.dataset.trackId);
                el.classList.add('selected');
                updateCheckbox(el.querySelector('.track-checkbox'), true);
            }
        }
    } else {
        if (!isSelected) {
            trackSelection.selectedIds.add(trackId);
            trackItem.classList.add('selected');
            updateCheckbox(trackItem.querySelector('.track-checkbox'), true);
        } else {
            trackSelection.selectedIds.delete(trackId);
            trackItem.classList.remove('selected');
            updateCheckbox(trackItem.querySelector('.track-checkbox'), false);
        }
        trackSelection.lastClickedId = trackId;
    }

    trackSelection.isSelecting = trackSelection.selectedIds.size > 0;
    document.body.classList.toggle('multi-select-mode', trackSelection.isSelecting);
}

async function showMultiSelectPlaylistModal(tracks) {
    const modal = document.createElement('div');
    modal.className = 'modal-overlay';
    modal.style.cssText =
        'position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.8); display: flex; align-items: center; justify-content: center; z-index: 10000;';
    modal.innerHTML = `
        <div class="modal-content" style="background: var(--card); border-radius: var(--radius); padding: 1.5rem; min-width: 350px; max-width: 90%; max-height: 80vh; overflow-y: auto; box-shadow: 0 4px 20px rgba(0,0,0,0.3);">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; border-bottom: 1px solid var(--border); padding-bottom: 0.75rem;">
                <h3 style="margin: 0;">Add to Playlist</h3>
                <button class="modal-close" style="background: none; border: none; color: var(--foreground); font-size: 1.5rem; cursor: pointer; padding: 0; line-height: 1;">&times;</button>
            </div>
            <div class="playlist-body" style="max-height: 300px; overflow-y: auto;">
                <div class="create-new-playlist" style="padding: 12px; cursor: pointer; border-bottom: 1px solid var(--border); color: var(--primary); font-weight: 500;">
                    + Create new playlist
                </div>
                <div class="playlist-list"></div>
            </div>
        </div>
    `;

    const closeModal = () => {
        modal.remove();
        document.body.style.overflow = '';
    };

    modal.querySelector('.modal-close').addEventListener('click', closeModal);
    modal.addEventListener('click', (e) => {
        if (e.target === modal) closeModal();
    });

    document.body.appendChild(modal);
    document.body.style.overflow = 'hidden';

    await db.getPlaylists(true).then((playlists) => {
        const listEl = modal.querySelector('.playlist-list');
        if (playlists.length === 0) {
            listEl.innerHTML = '<div style="padding: 12px; color: var(--muted-foreground);">No playlists yet</div>';
        } else {
            listEl.innerHTML = playlists
                .map(
                    (p) => `
                <div class="playlist-item" data-playlist-id="${p.id}" style="padding: 12px; cursor: pointer; border-bottom: 1px solid var(--border);">
                    <span>${escapeHtml(p.name)}</span>
                    <span style="color: var(--muted-foreground); font-size: 0.85rem; margin-left: 8px;">${p.tracks?.length || 0} tracks</span>
                </div>
            `
                )
                .join('');
        }

        listEl.querySelectorAll('.playlist-item').forEach((item) => {
            item.addEventListener('click', async () => {
                const playlistId = item.dataset.playlistId;
                for (const track of tracks) {
                    await db.addTrackToPlaylist(playlistId, track);
                }
                await syncManager.syncUserPlaylist(await db.getPlaylist(playlistId), 'update');
                showNotification(`Added ${tracks.length} tracks to playlist`);
                closeModal();
            });
        });
    });

    modal.querySelector('.create-new-playlist').addEventListener('click', async () => {
        const name = prompt('Playlist name:');
        if (name) {
            await db.createPlaylist(name, tracks).then((_playlist) => {
                showNotification(`Created playlist "${name}" with ${tracks.length} tracks`);
                closeModal();
            });
        }
    });
}

const playPauseBtn = document.querySelector('.now-playing-bar .play-pause-btn');
const nextBtn = document.getElementById('next-btn');
const prevBtn = document.getElementById('prev-btn');
const shuffleBtn = document.getElementById('shuffle-btn');
const repeatBtn = document.getElementById('repeat-btn');
const homeStartRadioBtn = document.getElementById('home-start-infinite-radio-btn');
const sleepTimerBtnDesktop = document.getElementById('sleep-timer-btn-desktop');

const _volumeBar = document.getElementById('volume-bar');
const volumeFill = document.getElementById('volume-fill');
const volumeBtn = document.getElementById('volume-btn');

const updateVolumeUI = () => {
    const activeEl = Player.instance.activeElement;
    const { muted } = activeEl;
    const volume = Player.instance.userVolume;
    volumeBtn.innerHTML = muted || volume === 0 ? SVG_MUTE(20) : SVG_VOLUME(20);
    const effectiveVolume = muted ? 0 : volume * 100;
    volumeFill.style.setProperty('--volume-level', `${effectiveVolume}%`);
    volumeFill.style.width = `${effectiveVolume}%`;
};

function clearSelection() {
    trackSelection.selectedIds.clear();
    trackSelection.lastClickedId = null;
    trackSelection.isSelecting = false;
    document.body.classList.remove('multi-select-mode');
    document.querySelectorAll('.track-item.selected').forEach((el) => {
        el.classList.remove('selected');
    });
    document.querySelectorAll('.track-checkbox').forEach((checkbox) => {
        checkbox.innerHTML = SVG_CHECKBOX(18);
        checkbox.classList.remove('checked');
    });
    updateSelectionBar();
}

function updateSelectionBar() {
    let bar = document.getElementById('selection-bar');
    if (!bar) {
        bar = document.createElement('div');
        bar.id = 'selection-bar';
        bar.className = 'selection-bar';
        bar.innerHTML = `
            <span class="selection-count">0 selected</span>
            <div class="selection-actions">
                <button data-action="play-selected">Play</button>
                <button data-action="add-to-queue-selected">Add to queue</button>
                <button data-action="add-to-playlist-selected">Add to playlist</button>
                <button data-action="download-selected">Download</button>
                <button data-action="like-selected">Like</button>
            </div>
            <button data-action="clear-selection" style="margin-left: 8px;">Clear</button>
            `;
        document.body.appendChild(bar);

        bar.querySelectorAll('button').forEach((btn) => {
            btn.addEventListener('click', () => handleSelectionAction(btn.dataset.action));
        });
    }

    const count = trackSelection.selectedIds.size;
    bar.querySelector('.selection-count').textContent = `${count} selected`;
    bar.classList.toggle('visible', count > 0);
}

async function handleSelectionAction(action) {
    const selectedIds = getSelectedTracks();
    if (selectedIds.length === 0) return;

    const mainContent = document.getElementById('main-content');
    const selectedTracks = [];
    mainContent.querySelectorAll('.track-item').forEach((item) => {
        if (trackSelection.selectedIds.has(item.dataset.trackId)) {
            const track = trackDataStore.get(item);
            if (track) selectedTracks.push(track);
        }
    });

    switch (action) {
        case 'play-selected':
            if (selectedTracks.length > 0) {
                Player.instance.setQueue(selectedTracks, 0);
                document.getElementById('shuffle-btn').classList.remove('active');
                Player.instance.playTrackFromQueue();
            }
            break;
        case 'add-to-queue-selected':
            if (selectedTracks.length > 0) {
                Player.instance.addToQueue(selectedTracks);
                if (window.renderQueueFunction) await window.renderQueueFunction();
                showNotification(`Added ${selectedTracks.length} tracks to queue`);
            }
            break;
        case 'add-to-playlist-selected':
            if (selectedTracks.length > 0) {
                await showMultiSelectPlaylistModal(selectedTracks);
            }
            break;
        case 'download-selected':
            if (selectedTracks.length > 0) {
                showNotification(`Downloading ${selectedTracks.length} tracks`);
                for (const track of selectedTracks) {
                    await downloadTrackWithMetadata(
                        track,
                        downloadQualitySettings.getQuality(),
                        MusicAPI.instance.tidalAPI,
                        LyricsManager.instance
                    );
                }
            }
            break;
        case 'like-selected':
            for (const track of selectedTracks) {
                const added = await db.toggleFavorite('track', track);
                await syncManager.syncLibraryItem('track', track, added);
            }
            showNotification(`Liked ${selectedTracks.length} tracks`);
            break;
        case 'clear-selection':
            clearSelection();
            break;
    }
}

export async function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
    if (homeStartRadioBtn) {
        homeStartRadioBtn.addEventListener('click', async () => {
            await player.enableRadio();
        });
    }

    const sleepTimerBtnMobile = document.getElementById('sleep-timer-btn');

    let historyLoggedTrackId = null;

    const { listeningTracker } = await import('./listening-tracker.js');

    let _previousTrackId = null;
    let _trackPlayStartTime = null;

    const setupMediaListeners = (element) => {
        element.addEventListener('loadstart', () => {
            if (player.activeElement === element) {
                historyLoggedTrackId = null;
            }
        });

        element.addEventListener('play', async () => {
            if (player.activeElement !== element) return;

            if (!audioContextManager.isReady()) {
                audioContextManager.init(element);
            }
            await audioContextManager.resume();

            if (player.currentTrack) {
                const currentId = player.currentTrack.id;
                if (currentId !== _previousTrackId) {
                    if (_previousTrackId !== null) {
                        const prevSignal = listeningTracker.getSessionSignals();
                        const prevPlayTime = prevSignal.accumulatedPlayTime || 0;
                        const prevDuration = prevSignal.trackDuration || 0;
                        listeningTracker.onSkip();
                        const prevTrack =
                            player.getCurrentQueue()[player.currentQueueIndex - 1] ||
                            player.getCurrentQueue().find((t) => t.id === _previousTrackId);
                        if (prevTrack && prevPlayTime > 0) {
                            listeningTracker.updateArtistAffinity(prevTrack, prevPlayTime, prevDuration, true);
                        }
                        listeningTracker.forceFlush();
                    }
                    _previousTrackId = currentId;
                    listeningTracker.onTrackStart(player.currentTrack);
                    _trackPlayStartTime = Date.now();
                }

                if (scrobbler.isAuthenticated()) {
                    scrobbler.updateNowPlaying(player.currentTrack);
                }

                await updateWaveform();
            }

            playPauseBtn.innerHTML = SVG_PAUSE(20);
            player.updateMediaSessionPlaybackState();
            player.updateMediaSessionPositionState();
            updateTabTitle(player);
        });

        element.addEventListener('playing', () => {
            if (player.activeElement !== element) return;
            player.updateMediaSessionPlaybackState();
            player.updateMediaSessionPositionState();
        });

        element.addEventListener('pause', () => {
            if (player.activeElement !== element) return;
            playPauseBtn.innerHTML = SVG_PLAY(20);
            player.updateMediaSessionPlaybackState();
            player.updateMediaSessionPositionState();
        });

        element.addEventListener('ended', () => {
            if (player.activeElement !== element) return;
            const elapsedPlayTime = listeningTracker.getSessionSignals().accumulatedPlayTime || 0;
            const trackDur = listeningTracker.getSessionSignals().trackDuration || 0;
            listeningTracker.onTrackEnd();
            if (player.currentTrack) {
                const effectivePlayTime = elapsedPlayTime || (Date.now() - _trackPlayStartTime) / 1000;
                listeningTracker.updateArtistAffinity(player.currentTrack, effectivePlayTime, trackDur, false);
            }
            listeningTracker.forceFlush();
            _previousTrackId = null;
            player.playNext();
        });

        element.addEventListener('timeupdate', async () => {
            if (player.activeElement !== element) return;

            const { currentTime, duration } = element;
            if (duration) {
                const progressFill = document.getElementById('progress-fill');
                const currentTimeEl = document.getElementById('current-time');
                progressFill.style.width = `${(currentTime / duration) * 100}%`;
                currentTimeEl.textContent = formatTime(currentTime);

                listeningTracker.onTimeUpdate(currentTime, duration);

                if (currentTime >= 10 && player.currentTrack && player.currentTrack.id !== historyLoggedTrackId) {
                    historyLoggedTrackId = player.currentTrack.id;
                    const historyEntry = await db.addToHistory(player.currentTrack);
                    await syncManager.syncHistoryItem(historyEntry);

                    if (window.location.hash === '#recent') {
                        ui.renderRecentPage();
                    }
                }
            }
        });

        element.addEventListener('loadedmetadata', () => {
            if (player.activeElement !== element) return;
            const totalDurationEl = document.getElementById('total-duration');
            totalDurationEl.textContent = formatTime(element.duration);
            player.updateMediaSessionPositionState();
        });

        element.addEventListener('error', (e) => {
            if (player.activeElement !== element) return;

            if (!element.src) return;

            const error = element.error;
            let errorMsg = 'Unknown error';
            if (error) {
                switch (error.code) {
                    case 1:
                        errorMsg = 'Playback aborted';
                        break;
                    case 2:
                        errorMsg = 'Network error';
                        break;
                    case 3:
                        errorMsg = 'Decoding error';
                        break;
                    case 4:
                        errorMsg = 'Source not supported';
                        break;
                }
                if (error.message) errorMsg += `: ${error.message}`;
            }

            console.error(`Media playback error (${element.id}):`, errorMsg, e);
            playPauseBtn.innerHTML = SVG_PLAY(20);

            const canFallback =
                player.quality === 'HI_RES_LOSSLESS' &&
                errorMsg.includes('Source not supported') &&
                errorMsg.includes('0x80004005') &&
                !player.isFallbackRetry;

            if (canFallback) {
                console.warn('Hi-Res failed due to DASH.js Error (FUCK DASH)');
            }

            if (player.currentTrack && error && error.code !== 1) {
                if (player.isFallbackInProgress || canFallback) {
                    return;
                }
            }
        });

        element.addEventListener('volumechange', () => {
            if (player.activeElement === element) {
                updateVolumeUI();
            }
        });
    };

    window.addEventListener('volume-change', updateVolumeUI);

    setupMediaListeners(audioPlayer);
    if (player.video) {
        setupMediaListeners(player.video);
    }

    playPauseBtn.addEventListener('click', async () => {
        await hapticMedium();
        player.handlePlayPause();
    });
    nextBtn.addEventListener('click', async () => {
        await hapticMedium();
        player.playNext();
    });
    prevBtn.addEventListener('click', async () => {
        await hapticMedium();
        player.playPrev();
    });

    shuffleBtn.addEventListener('click', async () => {
        await hapticLight();
        player.toggleShuffle();
        shuffleBtn.classList.toggle('active', player.shuffleActive);
        if (window.renderQueueFunction) await window.renderQueueFunction();
    });

    repeatBtn.addEventListener('click', async () => {
        await hapticLight();
        const mode = await player.toggleRepeat();
        repeatBtn.classList.toggle('active', mode !== REPEAT_MODE.OFF);
        repeatBtn.classList.toggle('repeat-one', mode === REPEAT_MODE.ONE);
        repeatBtn.title =
            mode === REPEAT_MODE.OFF ? 'Repeat' : mode === REPEAT_MODE.ALL ? 'Repeat Queue' : 'Repeat One';
    });

    window.addEventListener('radio-state-changed', (e) => {
        if (e.detail && e.detail.enabled) {
            showNotification('Infinite Radio Enabled');
        }
    });

    // Sleep Timer for desktop
    if (sleepTimerBtnDesktop) {
        sleepTimerBtnDesktop.addEventListener('click', () => {
            if (player.isSleepTimerActive()) {
                player.clearSleepTimer();
                showNotification('Sleep timer cancelled');
            } else {
                showSleepTimerModal(player);
            }
        });
    }

    // Sleep Timer for mobile
    if (sleepTimerBtnMobile) {
        sleepTimerBtnMobile.addEventListener('click', () => {
            if (player.isSleepTimerActive()) {
                player.clearSleepTimer();
                showNotification('Sleep timer cancelled');
            } else {
                showSleepTimerModal(player);
            }
        });
    }

    // Waveform Masking Logic
    const updateWaveform = async () => {
        const progressBar = document.getElementById('progress-bar');
        const playerControls = document.querySelector('.player-controls');

        const isTracker =
            player.currentTrack &&
            (player.currentTrack.isTracker ||
                (player.currentTrack.id && String(player.currentTrack.id).startsWith('tracker-')));

        if (!waveformSettings.isEnabled() || !player.currentTrack || isTracker) {
            if (progressBar) {
                progressBar.style.webkitMaskImage = '';
                progressBar.style.maskImage = '';
                progressBar.classList.remove('has-waveform', 'waveform-loaded');
            }
            if (playerControls) {
                playerControls.classList.remove('waveform-loaded');
            }
            currentTrackIdForWaveform = null;
            return;
        }

        if (progressBar && currentTrackIdForWaveform !== player.currentTrack.id) {
            currentTrackIdForWaveform = player.currentTrack.id;
            progressBar.classList.add('has-waveform');
            progressBar.classList.remove('waveform-loaded');
            if (playerControls) {
                playerControls.classList.remove('waveform-loaded');
            }

            // Clear current mask while loading
            progressBar.style.webkitMaskImage = '';
            progressBar.style.maskImage = '';

            try {
                const { url: streamUrl } = await player.api.getStreamUrl(player.currentTrack.id, 'LOW');
                const waveformData = await waveformGenerator.getWaveform(streamUrl, player.currentTrack.id);

                if (waveformData && currentTrackIdForWaveform === player.currentTrack.id) {
                    let { peaks, duration } = waveformData;
                    const trackDuration = player.currentTrack.duration;

                    // Padding logic for sync
                    if (trackDuration && duration && duration < trackDuration) {
                        const diff = trackDuration - duration;
                        if (diff > 0.5) {
                            // If difference is significant (> 500ms)
                            // Calculate how many peaks represent the missing time
                            // peaks.length represents 'duration'
                            // X peaks represent 'diff'
                            const peaksPerSecond = peaks.length / duration;
                            const paddingPeaksCount = Math.floor(diff * peaksPerSecond);

                            if (paddingPeaksCount > 0) {
                                const newPeaks = new Float32Array(peaks.length + paddingPeaksCount);
                                // Fill start with 0s (implied by new Float32Array)
                                newPeaks.set(peaks, paddingPeaksCount);
                                peaks = newPeaks;
                            }
                        }
                    }

                    // Create a temporary canvas to generate the mask
                    const canvas = document.createElement('canvas');
                    const rect = progressBar.getBoundingClientRect();
                    canvas.width = rect.width || 500;
                    canvas.height = 28; // Fixed height for mask generation

                    waveformGenerator.drawWaveform(canvas, peaks);

                    const dataUrl = canvas.toDataURL();
                    progressBar.style.webkitMaskImage = `url(${dataUrl})`;
                    progressBar.style.webkitMaskSize = '100% 100%';
                    progressBar.style.webkitMaskRepeat = 'no-repeat';
                    progressBar.style.maskImage = `url(${dataUrl})`;
                    progressBar.style.maskSize = '100% 100%';
                    progressBar.style.maskRepeat = 'no-repeat';

                    progressBar.classList.add('waveform-loaded');
                    if (playerControls) {
                        playerControls.classList.add('waveform-loaded');
                    }
                }
            } catch (e) {
                console.error('Failed to load waveform mask:', e);
            }
        }
    };

    window.addEventListener('waveform-toggle', async (e) => {
        if (!e.detail.enabled) {
            const progressBar = document.getElementById('progress-bar');
            const playerControls = document.querySelector('.player-controls');
            if (progressBar) {
                progressBar.style.webkitMaskImage = '';
                progressBar.style.maskImage = '';
                progressBar.classList.remove('has-waveform', 'waveform-loaded');
            }
            if (playerControls) {
                playerControls.classList.remove('waveform-loaded');
            }
        }
        await updateWaveform();
    });

    if (volumeBtn) {
        volumeBtn.addEventListener('click', () => {
            const activeEl = player.activeElement;
            activeEl.muted = !activeEl.muted;
            localStorage.setItem('muted', activeEl.muted);

            const inactiveEl = player.currentTrack?.type === 'video' ? player.audio : player.video;
            if (inactiveEl) inactiveEl.muted = activeEl.muted;

            updateVolumeUI();
        });
    }
    const isMuted = localStorage.getItem('muted') === 'true';
    audioPlayer.muted = isMuted;
    if (player.video) player.video.muted = isMuted;
    updateVolumeUI();

    initializeSmoothSliders(player);
}

function initializeSmoothSliders(player) {
    const progressBar = document.getElementById('progress-bar');
    const progressFill = document.getElementById('progress-fill');
    const currentTimeEl = document.getElementById('current-time');
    const volumeBar = document.getElementById('volume-bar');
    const volumeFill = document.getElementById('volume-fill');
    const volumeBtn = document.getElementById('volume-btn');

    let isSeeking = false;
    let wasPlaying = false;
    let isAdjustingVolume = false;
    let lastSeekPosition = 0;

    const seek = (bar, event, setter) => {
        const rect = bar.getBoundingClientRect();
        const position = Math.max(0, Math.min(1, (event.clientX - rect.left) / rect.width));
        setter(position);
    };

    const updateSeekUI = (position) => {
        const activeEl = player.activeElement;
        if (!isNaN(activeEl.duration)) {
            progressFill.style.width = `${position * 100}%`;
            if (currentTimeEl) {
                currentTimeEl.textContent = formatTime(position * activeEl.duration);
            }
        }
    };

    // Progress bar with smooth dragging
    progressBar.addEventListener('mousedown', (e) => {
        const activeEl = player.activeElement;
        isSeeking = true;
        wasPlaying = !activeEl.paused;
        if (wasPlaying) activeEl.pause();

        seek(progressBar, e, (position) => {
            lastSeekPosition = position;
            updateSeekUI(position);
        });
    });

    // Touch events for mobile
    progressBar.addEventListener('touchstart', (e) => {
        const activeEl = player.activeElement;
        e.preventDefault();
        isSeeking = true;
        wasPlaying = !activeEl.paused;
        if (wasPlaying) activeEl.pause();

        const touch = e.touches[0];
        const rect = progressBar.getBoundingClientRect();
        const position = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width));

        lastSeekPosition = position;
        updateSeekUI(position);
    });

    document.addEventListener('mousemove', (e) => {
        if (isSeeking) {
            seek(progressBar, e, (position) => {
                lastSeekPosition = position;
                updateSeekUI(position);
            });
        }

        if (isAdjustingVolume) {
            seek(volumeBar, e, (position) => {
                const activeEl = player.activeElement;
                if (activeEl.muted) {
                    activeEl.muted = false;
                    localStorage.setItem('muted', false);

                    const inactiveEl = player.currentTrack?.type === 'video' ? player.audio : player.video;
                    if (inactiveEl) inactiveEl.muted = false;
                }
                player.setVolume(position);
                volumeFill.style.width = `${position * 100}%`;
                volumeBar.style.setProperty('--volume-level', `${position * 100}%`);
            });
        }
    });

    document.addEventListener('touchmove', (e) => {
        if (isSeeking) {
            const touch = e.touches[0];
            const rect = progressBar.getBoundingClientRect();
            const position = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width));

            lastSeekPosition = position;
            updateSeekUI(position);
        }

        if (isAdjustingVolume) {
            const touch = e.touches[0];
            const rect = volumeBar.getBoundingClientRect();
            const position = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width));
            const activeEl = player.activeElement;
            if (activeEl.muted) {
                activeEl.muted = false;
                localStorage.setItem('muted', false);

                const inactiveEl = player.currentTrack?.type === 'video' ? player.audio : player.video;
                if (inactiveEl) inactiveEl.muted = false;
            }
            player.setVolume(position);
            volumeFill.style.width = `${position * 100}%`;
            volumeBar.style.setProperty('--volume-level', `${position * 100}%`);
        }
    });

    document.addEventListener('mouseup', () => {
        if (isSeeking) {
            const activeEl = player.activeElement;
            // Commit the seek
            if (!isNaN(activeEl.duration)) {
                activeEl.currentTime = lastSeekPosition * activeEl.duration;
                player.updateMediaSessionPositionState();
                if (wasPlaying) activeEl.play();
            }
            isSeeking = false;
        }

        if (isAdjustingVolume) {
            isAdjustingVolume = false;
        }
    });

    document.addEventListener('touchend', () => {
        if (isSeeking) {
            const activeEl = player.activeElement;
            if (!isNaN(activeEl.duration)) {
                activeEl.currentTime = lastSeekPosition * activeEl.duration;
                player.updateMediaSessionPositionState();
                if (wasPlaying) activeEl.play();
            }
            isSeeking = false;
        }

        if (isAdjustingVolume) {
            isAdjustingVolume = false;
        }
    });

    progressBar.addEventListener('click', (e) => {
        if (!isSeeking) {
            const activeEl = player.activeElement;
            // Only handle click if not result of a drag release
            seek(progressBar, e, (position) => {
                if (!isNaN(activeEl.duration) && activeEl.duration > 0 && activeEl.duration !== Infinity) {
                    activeEl.currentTime = position * activeEl.duration;
                    player.updateMediaSessionPositionState();
                } else if (player.currentTrack && player.currentTrack.duration) {
                    const targetTime = position * player.currentTrack.duration;
                    const progressFill = document.querySelector('.progress-fill');
                    if (progressFill) progressFill.style.width = `${position * 100}%`;
                    player.playTrackFromQueue(targetTime);
                }
            });
        }
    });

    volumeBar.addEventListener('mousedown', (e) => {
        isAdjustingVolume = true;
        seek(volumeBar, e, (position) => {
            const activeEl = player.activeElement;
            if (activeEl.muted) {
                activeEl.muted = false;
                localStorage.setItem('muted', false);

                const inactiveEl = player.currentTrack?.type === 'video' ? player.audio : player.video;
                if (inactiveEl) inactiveEl.muted = false;
            }
            player.setVolume(position);
            volumeFill.style.width = `${position * 100}%`;
            volumeBar.style.setProperty('--volume-level', `${position * 100}%`);
        });
    });

    volumeBar.addEventListener('touchstart', (e) => {
        e.preventDefault();
        isAdjustingVolume = true;
        const touch = e.touches[0];
        const rect = volumeBar.getBoundingClientRect();
        const position = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width));
        const activeEl = player.activeElement;
        if (activeEl.muted) {
            activeEl.muted = false;
            localStorage.setItem('muted', false);

            const inactiveEl = player.currentTrack?.type === 'video' ? player.audio : player.video;
            if (inactiveEl) inactiveEl.muted = false;
        }
        player.setVolume(position);
        volumeFill.style.width = `${position * 100}%`;
        volumeBar.style.setProperty('--volume-level', `${position * 100}%`);
    });

    volumeBar.addEventListener('click', (e) => {
        if (!isAdjustingVolume) {
            seek(volumeBar, e, (position) => {
                const activeEl = player.activeElement;
                if (activeEl.muted) {
                    activeEl.muted = false;
                    localStorage.setItem('muted', false);

                    const inactiveEl = player.currentTrack?.type === 'video' ? player.audio : player.video;
                    if (inactiveEl) inactiveEl.muted = false;
                }
                player.setVolume(position);
                volumeFill.style.width = `${position * 100}%`;
                volumeBar.style.setProperty('--volume-level', `${position * 100}%`);
            });
        }
    });
    volumeBar.addEventListener(
        'wheel',
        (e) => {
            e.preventDefault();
            const delta = e.deltaY > 0 ? -0.05 : 0.05;
            const newVolume = Math.max(0, Math.min(1, player.userVolume + delta));
            const activeEl = player.activeElement;

            if (delta > 0 && activeEl.muted) {
                activeEl.muted = false;
                localStorage.setItem('muted', false);

                const inactiveEl = player.currentTrack?.type === 'video' ? player.audio : player.video;
                if (inactiveEl) inactiveEl.muted = false;
            }

            player.setVolume(newVolume);
            volumeFill.style.width = `${newVolume * 100}%`;
            volumeBar.style.setProperty('--volume-level', `${newVolume * 100}%`);
        },
        { passive: false }
    );

    volumeBtn?.addEventListener(
        'wheel',
        (e) => {
            e.preventDefault();
            const delta = e.deltaY > 0 ? -0.05 : 0.05;
            const newVolume = Math.max(0, Math.min(1, player.userVolume + delta));
            const activeEl = player.activeElement;

            if (delta > 0 && activeEl.muted) {
                activeEl.muted = false;
                localStorage.setItem('muted', false);

                const inactiveEl = player.currentTrack?.type === 'video' ? player.audio : player.video;
                if (inactiveEl) inactiveEl.muted = false;
            }

            player.setVolume(newVolume);
            volumeFill.style.width = `${newVolume * 100}%`;
            volumeBar.style.setProperty('--volume-level', `${newVolume * 100}%`);
        },
        { passive: false }
    );
}

// Standalone function to show add to playlist modal
export async function showAddToPlaylistModal(track) {
    const modal = document.getElementById('playlist-select-modal');
    const list = document.getElementById('playlist-select-list');
    const cancelBtn = document.getElementById('playlist-select-cancel');
    const overlay = modal.querySelector('.modal-overlay');

    const renderModal = async () => {
        const playlists = await db.getPlaylists(true);

        const trackId = track.id;
        const playlistsWithTrack = new Set();

        for (const playlist of playlists) {
            if (playlist.tracks && playlist.tracks.some((t) => t.id == trackId)) {
                playlistsWithTrack.add(playlist.id);
            }
        }

        list.innerHTML =
            `
            <div class="modal-option create-new-option" style="border-bottom: 1px solid var(--border); margin-bottom: 0.5rem;">
                <span style="font-weight: 600; color: var(--primary);">+ Create New Playlist</span>
            </div>
        ` +
            playlists
                .map((p) => {
                    const alreadyContains = playlistsWithTrack.has(p.id);
                    return `
                <div class="modal-option ${alreadyContains ? 'already-contains' : ''}" data-id="${p.id}">
                    <span>${p.name}</span>
                    ${
                        alreadyContains
                            ? `<button class="remove-from-playlist-btn-modal" title="Remove from playlist" style="background: transparent; border: none; color: inherit; cursor: pointer; padding: 4px; display: flex; align-items: center;">${SVG_BIN(20)}</button>`
                            : ''
                    }
                </div>
            `;
                })
                .join('');
        return true;
    };

    if (!(await renderModal())) return;

    const closeModal = () => {
        modal.classList.remove('active');
        cleanup();
    };

    const handleOptionClick = async (e) => {
        const removeBtn = e.target.closest('.remove-from-playlist-btn-modal');
        const option = e.target.closest('.modal-option');

        if (!option) return;

        if (option.classList.contains('create-new-option')) {
            closeModal();
            const createModal = document.getElementById('playlist-modal');
            document.getElementById('playlist-modal-title').textContent = 'Create Playlist';
            document.getElementById('playlist-name-input').value = '';
            document.getElementById('playlist-cover-input').value = '';
            document.getElementById('playlist-cover-file-input').value = '';
            document.getElementById('playlist-description-input').value = '';
            createModal.dataset.editingId = '';
            document.getElementById('import-section').style.display = 'none';

            // Reset cover upload state
            const coverUploadBtn = document.getElementById('playlist-cover-upload-btn');
            const coverUrlInput = document.getElementById('playlist-cover-input');
            const coverToggleUrlBtn = document.getElementById('playlist-cover-toggle-url-btn');
            if (coverUploadBtn) {
                coverUploadBtn.style.flex = '1';
                coverUploadBtn.style.display = 'flex';
            }
            if (coverUrlInput) coverUrlInput.style.display = 'none';
            if (coverToggleUrlBtn) {
                coverToggleUrlBtn.textContent = 'or URL';
                coverToggleUrlBtn.title = 'Switch to URL input';
            }

            // Pass track
            createModal._pendingTracks = [track];

            createModal.classList.add('active');
            document.getElementById('playlist-name-input').focus();
            return;
        }

        const playlistId = option.dataset.id;

        if (removeBtn) {
            e.stopPropagation();
            await db.removeTrackFromPlaylist(playlistId, track.id);
            const updatedPlaylist = await db.getPlaylist(playlistId);
            await syncManager.syncUserPlaylist(updatedPlaylist, 'update');
            showNotification(`Removed from playlist: ${option.querySelector('span').textContent}`);
            await renderModal();
        } else {
            if (option.classList.contains('already-contains')) return;

            await db.addTrackToPlaylist(playlistId, track);
            const updatedPlaylist = await db.getPlaylist(playlistId);
            await syncManager.syncUserPlaylist(updatedPlaylist, 'update');
            showNotification(`Added to playlist: ${option.querySelector('span').textContent}`);
            closeModal();
        }
    };

    const cleanup = () => {
        cancelBtn.removeEventListener('click', closeModal);
        overlay.removeEventListener('click', closeModal);
        list.removeEventListener('click', handleOptionClick);
    };

    cancelBtn.addEventListener('click', closeModal);
    overlay.addEventListener('click', closeModal);
    list.addEventListener('click', handleOptionClick);

    modal.classList.add('active');
}

export async function handleTrackAction(
    action,
    item,
    player,
    api,
    lyricsManager,
    type = 'track',
    ui = null,
    scrobbler = null,
    extraData = null
) {
    if (!item) return;

    // Actions not allowed for unavailable tracks
    const forbiddenForUnavailable = [
        'add-to-queue',
        'play-next',
        'track-mix',
        'download',
        'start-radio',
        'start-infinite-radio',
    ];
    if (item.isUnavailable && forbiddenForUnavailable.includes(action)) {
        showNotification('This track is unavailable.');
        return;
    }

    if (action === 'request-song') {
        if (partyManager.currentParty) {
            await partyManager.requestSong(item);
        } else {
            showNotification('You are not in a listening party');
        }
        return;
    }

    if (action === 'start-radio' || action === 'start-infinite-radio') {
        let tracks = [];
        if (type === 'track') {
            tracks = [item];
        } else if (item.tracks) {
            tracks = item.tracks;
        } else if (type === 'album') {
            const data = await api.getAlbum(item.id);
            tracks = data.tracks;
        } else if (type === 'playlist') {
            const data = await api.getPlaylist(item.uuid);
            tracks = data.tracks;
        } else if (type === 'user-playlist') {
            const playlist = await db.getPlaylist(item.id);
            tracks = playlist ? playlist.tracks : [];
        }

        if (tracks.length > 0) {
            player.setQueue(tracks, 0);
            player.playAtIndex(0);
            player.enableRadio(tracks);
            showNotification(`Started radio based on ${type}: ${item.title || item.name}`);
        } else {
            showNotification('Could not start infinite radio: No tracks found');
        }
        return;
    }

    if (action === 'track-mix' && type === 'track') {
        if (item.mixes && item.mixes.TRACK_MIX) {
            navigate(`/mix/${item.mixes.TRACK_MIX}`);
        }
        return;
    }

    // Collection Actions (Album, Playlist, Mix)
    const isCollection = ['album', 'playlist', 'user-playlist', 'mix'].includes(type);
    const collectionActions = ['play-card', 'shuffle-play-card', 'add-to-queue', 'play-next', 'download', 'start-mix'];

    if (isCollection && collectionActions.includes(action)) {
        try {
            // Check if album/artist is blocked
            const { contentBlockingSettings } = await import('./storage.js');
            if (type === 'album' && contentBlockingSettings.shouldHideAlbum(item)) {
                showNotification('This album is blocked');
                return;
            }

            let tracks = [];
            let collectionItem = item;

            if (type === 'album') {
                const data = await api.getAlbum(item.id);
                tracks = data.tracks;
                collectionItem = data.album || item;
            } else if (type === 'playlist') {
                const data = await api.getPlaylist(item.uuid);
                tracks = data.tracks;
                collectionItem = data.playlist || item;
            } else if (type === 'user-playlist') {
                let playlist = await db.getPlaylist(item.id);
                if (!playlist) {
                    try {
                        playlist = await syncManager.getPublicPlaylist(item.id);
                    } catch {
                        /* ignore */
                    }
                }
                tracks = playlist ? playlist.tracks : item.tracks || [];
                collectionItem = playlist || item;
            } else if (type === 'mix') {
                const data = await api.getMix(item.id);
                tracks = data.tracks;
                collectionItem = data.mix || item;
            }

            if (tracks.length === 0 && action !== 'start-mix') {
                showNotification(`No tracks found in this ${type}`);
                return;
            }

            if (action === 'download') {
                if (type === 'album') {
                    await downloadAlbum(
                        collectionItem,
                        tracks,
                        api,
                        downloadQualitySettings.getQuality(),
                        lyricsManager
                    );
                } else {
                    await downloadPlaylist(
                        collectionItem,
                        tracks,
                        api,
                        downloadQualitySettings.getQuality(),
                        lyricsManager
                    );
                }
                return;
            }

            // Filter blocked tracks from collections
            tracks = contentBlockingSettings.filterTracks(tracks);

            if (action === 'add-to-queue') {
                player.addToQueue(tracks);
                if (window.renderQueueFunction) await window.renderQueueFunction();
                showNotification(`Added ${tracks.length} tracks to queue`);
                return;
            }

            if (action === 'play-next') {
                player.addNextToQueue(tracks);
                if (window.renderQueueFunction) await window.renderQueueFunction();
                showNotification(`Playing next: ${tracks.length} tracks`);
                return;
            }

            if (action === 'start-mix') {
                if (type === 'album' && collectionItem.artist?.id) {
                    const artistData = await api.getArtist(collectionItem.artist.id);
                    if (artistData.mixes?.ARTIST_MIX) {
                        navigate(`/mix/${artistData.mixes.ARTIST_MIX}`);
                        return;
                    }
                }
                // Fallback to item's own page or first track's mix
                if (tracks.length > 0 && tracks[0].mixes?.TRACK_MIX) {
                    navigate(`/mix/${tracks[0].mixes.TRACK_MIX}`);
                } else {
                    navigate(`/${type.replace('user-', '')}/${item.id || item.uuid}`);
                }
                return;
            }

            // play-card and shuffle-play-card
            if (action === 'shuffle-play-card') {
                player.shuffleActive = true;
                const tracksToShuffle = [...tracks];
                tracksToShuffle.sort(() => Math.random() - 0.5);
                player.setQueue(tracksToShuffle, 0);
                const shuffleBtn = document.getElementById('shuffle-btn');
                if (shuffleBtn) shuffleBtn.classList.add('active');
            } else {
                player.setQueue(tracks, 0);
                const shuffleBtn = document.getElementById('shuffle-btn');
                if (shuffleBtn) shuffleBtn.classList.remove('active');
            }
            player.playAtIndex(0);
            const name = type === 'user-playlist' ? collectionItem.name : collectionItem.title;
            showNotification(`Playing ${type.replace('user-', '')}: ${name}`);
        } catch (error) {
            console.error('Failed to handle collection action:', error);
            showNotification(`Failed to process ${type} action`);
        }
        return;
    }

    if (action === 'toggle-pin') {
        const pinned = await db.togglePinned(item, type);
        showNotification(pinned ? `Pinned to sidebar` : `Unpinned from sidebar`);

        if (ui && typeof ui.renderPinnedItems === 'function') {
            ui.renderPinnedItems();
        }
    }

    // Individual Track Actions
    // Check if track/artist is blocked
    const { contentBlockingSettings } = await import('./storage.js');
    const BLOCKED_PLAY_ACTIONS = new Set(['play-card', 'add-to-queue', 'play-next', 'start-mix']);
    if (type === 'track' && BLOCKED_PLAY_ACTIONS.has(action) && contentBlockingSettings.shouldHideTrack(item)) {
        showNotification('This track is blocked');
        return;
    }

    if (action === 'add-to-queue') {
        player.addToQueue(item);
        if (window.renderQueueFunction) await window.renderQueueFunction();
        showNotification(`Added to queue: ${item.title}`);
    } else if (action === 'play-next') {
        player.addNextToQueue(item);
        if (window.renderQueueFunction) await window.renderQueueFunction();
        showNotification(`Playing next: ${item.title}`);
    } else if (action === 'play-card') {
        player.setQueue([item], 0);
        player.playAtIndex(0);
        showNotification(`Playing track: ${item.title}`);
    } else if (action === 'start-mix') {
        if (item.mixes?.TRACK_MIX) {
            navigate(`/mix/${item.mixes.TRACK_MIX}`);
        } else {
            showNotification('No mix available for this track');
        }
    } else if (action === 'download') {
        await downloadTrackWithMetadata(item, downloadQualitySettings.getQuality(), api, lyricsManager);
    } else if (action === 'toggle-like') {
        const added = await db.toggleFavorite(type, item);
        await syncManager.syncLibraryItem(type, item, added);

        if (added && type === 'track' && scrobbler) {
            if (lastFMStorage.isEnabled() && lastFMStorage.shouldLoveOnLike()) {
                scrobbler.loveTrack(item);
            }
            if (libreFmSettings.isEnabled() && libreFmSettings.shouldLoveOnLike()) {
                scrobbler.loveTrack(item);
            }
            if (listenBrainzSettings.isEnabled() && listenBrainzSettings.shouldLoveOnLike()) {
                scrobbler.loveTrack(item);
            }
        }

        // Update all instances of this item's like button on the page
        const id = type === 'playlist' ? item.uuid : item.id;
        const selector =
            type === 'track'
                ? `[data-track-id="${id}"] .like-btn`
                : type === 'video'
                  ? `.card[data-video-id="${id}"] .like-btn`
                  : `.card[data-${type}-id="${id}"] .like-btn, .card[data-playlist-id="${id}"] .like-btn`;

        // Also check header buttons
        const headerBtn = document.getElementById(`like-${type}-btn`);

        const elementsToUpdate = [...document.querySelectorAll(selector)];
        if (headerBtn) elementsToUpdate.push(headerBtn);

        const nowPlayingLikeBtn = document.getElementById('now-playing-like-btn');
        if (nowPlayingLikeBtn && (type === 'track' || type === 'video') && player?.currentTrack?.id === item.id) {
            elementsToUpdate.push(nowPlayingLikeBtn);
        }

        const fsLikeBtn = document.getElementById('fs-like-btn');
        if (fsLikeBtn && (type === 'track' || type === 'video') && player?.currentTrack?.id === item.id) {
            elementsToUpdate.push(fsLikeBtn);
        }

        elementsToUpdate.forEach((btn) => {
            const heartIcon = btn.querySelector('svg');
            if (heartIcon) {
                heartIcon.classList.toggle('filled', added);
                if (heartIcon.hasAttribute('fill')) {
                    heartIcon.setAttribute('fill', added ? 'currentColor' : 'none');
                }
            }
            btn.classList.toggle('active', added);
            btn.title = added ? 'Remove from Favorites' : 'Add to Favorites';
        });

        // Handle Library Page Update
        if (window.location.pathname.split('/').filter(Boolean)[0] === 'library') {
            const itemSelector =
                type === 'track'
                    ? `.track-item[data-track-id="${id}"], .card[data-track-id="${id}"]`
                    : type === 'video'
                      ? `.video-card[data-video-id="${id}"]`
                      : `.card[data-${type}-id="${id}"], .card[data-playlist-id="${id}"]`;

            const itemEl = document.querySelector(itemSelector);

            if (!added && itemEl) {
                // Remove item
                const container = itemEl.parentElement;
                itemEl.remove();
                if (container && container.children.length === 0) {
                    const msg =
                        type === 'track'
                            ? 'No liked tracks yet.'
                            : type === 'video'
                              ? 'No liked videos yet.'
                              : `No liked ${type}s yet.`;
                    container.innerHTML = `<div class="placeholder-text">${msg}</div>`;
                }
            } else if (added && !itemEl && ui && (type === 'track' || type === 'video')) {
                // Add item
                if (type === 'track') {
                    const tracksContainer = document.getElementById('library-tracks-container');
                    if (tracksContainer) {
                        const placeholder = tracksContainer.querySelector('.placeholder-text');
                        if (placeholder) placeholder.remove();

                        const layout = localStorage.getItem('libraryLikedTracksView') || 'list';
                        const tempDiv = document.createElement('div');
                        if (layout === 'grid') {
                            tracksContainer.classList.remove('track-list');
                            tracksContainer.classList.add('card-grid');
                            tempDiv.innerHTML = ui.createTrackCardHTML(item);
                        } else {
                            tracksContainer.classList.remove('card-grid');
                            tracksContainer.classList.add('track-list');
                            const index = tracksContainer.children.length;
                            tempDiv.innerHTML = ui.createTrackItemHTML(item, index, true, false, false, true);
                        }
                        const newEl = tempDiv.firstElementChild;

                        if (newEl) {
                            tracksContainer.appendChild(newEl);
                            trackDataStore.set(newEl, item);
                            ui.updateLikeState(newEl, 'track', item.id);
                            const likedToolbar = document.getElementById('library-liked-tracks-toolbar');
                            if (likedToolbar) likedToolbar.style.display = 'flex';
                            const shuffleBtn = document.getElementById('shuffle-liked-tracks-btn');
                            const downloadBtn = document.getElementById('download-liked-tracks-btn');
                            if (shuffleBtn) shuffleBtn.style.display = 'flex';
                            if (downloadBtn) downloadBtn.style.display = 'flex';
                            ui.setupLibraryLikedTracksSearch(tracksContainer);
                        }
                    }
                } else if (type === 'video') {
                    const videosTabContent = document.getElementById('library-tab-videos');
                    if (videosTabContent) {
                        const grid = videosTabContent.querySelector('.card-grid');
                        if (grid) {
                            const placeholder = grid.querySelector('.placeholder-text');
                            if (placeholder) grid.innerHTML = '';

                            const videoHTML = ui.createVideoCardHTML(item);
                            const tempDiv = document.createElement('div');
                            tempDiv.innerHTML = videoHTML;
                            const newEl = tempDiv.firstElementChild;

                            if (newEl) {
                                grid.appendChild(newEl);
                                trackDataStore.set(newEl, item);
                                ui.updateLikeState(newEl, 'video', item.id);
                                newEl.addEventListener('click', (e) => {
                                    if (
                                        e.target.closest('.card-play-btn') ||
                                        e.target.closest('.card-image-container')
                                    ) {
                                        e.stopPropagation();
                                        player.playVideo(item);
                                    }
                                });
                            }
                        }
                    }
                }
            }
        }
    } else if (action === 'add-to-playlist') {
        const modal = document.getElementById('playlist-select-modal');
        const list = document.getElementById('playlist-select-list');
        const cancelBtn = document.getElementById('playlist-select-cancel');
        const overlay = modal.querySelector('.modal-overlay');

        const renderModal = async () => {
            const playlists = await db.getPlaylists(true);
            // Removed empty check to allow creating new playlist

            const trackId = item.id;
            const trackType = item.type || 'track';
            const playlistsWithTrack = new Set();

            for (const playlist of playlists) {
                if (
                    playlist.tracks &&
                    playlist.tracks.some((t) => t.id == trackId && (t.type || 'track') === trackType)
                ) {
                    playlistsWithTrack.add(playlist.id);
                }
            }

            list.innerHTML =
                `
                <div class="modal-option create-new-option" style="border-bottom: 1px solid var(--border); margin-bottom: 0.5rem;">
                    <span style="font-weight: 600; color: var(--primary);">+ Create New Playlist</span>
                </div>
            ` +
                playlists
                    .map((p) => {
                        const alreadyContains = playlistsWithTrack.has(p.id);
                        return `
                    <div class="modal-option ${alreadyContains ? 'already-contains' : ''}" data-id="${p.id}">
                        <span>${p.name}</span>
                        ${
                            alreadyContains
                                ? `<button class="remove-from-playlist-btn-modal" title="Remove from playlist" style="background: transparent; border: none; color: inherit; cursor: pointer; padding: 4px; display: flex; align-items: center;">${SVG_BIN(20)}</button>`
                                : ''
                        }
                    </div>
                `;
                    })
                    .join('');
            return true;
        };

        if (!(await renderModal())) return;

        const closeModal = () => {
            modal.classList.remove('active');
            cleanup();
        };

        const handleOptionClick = async (e) => {
            const removeBtn = e.target.closest('.remove-from-playlist-btn-modal');
            const option = e.target.closest('.modal-option');

            if (!option) return;

            if (option.classList.contains('create-new-option')) {
                closeModal();
                const createModal = document.getElementById('playlist-modal');
                document.getElementById('playlist-modal-title').textContent = 'Create Playlist';
                document.getElementById('playlist-name-input').value = '';
                document.getElementById('playlist-cover-input').value = '';
                document.getElementById('playlist-cover-file-input').value = '';
                document.getElementById('playlist-description-input').value = '';
                createModal.dataset.editingId = '';
                document.getElementById('import-section').style.display = 'none';

                // Reset cover upload state
                const coverUploadBtn = document.getElementById('playlist-cover-upload-btn');
                const coverUrlInput = document.getElementById('playlist-cover-input');
                const coverToggleUrlBtn = document.getElementById('playlist-cover-toggle-url-btn');
                if (coverUploadBtn) {
                    coverUploadBtn.style.flex = '1';
                    coverUploadBtn.style.display = 'flex';
                }
                if (coverUrlInput) coverUrlInput.style.display = 'none';
                if (coverToggleUrlBtn) {
                    coverToggleUrlBtn.textContent = 'or URL';
                    coverToggleUrlBtn.title = 'Switch to URL input';
                }

                // Pass track
                createModal._pendingTracks = [item];

                createModal.classList.add('active');
                document.getElementById('playlist-name-input').focus();
                return;
            }

            const playlistId = option.dataset.id;

            if (removeBtn) {
                e.stopPropagation();
                await db.removeTrackFromPlaylist(playlistId, item.id);
                const updatedPlaylist = await db.getPlaylist(playlistId);
                await syncManager.syncUserPlaylist(updatedPlaylist, 'update');
                showNotification(`Removed from playlist: ${option.querySelector('span').textContent}`);
                await renderModal();
            } else {
                if (option.classList.contains('already-contains')) return;

                await db.addTrackToPlaylist(playlistId, item);
                const updatedPlaylist = await db.getPlaylist(playlistId);
                await syncManager.syncUserPlaylist(updatedPlaylist, 'update');
                showNotification(`Added to playlist: ${option.querySelector('span').textContent}`);
                closeModal();
            }
        };

        const cleanup = () => {
            cancelBtn.removeEventListener('click', closeModal);
            overlay.removeEventListener('click', closeModal);
            list.removeEventListener('click', handleOptionClick);
        };

        cancelBtn.addEventListener('click', closeModal);
        overlay.addEventListener('click', closeModal);
        list.addEventListener('click', handleOptionClick);

        modal.classList.add('active');
    } else if (action === 'go-to-artist') {
        const artistId = extraData?.artistId || item.artist?.id || item.artists?.[0]?.id;
        const trackerSheetId = extraData?.trackerSheetId || (item.isTracker ? item.trackerInfo?.sheetId : null);

        if (trackerSheetId) {
            navigate(`/unreleased/${trackerSheetId}`);
        } else if (artistId) {
            navigate(`/artist/${artistId}`);
        }
    } else if (action === 'go-to-album') {
        if (item.album?.id) {
            navigate(`/album/${item.album.id}`);
        }
    } else if (action === 'copy-link' || action === 'share') {
        // Use stored href from card if available, otherwise construct URL
        const contextMenu = document.getElementById('context-menu');
        const storedHref = contextMenu?._contextHref;
        const typeForUrl = type === 'user-playlist' ? 'userplaylist' : type;
        const url = getShareUrl(storedHref ? storedHref : `/${typeForUrl}/${item.id || item.uuid}`);

        await navigator.clipboard
            .writeText(url)
            .then(() => {
                showNotification('Link copied to clipboard!');
            })
            .catch(console.error);
    } else if (action === 'open-in-new-tab') {
        // Use stored href from card if available, otherwise construct URL
        const contextMenu = document.getElementById('context-menu');
        const storedHref = contextMenu?._contextHref;
        const url = storedHref
            ? `${window.location.origin}${storedHref}`
            : `${window.location.origin}/${type}/${item.id || item.uuid}`;

        window.open(url, '_blank');
    } else if (action === 'open-in-harmony') {
        const albumId = item.id;
        const harmonyUrl = `https://harmony.pulsewidth.org.uk/release?url=${encodeURIComponent(`https://tidal.com/album/${albumId}`)}&gtin=&region=&musicbrainz=&deezer=&itunes=&spotify=&tidal=&beatport=`;
        window.open(harmonyUrl, '_blank');
    } else if (action === 'track-info') {
        // Show detailed track info modal
        const isTracker = item.isTracker;
        let infoHTML = '';

        if (isTracker && item.trackerInfo) {
            // Detailed unreleased/tracker track info
            const releaseDate = item.trackerInfo.releaseDate || item.streamStartDate;
            const dateDisplay = releaseDate ? new Date(releaseDate).toLocaleDateString() : 'Unknown';
            const addedDate = item.trackerInfo.addedDate
                ? new Date(item.trackerInfo.addedDate).toLocaleDateString()
                : 'Unknown';

            infoHTML = `
                <div style="padding: 1.5rem; max-width: 500px; max-height: 80vh; overflow-y: auto;">
                    <h3 style="margin-bottom: 1rem; font-size: 1.3rem; font-weight: 600;">${escapeHtml(item.title)}</h3>
                    <div style="color: var(--muted-foreground); font-size: 0.9rem; line-height: 1.8;">
                        <div style="margin-bottom: 1rem; padding: 0.75rem; background: var(--accent); border-radius: 8px;">
                            <p style="color: var(--primary); font-weight: 500;">Unreleased Track</p>
                        </div>

                        <div style="display: grid; gap: 0.5rem;">
                            ${item.artists ? `<p><strong style="color: var(--foreground);">Artist:</strong> ${escapeHtml(Array.isArray(item.artists) ? item.artists.map((a) => a.name || a).join(', ') : item.artists)}</p>` : ''}
                            ${item.trackerInfo.artist ? `<p><strong style="color: var(--foreground);">Tracked Artist:</strong> ${escapeHtml(item.trackerInfo.artist)}</p>` : ''}
                            ${item.trackerInfo.project ? `<p><strong style="color: var(--foreground);">Project:</strong> ${escapeHtml(item.trackerInfo.project)}</p>` : ''}
                            ${item.trackerInfo.era ? `<p><strong style="color: var(--foreground);">Era:</strong> ${escapeHtml(item.trackerInfo.era)}</p>` : ''}
                            ${item.trackerInfo.timeline ? `<p><strong style="color: var(--foreground);">Timeline:</strong> ${escapeHtml(item.trackerInfo.timeline)}</p>` : ''}
                            ${item.trackerInfo.category ? `<p><strong style="color: var(--foreground);">Category:</strong> ${escapeHtml(item.trackerInfo.category)}</p>` : ''}
                            ${item.trackerInfo.trackNumber ? `<p><strong style="color: var(--foreground);">Track Number:</strong> ${escapeHtml(String(item.trackerInfo.trackNumber))}</p>` : ''}
                            <p><strong style="color: var(--foreground);">Duration:</strong> ${escapeHtml(formatTime(item.duration))}</p>
                            ${releaseDate !== 'Unknown' ? `<p><strong style="color: var(--foreground);">Release Date:</strong> ${escapeHtml(dateDisplay)}</p>` : ''}
                            ${item.trackerInfo.addedDate ? `<p><strong style="color: var(--foreground);">Added to Tracker:</strong> ${escapeHtml(addedDate)}</p>` : ''}
                            ${item.trackerInfo.leakedDate ? `<p><strong style="color: var(--foreground);">Leak Date:</strong> ${escapeHtml(new Date(item.trackerInfo.leakedDate).toLocaleDateString())}</p>` : ''}
                            ${item.trackerInfo.recordingDate ? `<p><strong style="color: var(--foreground);">Recording Date:</strong> ${escapeHtml(new Date(item.trackerInfo.recordingDate).toLocaleDateString())}</p>` : ''}
                        </div>

                        ${
                            item.trackerInfo.description
                                ? `
                            <div style="margin-top: 1rem; padding: 0.75rem; background: var(--accent); border-radius: 8px;">
                                <p style="color: var(--foreground); font-weight: 500; margin-bottom: 0.5rem;">Description</p>
                                <p style="font-size: 0.85rem; line-height: 1.6;">${escapeHtml(item.trackerInfo.description)}</p>
                            </div>
                        `
                                : ''
                        }

                        ${
                            item.trackerInfo.notes
                                ? `
                            <div style="margin-top: 1rem; padding: 0.75rem; background: var(--accent); border-radius: 8px;">
                                <p style="color: var(--foreground); font-weight: 500; margin-bottom: 0.5rem;">Notes</p>
                                <p style="font-size: 0.85rem; line-height: 1.6;">${escapeHtml(item.trackerInfo.notes)}</p>
                            </div>
                        `
                                : ''
                        }

                        ${
                            item.trackerInfo.sourceUrl
                                ? `
                            <div style="margin-top: 1rem;">
                                <p style="margin-bottom: 0.5rem;"><strong style="color: var(--foreground);">Source URL:</strong></p>
                                <a href="${escapeHtml(item.trackerInfo.sourceUrl)}" target="_blank" style="color: var(--primary); word-break: break-all; font-size: 0.85rem; display: block; padding: 0.5rem; background: var(--accent); border-radius: 6px; text-decoration: none;">
                                    ${escapeHtml(item.trackerInfo.sourceUrl)}
                                </a>
                            </div>
                        `
                                : ''
                        }

                        ${item.id ? `<p style="margin-top: 1rem; font-size: 0.8rem; color: var(--muted);"><strong>Track ID:</strong> ${escapeHtml(item.id)}</p>` : ''}
                    </div>
                    <button class="btn-primary track-info-close-btn" style="margin-top: 1.5rem; width: 100%;">Close</button>
                </div>
            `;
        } else {
            // Detailed normal track info
            const releaseDate = item.album?.releaseDate || item.streamStartDate;
            const dateDisplay = releaseDate ? new Date(releaseDate).toLocaleDateString() : 'Unknown';
            const quality = item.audioQuality || 'Unknown';
            const bitrate = item.bitrate ? `${item.bitrate} kbps` : '';

            infoHTML = `
                <div style="padding: 1.5rem; max-width: 500px; max-height: 80vh; overflow-y: auto;">
                    <h3 style="margin-bottom: 1rem; font-size: 1.3rem; font-weight: 600;">${escapeHtml(item.title)}</h3>
                    <div style="color: var(--muted-foreground); font-size: 0.9rem; line-height: 1.8;">
                        <div style="display: grid; gap: 0.5rem;">
                            <p><strong style="color: var(--foreground);">Artist:</strong> ${escapeHtml(getTrackArtists(item))}</p>
                            <p><strong style="color: var(--foreground);">Album:</strong> ${escapeHtml(item.album?.title || 'Unknown')}</p>
                            ${item.album?.artist?.name ? `<p><strong style="color: var(--foreground);">Album Artist:</strong> ${escapeHtml(item.album.artist.name)}</p>` : ''}
                            <p><strong style="color: var(--foreground);">Release Date:</strong> ${escapeHtml(dateDisplay)}</p>
                            <p><strong style="color: var(--foreground);">Duration:</strong> ${escapeHtml(formatTime(item.duration))}</p>
                            ${item.trackNumber ? `<p><strong style="color: var(--foreground);">Track Number:</strong> ${escapeHtml(String(item.trackNumber))}</p>` : ''}
                            ${item.discNumber ? `<p><strong style="color: var(--foreground);">Disc Number:</strong> ${escapeHtml(String(item.discNumber))}</p>` : ''}
                            ${item.version ? `<p><strong style="color: var(--foreground);">Version:</strong> ${escapeHtml(item.version)}</p>` : ''}
                            ${item.explicit ? `<p><strong style="color: var(--foreground);">Explicit:</strong> Yes</p>` : ''}
                            <p><strong style="color: var(--foreground);">Quality:</strong> ${escapeHtml(quality)} ${bitrate ? `(${escapeHtml(bitrate)})` : ''}</p>
                        </div>

                        ${
                            item.credits && item.credits.length > 0
                                ? `
                            <div style="margin-top: 1rem; padding: 0.75rem; background: var(--accent); border-radius: 8px;">
                                <p style="color: var(--foreground); font-weight: 500; margin-bottom: 0.5rem;">Credits</p>
                                <div style="font-size: 0.85rem; line-height: 1.6;">
                                    ${item.credits.map((c) => `<p>${escapeHtml(c.type)}: ${escapeHtml(c.name)}</p>`).join('')}
                                </div>
                            </div>
                        `
                                : ''
                        }

                        ${
                            item.composers && item.composers.length > 0
                                ? `
                            <p style="margin-top: 0.5rem;"><strong style="color: var(--foreground);">Composers:</strong> ${escapeHtml(item.composers.map((c) => c.name).join(', '))}</p>
                        `
                                : ''
                        }

                        ${
                            item.lyrics?.text
                                ? `
                            <div style="margin-top: 1rem; padding: 0.75rem; background: var(--accent); border-radius: 8px;">
                                <p style="color: var(--foreground); font-weight: 500; margin-bottom: 0.5rem;">Has Lyrics</p>
                            </div>
                        `
                                : ''
                        }

                        ${item.id ? `<p style="margin-top: 1rem; font-size: 0.8rem; color: var(--muted);"><strong>Track ID:</strong> ${escapeHtml(item.id)}</p>` : ''}
                        ${item.album?.id ? `<p style="font-size: 0.8rem; color: var(--muted);"><strong>Album ID:</strong> ${escapeHtml(item.album.id)}</p>` : ''}
                    </div>
                    <button class="btn-primary track-info-close-btn" style="margin-top: 1.5rem; width: 100%;">Close</button>
                </div>
            `;
        }

        // Create and show modal
        const modal = document.createElement('div');
        modal.className = 'modal-overlay';
        modal.style.cssText =
            'position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.8); display: flex; align-items: center; justify-content: center; z-index: 10000;';
        modal.innerHTML = infoHTML;
        modal.onclick = (e) => {
            if (e.target === modal) modal.remove();
        };
        const closeBtn = modal.querySelector('.track-info-close-btn');
        if (closeBtn) {
            closeBtn.onclick = () => modal.remove();
        }
        document.body.appendChild(modal);
    } else if (action === 'open-original-url') {
        // Open the original source URL for the track
        let url = null;

        if (item.isTracker && item.trackerInfo && item.trackerInfo.sourceUrl) {
            url = item.trackerInfo.sourceUrl;
        } else if (item.remoteUrl) {
            url = item.remoteUrl;
        }

        if (url) {
            window.open(url, '_blank');
        } else {
            showNotification('No original URL available for this track.');
        }
    } else if (action === 'block-track') {
        const { contentBlockingSettings } = await import('./storage.js');
        if (contentBlockingSettings.isTrackBlocked(item.id)) {
            contentBlockingSettings.unblockTrack(item.id);
            showNotification(`Unblocked track: ${item.title}`);
        } else {
            contentBlockingSettings.blockTrack(item);
            showNotification(`Blocked track: ${item.title}`);
        }
    } else if (action === 'block-album') {
        const { contentBlockingSettings } = await import('./storage.js');
        const albumId = type === 'album' ? item.id : item.album?.id;
        const albumTitle = type === 'album' ? item.title || item.name : item.album?.title || item.album?.name;
        const albumArtist =
            type === 'album' ? item.artist?.name || item.artist : item.album?.artist?.name || item.album?.artist;

        if (!albumId) {
            showNotification('No album information available');
            return;
        }

        const albumObj = { id: albumId, title: albumTitle, artist: albumArtist };

        if (contentBlockingSettings.isAlbumBlocked(albumId)) {
            contentBlockingSettings.unblockAlbum(albumId);
            showNotification(`Unblocked album: ${albumTitle || 'Unknown Album'}`);
        } else {
            contentBlockingSettings.blockAlbum(albumObj);
            showNotification(`Blocked album: ${albumTitle || 'Unknown Album'}`);
        }
    } else if (action === 'block-artist') {
        const { contentBlockingSettings } = await import('./storage.js');
        const artistId = item.artist?.id || item.artists?.[0]?.id;
        const artistName = item.artist?.name || item.artists?.[0]?.name || item.name;

        if (!artistId) {
            showNotification('No artist information available');
            return;
        }

        const artistObj = { id: artistId, name: artistName };

        if (contentBlockingSettings.isArtistBlocked(artistId)) {
            contentBlockingSettings.unblockArtist(artistId);
            showNotification(`Unblocked artist: ${artistName || 'Unknown Artist'}`);
        } else {
            contentBlockingSettings.blockArtist(artistObj);
            showNotification(`Blocked artist: ${artistName || 'Unknown Artist'}`);
        }
    }
}

async function updateContextMenuLikeState(contextMenu, contextTrack) {
    if (!contextMenu || !contextTrack) return;

    const type = contextMenu._contextType || 'track';

    const likeItem = contextMenu.querySelector('li[data-action="toggle-like"]');
    let isLiked = false;
    if (likeItem) {
        const key = type === 'playlist' ? contextTrack.uuid : contextTrack.id;
        isLiked = await db.isFavorite(type, key);
    }

    const pinItem = contextMenu.querySelector('li[data-action="toggle-pin"]');
    if (pinItem) {
        const isPinned = await db.isPinned(contextTrack.id || contextTrack.uuid);
        pinItem.textContent = isPinned ? 'Unpin' : 'Pin';
    }

    const trackMixItem = contextMenu.querySelector('li[data-action="track-mix"]');
    if (trackMixItem) {
        const hasMix = contextTrack.mixes && contextTrack.mixes.TRACK_MIX;
        trackMixItem.style.display = hasMix ? 'block' : 'none';
    }

    // Show/hide "Open Original URL" only for unreleased/tracker tracks
    const openOriginalUrlItem = contextMenu.querySelector('li[data-action="open-original-url"]');
    if (openOriginalUrlItem) {
        const isUnreleased = contextTrack.isTracker || (contextTrack.trackerInfo && contextTrack.trackerInfo.sourceUrl);
        openOriginalUrlItem.style.display = isUnreleased ? 'block' : 'none';
    }

    // Update block/unblock labels
    const { contentBlockingSettings } = await import('./storage.js');

    const blockTrackItem = contextMenu.querySelector('li[data-action="block-track"]');
    if (blockTrackItem) {
        const isBlocked = contentBlockingSettings.isTrackBlocked(contextTrack.id);
        blockTrackItem.textContent = isBlocked
            ? blockTrackItem.dataset.labelUnblock || 'Unblock track'
            : blockTrackItem.dataset.labelBlock || 'Block track';
    }

    const blockAlbumItem = contextMenu.querySelector('li[data-action="block-album"]');
    if (blockAlbumItem) {
        const albumId = type === 'album' ? contextTrack.id : contextTrack.album?.id;
        const isBlocked = albumId ? contentBlockingSettings.isAlbumBlocked(albumId) : false;
        blockAlbumItem.textContent = isBlocked
            ? blockAlbumItem.dataset.labelUnblock || 'Unblock album'
            : blockAlbumItem.dataset.labelBlock || 'Block album';
    }

    const blockArtistItem = contextMenu.querySelector('li[data-action="block-artist"]');
    if (blockArtistItem) {
        const artistId = contextTrack.artist?.id || contextTrack.artists?.[0]?.id;
        const isBlocked = artistId ? contentBlockingSettings.isArtistBlocked(artistId) : false;
        blockArtistItem.textContent = isBlocked
            ? blockArtistItem.dataset.labelUnblock || 'Unblock artist'
            : blockArtistItem.dataset.labelBlock || 'Block artist';
    }

    // Filter items based on type
    contextMenu.querySelectorAll('li[data-action]').forEach((item) => {
        const filter = item.dataset.typeFilter;
        if (filter) {
            const types = filter.split(',');
            item.style.display = types.includes(type) ? 'block' : 'none';
        } else {
            item.style.display = 'block';
        }
        if (item.dataset.action === 'request-song') {
            if (!partyManager.currentParty) {
                item.style.display = 'none';
            }
        }

        // Update labels for Like/Save
        if (item.dataset.action === 'toggle-like') {
            const labelPrefix = isLiked ? 'labelUnlike' : 'label';
            const labelKey = `${labelPrefix}${type.charAt(0).toUpperCase() + type.slice(1).replace('User-playlist', 'Playlist')}`;
            const fallbackKey = isLiked ? 'labelUnlikeTrack' : 'labelTrack';
            const label = item.dataset[labelKey] || item.dataset[fallbackKey] || (isLiked ? 'Unlike' : 'Like');
            item.textContent = label;
        }
    });

    // Handle multiple artists for "Go to artist"
    const artistItem = contextMenu.querySelector('li[data-action="go-to-artist"]');
    if (artistItem) {
        const artists = Array.isArray(contextTrack.artists)
            ? contextTrack.artists
            : contextTrack.artist
              ? [contextTrack.artist]
              : [];
        const canShowArtist = type === 'track' || type === 'album';

        if (artists.length > 1 && canShowArtist) {
            artistItem.style.display = 'block';
            artistItem.textContent = 'Go to artists';
            artistItem.dataset.hasMultipleArtists = 'true';
        } else {
            const hasArtist = artists.length > 0;
            artistItem.style.display = hasArtist && canShowArtist ? 'block' : 'none';
            artistItem.dataset.hasMultipleArtists = 'false';
            artistItem.textContent = artists.length > 1 ? 'Go to artists' : 'Go to artist';
            delete artistItem.dataset.artistId;
            delete artistItem.dataset.trackerSheetId;
        }
    }
}

export function initializeTrackInteractions(player, api, mainContent, contextMenu, lyricsManager, ui, scrobbler) {
    let contextTrack = null;

    mainContent.addEventListener('touchstart', handleTrackTouchStart, { passive: true });
    mainContent.addEventListener('touchmove', handleTrackTouchMove, { passive: true });
    mainContent.addEventListener('touchend', handleTrackTouchEnd, { passive: true });

    mainContent.addEventListener('click', async (e) => {
        const actionBtn = e.target.closest('.track-action-btn, .like-btn, .play-btn');
        if (actionBtn && actionBtn.dataset.action) {
            e.preventDefault(); // Prevent card navigation
            e.stopPropagation();
            const itemElement = actionBtn.closest('.track-item, .card');
            const action = actionBtn.dataset.action;
            const type = actionBtn.dataset.type || 'track';

            let item = itemElement ? trackDataStore.get(itemElement) : trackDataStore.get(actionBtn);

            // If no item from element (e.g. header buttons), try to get from hash
            if (!item && action === 'toggle-like') {
                const id = window.location.pathname.split('/')[2];
                if (id) {
                    try {
                        if (type === 'album') {
                            const data = await api.getAlbum(id);
                            item = data.album;
                        } else if (type === 'artist') {
                            item = await api.getArtist(id);
                        } else if (type === 'playlist') {
                            const data = await api.getPlaylist(id);
                            item = data.playlist;
                        } else if (type === 'mix') {
                            const data = await api.getMix(id);
                            item = data.mix;
                        } else if (type === 'track') {
                            const data = await api.getTrack(id);
                            item = data.track;
                        }
                    } catch (err) {
                        console.error(err);
                    }
                }
            }

            if (item) {
                await handleTrackAction(action, item, player, api, lyricsManager, type, ui, scrobbler);
            }
            return;
        }

        const cardMenuBtn = e.target.closest('.card-menu-btn, #album-menu-btn');
        if (cardMenuBtn) {
            e.stopPropagation();
            const card = cardMenuBtn.closest('.card');
            const type = cardMenuBtn.dataset.type;
            const id = cardMenuBtn.dataset.id;

            let item = card ? trackDataStore.get(card) : null;

            if (!item) {
                // Check if item is stored on the button itself (e.g., album page header menu)
                item = trackDataStore.get(cardMenuBtn);
            }

            if (!item) {
                // Fallback: create a shell item
                item = { id, uuid: id, title: card?.querySelector('.card-title')?.textContent || 'Item' };
            }

            if (contextMenu._originalHTML) {
                contextMenu.innerHTML = contextMenu._originalHTML;
                contextMenu._originalHTML = null;
            }

            contextTrack = item;
            contextMenu._contextTrack = item;
            contextMenu._contextType = type;

            await updateContextMenuLikeState(contextMenu, item);
            const rect = cardMenuBtn.getBoundingClientRect();
            positionMenu(contextMenu, rect.left, rect.bottom + 5, rect);
            return;
        }

        const menuBtn = e.target.closest('.track-menu-btn');
        if (menuBtn) {
            e.stopPropagation();
            const trackItem = menuBtn.closest('.track-item');
            if (trackItem && !trackItem.dataset.queueIndex) {
                const clickedTrack = trackDataStore.get(trackItem);

                if (clickedTrack && clickedTrack.isLocal) return;

                if (
                    contextMenu.style.display === 'block' &&
                    contextTrack &&
                    clickedTrack &&
                    contextTrack.id === clickedTrack.id
                ) {
                    if (contextMenu._originalHTML) {
                        contextMenu.innerHTML = contextMenu._originalHTML;
                    }
                    contextMenu.style.display = 'none';
                    contextMenu._contextType = null;
                    contextMenu._originalHTML = null;
                    return;
                }

                contextTrack = clickedTrack;
                if (contextTrack) {
                    if (contextMenu._originalHTML) {
                        contextMenu.innerHTML = contextMenu._originalHTML;
                        contextMenu._originalHTML = null;
                    }
                    contextMenu._contextTrack = contextTrack;
                    contextMenu._contextType = menuBtn.dataset.type || trackItem.dataset.type || 'track';
                    if (trackSelection.isSelecting && trackSelection.selectedIds.size > 0) {
                        const selectedTracks = [];
                        document.querySelectorAll('.track-item.selected').forEach((item) => {
                            const track = trackDataStore.get(item);
                            if (track) selectedTracks.push(track);
                        });
                        contextMenu._selectedTracks = selectedTracks;
                    }
                    await updateContextMenuLikeState(contextMenu, contextTrack);
                    const rect = menuBtn.getBoundingClientRect();
                    positionMenu(contextMenu, rect.left, rect.bottom + 5, rect);
                }
            }
            return;
        }

        const checkbox = e.target.closest('.track-checkbox');
        if (checkbox) {
            e.stopPropagation();
            const trackItem = checkbox.closest('.track-item');
            if (trackItem) {
                toggleTrackSelection(trackItem, isMultiSelectToggle(e), isMultiSelectRange(e));
            }
            return;
        }

        const trackItem = e.target.closest('.track-item');
        if (trackItem && trackItem.classList.contains('unavailable')) {
            return;
        }
        if (isLongPress && longPressTrackItem === trackItem) {
            return;
        }
        if (
            trackItem &&
            !trackItem.classList.contains('blocked') &&
            !trackItem.dataset.queueIndex &&
            !e.target.closest('.remove-from-playlist-btn') &&
            !e.target.closest('.artist-link') &&
            !e.target.closest('.like-btn')
        ) {
            const clickedTrackId = trackItem.dataset.trackId;
            const isSearch = window.location.pathname.startsWith('/search/');

            if (isMultiSelectToggle(e)) {
                e.preventDefault();
                toggleTrackSelection(trackItem, true, isMultiSelectRange(e));
                return;
            }

            if (isMultiSelectRange(e) && trackSelection.isSelecting) {
                e.preventDefault();
                toggleTrackSelection(trackItem, false, true);
                return;
            }

            if (trackSelection.isSelecting) {
                return;
            }

            if (isSearch) {
                const clickedTrack = trackDataStore.get(trackItem);
                if (clickedTrack) {
                    if (trackItem.dataset.type === 'video') {
                        player.playVideo(clickedTrack);
                    } else {
                        player.setQueue([clickedTrack], 0);
                        player.enableAutoplay();
                        document.getElementById('shuffle-btn').classList.remove('active');
                        player.playTrackFromQueue();

                        const { autoplaySettings } = await import('./storage.js');
                        const fetchRecs = autoplaySettings.isSmartRecsEnabled()
                            ? (async () => {
                                  const { smartRecommendations } = await import('./smart-recommendations.js');
                                  const recs = await api.getTrackRecommendations(clickedTrack.id);
                                  if (recs && recs.length > 0) {
                                      const filtered = smartRecommendations.filterRecommendations(recs);
                                      const ranked = smartRecommendations.rankRecommendations(filtered);
                                      return ranked;
                                  }
                                  return [];
                              })()
                            : api.getTrackRecommendations(clickedTrack.id);

                        fetchRecs.then((recs) => {
                            if (recs && recs.length > 0) {
                                player.addToQueue(recs);
                            }
                        });
                    }
                }
            } else {
                const parentList = trackItem.closest('.track-list');
                const allTrackElements = Array.from(parentList.querySelectorAll('.track-item'));
                const trackList = allTrackElements.map((el) => trackDataStore.get(el)).filter(Boolean);

                if (trackList.length > 0) {
                    const startIndex = trackList.findIndex((t) => t.id == clickedTrackId);

                    player.setQueue(trackList, startIndex);
                    player.enableAutoplay();

                    if (ui.currentPage === 'artist' && ui.currentArtistId) {
                        player.setArtistPopularTracksContext(ui.currentArtistId, trackList, trackList.length, true);
                    }

                    document.getElementById('shuffle-btn').classList.remove('active');
                    player.playTrackFromQueue();
                }
            }
        }

        // Handle artist link clicks in track lists
        const artistLink = e.target.closest('.artist-link');
        if (artistLink) {
            e.stopPropagation();
            const artistId = artistLink.dataset.artistId;
            const trackerSheetId = artistLink.dataset.trackerSheetId;
            if (trackerSheetId) {
                navigate(`/unreleased/${trackerSheetId}`);
            } else if (artistId) {
                navigate(`/artist/${artistId}`);
            }
            return;
        }

        const card = e.target.closest('.card');
        if (card) {
            if (e.target.closest('.edit-playlist-btn') || e.target.closest('.delete-playlist-btn')) {
                return;
            }

            const libraryTracksContainer = card.closest('#library-tracks-container');
            if (libraryTracksContainer && card.dataset.trackId) {
                if (card.classList.contains('blocked')) return;
                if (
                    e.target.closest('.like-btn') ||
                    e.target.closest('.card-play-btn') ||
                    e.target.closest('.card-menu-btn')
                ) {
                    return;
                }
                e.preventDefault();
                const clickedTrackId = card.dataset.trackId;
                const clickedTrack = trackDataStore.get(card);
                if (!clickedTrack) return;
                const allTrackElements = Array.from(libraryTracksContainer.querySelectorAll('.card[data-track-id]'));
                const trackList = allTrackElements.map((el) => trackDataStore.get(el)).filter(Boolean);
                if (trackList.length === 0) return;
                const startIndex = trackList.findIndex((t) => t.id == clickedTrackId);
                player.setQueue(trackList, startIndex);
                player.enableAutoplay();
                if (ui.currentPage === 'artist' && ui.currentArtistId) {
                    player.setArtistPopularTracksContext(ui.currentArtistId, trackList, trackList.length, true);
                }
                document.getElementById('shuffle-btn').classList.remove('active');
                player.playTrackFromQueue();
                return;
            }

            const href = card.dataset.href;
            if (href) {
                // Allow native links inside card to work if any exist
                if (e.target.closest('a')) return;

                e.preventDefault();
                navigate(href);
            }
        }
    });

    mainContent.addEventListener('contextmenu', async (e) => {
        const trackItem = e.target.closest('.track-item, .queue-track-item');
        const card = e.target.closest('.card');

        if (trackItem) {
            e.preventDefault();
            if (trackItem.classList.contains('queue-track-item')) {
                // For queue items, get track from player's queue
                const queueIndex = parseInt(trackItem.dataset.queueIndex);
                contextTrack = player.getCurrentQueue()[queueIndex];
            } else {
                // For regular track items
                contextTrack = trackDataStore.get(trackItem);
            }

            if (contextTrack) {
                if (contextTrack.isLocal) return;

                if (contextMenu._originalHTML) {
                    contextMenu.innerHTML = contextMenu._originalHTML;
                    contextMenu._originalHTML = null;
                }

                // Store selected tracks for multi-select actions
                let selectedTracks = [];
                if (trackSelection.isSelecting && trackSelection.selectedIds.size > 0) {
                    document.querySelectorAll('.track-item.selected').forEach((item) => {
                        const track = trackDataStore.get(item);
                        if (track) selectedTracks.push(track);
                    });
                }

                // Hide actions for unavailable tracks
                const unavailableActions = ['play-next', 'add-to-queue', 'download', 'track-mix'];
                contextMenu.querySelectorAll('[data-action]').forEach((btn) => {
                    if (unavailableActions.includes(btn.dataset.action)) {
                        btn.style.display = contextTrack.isUnavailable ? 'none' : 'block';
                    }
                });

                contextMenu._contextTrack = contextTrack;
                contextMenu._contextType = contextTrack.type || 'track';
                contextMenu._selectedTracks = selectedTracks;
                await updateContextMenuLikeState(contextMenu, contextTrack);
                positionMenu(contextMenu, e.clientX, e.clientY);
            }
        } else if (card) {
            e.preventDefault();
            const type = card.dataset.albumId
                ? 'album'
                : card.dataset.playlistId
                  ? 'playlist'
                  : card.dataset.mixId
                    ? 'mix'
                    : card.dataset.href
                      ? card.dataset.href.split('/')[1]
                      : 'item';
            const id = card.dataset.albumId || card.dataset.playlistId || card.dataset.mixId;

            const item = trackDataStore.get(card) || {
                id,
                uuid: id,
                title: card.querySelector('.card-title')?.textContent,
            };

            if (contextMenu._originalHTML) {
                contextMenu.innerHTML = contextMenu._originalHTML;
                contextMenu._originalHTML = null;
            }

            contextTrack = item;
            contextMenu._contextTrack = item;
            contextMenu._contextType = type.replace('userplaylist', 'user-playlist');
            contextMenu._contextHref = card.dataset.href;

            await updateContextMenuLikeState(contextMenu, item);
            positionMenu(contextMenu, e.clientX, e.clientY);
        }
    });

    document.querySelector('.now-playing-bar')?.addEventListener('contextmenu', async (e) => {
        if (!player.currentTrack) return;
        const track = player.currentTrack;
        if (track.isLocal) return;

        const target = e.target.closest('.cover, .title, .album, .artist');
        if (!target) return;

        e.preventDefault();
        e.stopPropagation();

        if (contextMenu._originalHTML) {
            contextMenu.innerHTML = contextMenu._originalHTML;
            contextMenu._originalHTML = null;
        }

        contextTrack = track;
        contextMenu._contextTrack = track;
        contextMenu._contextType = track.type || 'track';
        contextMenu._selectedTracks = [];

        const unavailableActions = ['play-next', 'add-to-queue', 'download', 'track-mix'];
        contextMenu.querySelectorAll('[data-action]').forEach((btn) => {
            if (unavailableActions.includes(btn.dataset.action)) {
                btn.style.display = track.isUnavailable ? 'none' : 'block';
            }
        });

        await updateContextMenuLikeState(contextMenu, track);
        positionMenu(contextMenu, e.clientX, e.clientY);
    });

    document.addEventListener('click', async (e) => {
        if (contextMenu.style.display === 'block') {
            if (contextMenu._originalHTML) {
                contextMenu.innerHTML = contextMenu._originalHTML;
            }
            contextMenu.style.display = 'none';
            contextMenu._contextType = null;
            contextMenu._originalHTML = null;
        }

        if (
            trackSelection.isSelecting &&
            !e.target.closest('.track-item') &&
            !e.target.closest('.selection-bar') &&
            !e.target.closest('.track-checkbox')
        ) {
            clearSelection();
        }
    });

    document.addEventListener('keydown', async (e) => {
        if (e.key === 'Escape' && trackSelection.isSelecting) {
            clearSelection();
        }
    });

    contextMenu.addEventListener('click', async (e) => {
        e.stopPropagation();
        const target = e.target.closest('[data-action]');
        if (!target) return;

        const action = target.dataset.action;
        const track = contextMenu._contextTrack || contextTrack;
        const type = contextMenu._contextType || 'track';

        if (action === 'go-to-artists' || (action === 'go-to-artist' && target.dataset.hasMultipleArtists === 'true')) {
            const artists = Array.isArray(track.artists) ? track.artists : track.artist ? [track.artist] : [];
            if (artists.length > 1) {
                // Save original HTML if not already saved
                if (!contextMenu._originalHTML) {
                    contextMenu._originalHTML = contextMenu.innerHTML;
                }

                // Render sub-menu
                let subMenuHTML =
                    '<li data-action="back-to-main-menu" style="font-weight: bold; border-bottom: 1px solid var(--border); margin-bottom: 0.5rem; padding: 0.75rem 1rem; cursor: pointer;">← Back</li>';
                artists.forEach((artist) => {
                    subMenuHTML += `<li data-action="go-to-artist" data-artist-id="${artist.id}" style="padding: 0.75rem 1rem; cursor: pointer;">${escapeHtml(artist.name || 'Unknown Artist')}</li>`;
                });
                contextMenu.innerHTML = `<ul>${subMenuHTML}</ul>`;
                return;
            }
        }

        if (action === 'back-to-main-menu') {
            if (contextMenu._originalHTML) {
                contextMenu.innerHTML = contextMenu._originalHTML;
                contextMenu._originalHTML = null;
                // Re-update like state since we replaced the HTML
                await updateContextMenuLikeState(contextMenu, track);
            }
            return;
        }

        if (action && track) {
            const selectedTracks = contextMenu._selectedTracks || [];
            const isMultiSelect = selectedTracks.length > 1;

            if (isMultiSelect) {
                // Handle multi-select actions
                switch (action) {
                    case 'play-next':
                        selectedTracks.forEach((t) => {
                            player.addNextToQueue(t);
                        });
                        if (window.renderQueueFunction) await window.renderQueueFunction();
                        showNotification(`Playing next: ${selectedTracks.length} tracks`);
                        clearSelection();
                        break;
                    case 'add-to-queue':
                        player.addToQueue(selectedTracks);
                        if (window.renderQueueFunction) await window.renderQueueFunction();
                        showNotification(`Added ${selectedTracks.length} tracks to queue`);
                        clearSelection();
                        break;
                    case 'toggle-like':
                        selectedTracks.forEach(async (t) => {
                            const added = await db.toggleFavorite('track', t);
                            await syncManager.syncLibraryItem('track', t, added);
                        });
                        showNotification(`Liked ${selectedTracks.length} tracks`);
                        clearSelection();
                        break;
                    case 'add-to-playlist':
                        await showMultiSelectPlaylistModal(selectedTracks);
                        clearSelection();
                        break;
                    case 'download':
                        showNotification(`Downloading ${selectedTracks.length} tracks`);
                        clearSelection();
                        for (const track of selectedTracks) {
                            await downloadTrackWithMetadata(
                                track,
                                downloadQualitySettings.getQuality(),
                                api,
                                lyricsManager
                            );
                        }
                        break;
                    default:
                        clearSelection();
                        break;
                }
            } else {
                await handleTrackAction(action, track, player, api, lyricsManager, type, ui, scrobbler, target.dataset);
            }
        }

        // Reset menu state before closing
        if (contextMenu._originalHTML) {
            contextMenu.innerHTML = contextMenu._originalHTML;
            contextMenu._originalHTML = null;
        }
        contextMenu.style.display = 'none';
        contextMenu._contextType = null;
        contextMenu._selectedTracks = null;
    });

    // Now playing bar interactions
    document.querySelector('.now-playing-bar .title').addEventListener('click', () => {
        const track = player.currentTrack;
        if (track?.album?.id) {
            navigate(`/album/${track.album.id}`);
        }
    });

    document.querySelector('.now-playing-bar .album').addEventListener('click', () => {
        const track = player.currentTrack;
        if (track?.album?.id) {
            navigate(`/album/${track.album.id}`);
        }
    });

    document.querySelector('.now-playing-bar .artist').addEventListener('click', (e) => {
        const link = e.target.closest('.artist-link');
        if (link) {
            e.stopPropagation();
            const artistId = link.dataset.artistId;
            const trackerSheetId = link.dataset.trackerSheetId;
            if (trackerSheetId) {
                // Navigate to tracker artist page
                navigate(`/unreleased/${trackerSheetId}`);
            } else if (artistId) {
                navigate(`/artist/${artistId}`);
            }
            return;
        }

        // Fallback for non-link clicks (e.g. separators) or single artist legacy
        const track = player.currentTrack;
        if (track) {
            // Check if this is a tracker track
            const isTracker = track.isTracker || (track.id && String(track.id).startsWith('tracker-'));
            if (isTracker && track.trackerInfo?.sheetId) {
                navigate(`/unreleased/${track.trackerInfo.sheetId}`);
            } else if (track.artist?.id) {
                navigate(`/artist/${track.artist.id}`);
            }
        }
    });

    const nowPlayingLikeBtn = document.getElementById('now-playing-like-btn');
    if (nowPlayingLikeBtn) {
        nowPlayingLikeBtn.addEventListener('click', async (e) => {
            e.stopPropagation();
            if (player.currentTrack) {
                await handleTrackAction(
                    'toggle-like',
                    player.currentTrack,
                    player,
                    api,
                    lyricsManager,
                    player.currentTrack.type || 'track',
                    ui,
                    scrobbler
                );
            }
        });
    }

    const nowPlayingMixBtn = document.getElementById('now-playing-mix-btn');
    if (nowPlayingMixBtn) {
        nowPlayingMixBtn.addEventListener('click', async (e) => {
            e.stopPropagation();
            if (player.currentTrack) {
                await handleTrackAction(
                    'track-mix',
                    player.currentTrack,
                    player,
                    api,
                    lyricsManager,
                    'track',
                    ui,
                    scrobbler
                );
            }
        });
    }

    const nowPlayingAddPlaylistBtn = document.getElementById('now-playing-add-playlist-btn');
    if (nowPlayingAddPlaylistBtn) {
        nowPlayingAddPlaylistBtn.addEventListener('click', async (e) => {
            e.stopPropagation();
            if (player.currentTrack) {
                await handleTrackAction(
                    'add-to-playlist',
                    player.currentTrack,
                    player,
                    api,
                    lyricsManager,
                    player.currentTrack.type || 'track',
                    ui,
                    scrobbler
                );
            }
        });
    }

    // Mobile add playlist button functionality
    const mobileAddPlaylistBtn = document.getElementById('mobile-add-playlist-btn');

    if (mobileAddPlaylistBtn) {
        mobileAddPlaylistBtn.addEventListener('click', async (e) => {
            e.stopPropagation();
            if (player.currentTrack) {
                await handleTrackAction(
                    'add-to-playlist',
                    player.currentTrack,
                    player,
                    api,
                    lyricsManager,
                    player.currentTrack.type || 'track',
                    ui,
                    scrobbler
                );
            }
        });
    }
}

function showSleepTimerModal(player) {
    const modal = document.getElementById('sleep-timer-modal');
    if (!modal) return;

    const closeModal = () => {
        modal.classList.remove('active');
        cleanup();
    };

    const handleOptionClick = (e) => {
        const timerOption = e.target.closest('.timer-option');
        if (timerOption) {
            let minutes;
            if (timerOption.id === 'custom-timer-btn') {
                const customInput = document.getElementById('custom-minutes');
                minutes = parseInt(customInput.value);
                if (!minutes || minutes < 1) {
                    showNotification('Please enter a valid number of minutes');
                    return;
                }
            } else {
                minutes = parseInt(timerOption.dataset.minutes);
            }

            if (minutes) {
                player.setSleepTimer(minutes);
                showNotification(`Sleep timer set for ${minutes} minute${minutes === 1 ? '' : 's'}`);
                closeModal();
            }
        }
    };

    const handleCancel = (e) => {
        if (e.target.id === 'cancel-sleep-timer' || e.target.classList.contains('modal-overlay')) {
            closeModal();
        }
    };

    const cleanup = () => {
        modal.removeEventListener('click', handleOptionClick);
        modal.removeEventListener('click', handleCancel);
    };

    modal.addEventListener('click', handleOptionClick);
    modal.addEventListener('click', handleCancel);

    modal.classList.add('active');
}
