//js/ui-interactions.js
import {
    formatTime,
    getTrackTitle,
    getTrackArtists,
    escapeHtml,
    createQualityBadgeHTML,
    positionMenu,
} from './utils.js';
import { sidePanelManager } from './side-panel.js';
import { downloadQualitySettings, contentBlockingSettings } from './storage.js';
import { db } from './db.js';
import { syncManager } from './accounts/pocketbase.js';
import { showNotification, downloadTracks } from './downloads.js';
import {
    SVG_CLOSE,
    SVG_BIN,
    SVG_HEART,
    SVG_DOWNLOAD,
    SVG_HEART_FILLED,
    SVG_SQUARE_PEN,
    SVG_TRASH,
    SVG_EQUAL,
} from './icons.js';
import { hapticSuccess } from './haptics.js';

export function initializeUIInteractions(player, api, ui) {
    const sidebar = document.querySelector('.sidebar');
    const sidebarOverlay = document.getElementById('sidebar-overlay');
    const hamburgerBtn = document.getElementById('hamburger-btn');
    const queueBtn = document.getElementById('queue-btn');
    const libraryPage = document.getElementById('page-library');

    if (libraryPage) {
        libraryPage.addEventListener('dragstart', (e) => {
            const playlistCard = e.target.closest('.card.user-playlist');
            if (playlistCard) {
                e.dataTransfer.setData('text/playlist-id', playlistCard.dataset.userPlaylistId);
                e.dataTransfer.effectAllowed = 'move';
            }
        });

        const handleDragOver = (e) => {
            const folderCard = e.target.closest('.card[data-folder-id]');
            if (folderCard && e.dataTransfer.types.includes('text/playlist-id')) {
                e.preventDefault();
                folderCard.classList.add('drag-over');
            }
        };

        const handleDragLeave = (e) => {
            const folderCard = e.target.closest('.card[data-folder-id]');
            if (folderCard) {
                folderCard.classList.remove('drag-over');
            }
        };

        const handleDrop = async (e) => {
            e.preventDefault();
            const folderCard = e.target.closest('.card[data-folder-id]');
            if (folderCard) {
                folderCard.classList.remove('drag-over');
                const playlistId = e.dataTransfer.getData('text/playlist-id');
                const folderId = folderCard.dataset.folderId;

                if (playlistId && folderId) {
                    const updatedFolder = await db.addPlaylistToFolder(folderId, playlistId);
                    await syncManager.syncUserFolder(updatedFolder, 'update');
                    const subtitle = folderCard.querySelector('.card-subtitle');
                    if (subtitle) {
                        subtitle.textContent = `${updatedFolder.playlists.length} playlists`;
                    }
                    showNotification('Playlist added to folder');
                }
            }
        };

        libraryPage.addEventListener('dragover', handleDragOver);
        libraryPage.addEventListener('dragleave', handleDragLeave);
        libraryPage.addEventListener('drop', handleDrop);
    }

    let draggedQueueIndex = null;
    let queueStartIndex = 0;
    let queueEndIndex = 1000;
    let isQueueRendering = false;
    let topObserver = null;
    let bottomObserver = null;
    const QUEUE_VIRTUALIZATION_THRESHOLD = 1500;
    const QUEUE_MAX_RENDERED = 1000;
    const QUEUE_CHUNK_SIZE = 200;
    const ESTIMATED_ITEM_HEIGHT = 58;

    // Sidebar mobile
    hamburgerBtn.addEventListener('click', () => {
        sidebar.classList.add('is-open');
        sidebarOverlay.classList.add('is-visible');
    });

    const closeSidebar = () => {
        sidebar.classList.remove('is-open');
        sidebarOverlay.classList.remove('is-visible');
    };

    sidebarOverlay.addEventListener('click', closeSidebar);

    sidebar.addEventListener('click', (e) => {
        if (e.target.closest('a')) {
            closeSidebar();
        }
    });

    // Queue panel
    const renderQueueControls = async (container) => {
        const currentQueue = player.getCurrentQueue();
        const showActionBtns = currentQueue.length > 0;

        container.innerHTML = `
            <button id="download-queue-btn" class="btn-icon" title="Download Queue" style="display: ${showActionBtns ? 'flex' : 'none'}">
                ${SVG_DOWNLOAD(20)}
            </button>
            <button id="like-queue-btn" class="btn-icon" title="Add Queue to Liked" style="display: ${showActionBtns ? 'flex' : 'none'}">
                ${SVG_HEART(20)}
            </button>
            <button id="add-queue-to-playlist-btn" class="btn-icon" title="Add Queue to Playlist" style="display: ${showActionBtns ? 'flex' : 'none'}">
                ${SVG_SQUARE_PEN(20)}
            </button>
            <button id="clear-queue-btn" class="btn-icon" title="Clear Queue" style="display: ${showActionBtns ? 'flex' : 'none'}">
                ${SVG_TRASH(20)}
            </button>
            <button id="close-side-panel-btn" class="btn-icon" title="Close">
                ${SVG_CLOSE(20)}
            </button>
        `;

        container.querySelector('#close-side-panel-btn').addEventListener('click', () => {
            sidePanelManager.close();
        });

        const downloadBtn = container.querySelector('#download-queue-btn');
        if (downloadBtn) {
            downloadBtn.addEventListener('click', async () => {
                await downloadTracks(currentQueue, api, downloadQualitySettings.getQuality());
            });
        }

        const likeBtn = container.querySelector('#like-queue-btn');
        if (likeBtn) {
            likeBtn.addEventListener('click', async () => {
                let addedCount = 0;
                for (const track of currentQueue) {
                    const wasAdded = await db.toggleFavorite('track', track);
                    if (wasAdded) {
                        await syncManager.syncLibraryItem('track', track, true);
                        addedCount++;
                    }
                }

                if (addedCount > 0) {
                    showNotification(`Added ${addedCount} track${addedCount > 1 ? 's' : ''} to Liked`);
                } else {
                    showNotification('All tracks in queue are already liked');
                }

                await refreshQueuePanel();
            });
        }

        const addToPlaylistBtn = container.querySelector('#add-queue-to-playlist-btn');
        if (addToPlaylistBtn) {
            addToPlaylistBtn.addEventListener('click', async () => {
                const playlists = await db.getPlaylists();
                if (playlists.length === 0) {
                    showNotification('No playlists yet. Create one first.');
                    return;
                }

                const modal = document.createElement('div');
                modal.className = 'modal active';
                modal.innerHTML = `
                    <div class="modal-overlay"></div>
                    <div class="modal-content">
                        <h3>Add Queue to Playlist</h3>
                        <div class="modal-list">
                            ${playlists
                                .map(
                                    (p) => `
                                <div class="modal-option" data-id="${p.id}">${escapeHtml(p.name)}</div>
                            `
                                )
                                .join('')}
                        </div>
                        <div class="modal-actions">
                            <button class="btn-secondary cancel-btn">Cancel</button>
                        </div>
                    </div>
                `;

                document.body.appendChild(modal);

                const closeModal = () => {
                    modal.remove();
                };

                modal.addEventListener('click', async (e) => {
                    if (e.target.classList.contains('modal-overlay') || e.target.classList.contains('cancel-btn')) {
                        closeModal();
                        return;
                    }

                    const option = e.target.closest('.modal-option');
                    if (option) {
                        const playlistId = option.dataset.id;
                        const playlistName = option.textContent;

                        try {
                            let addedCount = 0;
                            for (const track of currentQueue) {
                                await db.addTrackToPlaylist(playlistId, track);
                                addedCount++;
                            }

                            const updatedPlaylist = await db.getPlaylist(playlistId);
                            await syncManager.syncUserPlaylist(updatedPlaylist, 'update');

                            showNotification(`Added ${addedCount} tracks to playlist: ${playlistName}`);
                        } catch (error) {
                            console.error('Failed to add tracks to playlist:', error);
                            showNotification('Failed to add tracks to playlist');
                        }

                        closeModal();
                    }
                });
            });
        }

        const clearBtn = container.querySelector('#clear-queue-btn');
        if (clearBtn) {
            clearBtn.addEventListener('click', async () => {
                player.clearQueue();
                await refreshQueuePanel();
            });
        }
    };

    const renderQueueItemHTML = (track, index) => {
        const isPlaying = index === player.currentQueueIndex;
        const isBlocked = contentBlockingSettings?.shouldHideTrack(track);
        const trackTitle = getTrackTitle(track);
        const trackArtists = getTrackArtists(track, { fallback: 'Unknown' });
        const qualityBadge = createQualityBadgeHTML(track);
        const blockedTitle = isBlocked
            ? `title="Blocked: ${contentBlockingSettings.isTrackBlocked(track.id) ? 'Track blocked' : contentBlockingSettings.isArtistBlocked(track.artist?.id) ? 'Artist blocked' : 'Album blocked'}"`
            : '';

        const isVideo = track.type === 'video';
        const coverUrl =
            isVideo && track.imageId ? api.getVideoCoverUrl(track.imageId) : api.getCoverUrl(track.album?.cover);

        return `
        <div class="queue-track-item ${isPlaying ? 'playing' : ''} ${isBlocked ? 'blocked' : ''}" data-queue-index="${index}" data-track-id="${track.id}" draggable="${isBlocked ? 'false' : 'true'}" ${blockedTitle}>
            <div class="drag-handle">
                ${SVG_EQUAL(16)}
            </div>
            <div class="track-item-info">
                <img src="${coverUrl}"
                     class="track-item-cover" loading="lazy">
                <div class="track-item-details">
                    <div class="title">${escapeHtml(trackTitle)} ${qualityBadge}</div>
                    <div class="artist">${escapeHtml(trackArtists)}</div>
                </div>
            </div>
            <div class="track-item-duration">${isBlocked ? '--:--' : formatTime(track.duration)}</div>
            <button class="queue-like-btn" data-action="toggle-like" title="Add to Liked">
                ${SVG_HEART(20)}
            </button>
            <button class="queue-remove-btn" data-track-index="${index}" title="Remove from queue">
                ${SVG_BIN(20)}
            </button>
        </div>
    `;
    };

    const attachQueueListeners = async (container) => {
        if (container._queueListenersAttached) return;

        container.addEventListener('click', async (e) => {
            const item = e.target.closest('.queue-track-item');
            if (!item) return;

            const index = parseInt(item.dataset.queueIndex);
            const removeBtn = e.target.closest('.queue-remove-btn');
            if (removeBtn) {
                e.stopPropagation();
                player.removeFromQueue(index);
                await refreshQueuePanel();
                return;
            }

            const likeBtn = e.target.closest('.queue-like-btn');
            if (likeBtn && likeBtn.dataset.action === 'toggle-like') {
                e.stopPropagation();
                const track = player.getCurrentQueue()[index];
                if (track) {
                    const added = await db.toggleFavorite('track', track);
                    await syncManager.syncLibraryItem('track', track, added);

                    likeBtn.classList.toggle('active', added);
                    likeBtn.innerHTML = added ? SVG_HEART_FILLED(20) : SVG_HEART(20);

                    await hapticSuccess();
                    showNotification(added ? `Added to Liked: ${track.title}` : `Removed from Liked: ${track.title}`);
                }
                return;
            }

            if (item.classList.contains('blocked')) return;

            player.playAtIndex(index);
            await refreshQueuePanel();
        });

        container.addEventListener('contextmenu', async (e) => {
            const item = e.target.closest('.queue-track-item');
            if (!item) return;

            e.preventDefault();
            const index = parseInt(item.dataset.queueIndex);
            const contextMenu = document.getElementById('context-menu');
            if (contextMenu) {
                const track = player.getCurrentQueue()[index];
                if (track) {
                    const isLiked = await db.isFavorite('track', track.id);
                    const likeItem = contextMenu.querySelector('li[data-action="toggle-like"]');
                    if (likeItem) {
                        likeItem.textContent = isLiked ? 'Unlike' : 'Like';
                    }

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

                    positionMenu(contextMenu, e.clientX, e.clientY);
                    contextMenu._contextTrack = track;
                }
            }
        });

        container.addEventListener('dragstart', (e) => {
            const item = e.target.closest('.queue-track-item');
            if (item) {
                draggedQueueIndex = parseInt(item.dataset.queueIndex);
                item.style.opacity = '0.5';
            }
        });

        container.addEventListener('dragend', (e) => {
            const item = e.target.closest('.queue-track-item');
            if (item) {
                item.style.opacity = '1';
            }
        });

        container.addEventListener('dragover', (e) => {
            e.preventDefault();
        });

        container.addEventListener('drop', async (e) => {
            e.preventDefault();
            const item = e.target.closest('.queue-track-item');
            if (item && draggedQueueIndex !== null) {
                const index = parseInt(item.dataset.queueIndex);
                if (draggedQueueIndex !== index) {
                    player.moveInQueue(draggedQueueIndex, index);
                    await refreshQueuePanel();
                }
            }
        });

        container._queueListenersAttached = true;
    };

    const renderQueueContent = async (container, isUpdate = false) => {
        const currentQueue = player.getCurrentQueue();

        if (currentQueue.length === 0) {
            container.innerHTML = '<div class="placeholder-text">Queue is empty.</div>';
            queueStartIndex = 0;
            queueEndIndex = QUEUE_MAX_RENDERED;
            return;
        }

        isQueueRendering = true;
        await attachQueueListeners(container);

        if (currentQueue.length > QUEUE_VIRTUALIZATION_THRESHOLD) {
            if (!isUpdate) {
                const currentIndex = player.currentQueueIndex || 0;
                queueStartIndex = Math.max(0, Math.floor((currentIndex - QUEUE_MAX_RENDERED / 2) / 100) * 100);
                queueEndIndex = Math.min(currentQueue.length, queueStartIndex + QUEUE_MAX_RENDERED);
            }

            const visibleTracks = currentQueue.slice(queueStartIndex, queueEndIndex);
            const topSpacerHeight = queueStartIndex * ESTIMATED_ITEM_HEIGHT;
            const bottomSpacerHeight = (currentQueue.length - queueEndIndex) * ESTIMATED_ITEM_HEIGHT;

            container.innerHTML = `
                <div class="queue-virtual-container" style="padding: 0.5rem">
                    <div id="queue-top-sentinel" style="height: 20px; margin-top: ${topSpacerHeight}px"></div>
                    <div class="queue-items-wrapper">
                        ${visibleTracks.map((track, i) => renderQueueItemHTML(track, queueStartIndex + i)).join('')}
                    </div>
                    <div id="queue-bottom-sentinel" style="height: 20px; margin-bottom: ${bottomSpacerHeight}px"></div>
                </div>
            `;

            if (topObserver) topObserver.disconnect();
            if (bottomObserver) bottomObserver.disconnect();

            bottomObserver = new IntersectionObserver(
                async (entries) => {
                    if (entries[0].isIntersecting && !isQueueRendering && queueEndIndex < currentQueue.length) {
                        queueEndIndex = Math.min(currentQueue.length, queueEndIndex + QUEUE_CHUNK_SIZE);
                        if (queueEndIndex - queueStartIndex > QUEUE_MAX_RENDERED) {
                            queueStartIndex += QUEUE_CHUNK_SIZE;
                        }
                        await renderQueueContent(container, true);
                    }
                },
                { root: container, rootMargin: '200px' }
            );

            topObserver = new IntersectionObserver(
                async (entries) => {
                    if (entries[0].isIntersecting && !isQueueRendering && queueStartIndex > 0) {
                        queueStartIndex = Math.max(0, queueStartIndex - QUEUE_CHUNK_SIZE);
                        if (queueEndIndex - queueStartIndex > QUEUE_MAX_RENDERED) {
                            queueEndIndex -= QUEUE_CHUNK_SIZE;
                        }
                        await renderQueueContent(container, true);
                    }
                },
                { root: container, rootMargin: '200px' }
            );

            topObserver.observe(container.querySelector('#queue-top-sentinel'));
            bottomObserver.observe(container.querySelector('#queue-bottom-sentinel'));
        } else {
            container.innerHTML = `<div style="padding: 0.5rem">${currentQueue.map((track, index) => renderQueueItemHTML(track, index)).join('')}</div>`;
            if (topObserver) topObserver.disconnect();
            if (bottomObserver) bottomObserver.disconnect();
        }

        container.querySelectorAll('.queue-track-item').forEach(async (item) => {
            const index = parseInt(item.dataset.queueIndex);
            const track = currentQueue[index];
            const likeBtn = item.querySelector('.queue-like-btn');
            if (likeBtn && track) {
                const isLiked = await db.isFavorite('track', track.id);
                likeBtn.classList.toggle('active', isLiked);
                likeBtn.innerHTML = isLiked ? SVG_HEART_FILLED(20) : SVG_HEART(20);
            }
        });

        isQueueRendering = false;
    };

    const refreshQueuePanel = async () => {
        await sidePanelManager.refresh('queue', renderQueueControls, renderQueueContent, { noClear: true });
    };

    const openQueuePanel = () => {
        sidePanelManager.open('queue', 'Queue', renderQueueControls, renderQueueContent);

        setTimeout(() => {
            const container = document.getElementById('side-panel-content');
            const playingItem = container?.querySelector('.queue-track-item.playing');
            if (playingItem) {
                playingItem.scrollIntoView({ block: 'center', behavior: 'auto' });
            }
        }, 100);
    };

    queueBtn.addEventListener('click', openQueuePanel);

    // Expose renderQueue for external updates (e.g. shuffle, add to queue)
    window.renderQueueFunction = async () => {
        if (sidePanelManager.isActive('queue')) {
            await refreshQueuePanel();
        }

        const overlay = document.getElementById('fullscreen-cover-overlay');
        if (overlay && getComputedStyle(overlay).display !== 'none') {
            ui.updateFullscreenMetadata(player.currentTrack, player.getNextTrack());
        }
    };

    const folderPage = document.getElementById('page-folder');
    if (folderPage) {
        folderPage.addEventListener('dragover', (e) => {
            if (e.dataTransfer.types.includes('text/playlist-id')) {
                e.preventDefault();
                folderPage.classList.add('drag-over-folder-page');
            }
        });
        folderPage.addEventListener('dragleave', () => {
            folderPage.classList.remove('drag-over-folder-page');
        });
        folderPage.addEventListener('drop', async (e) => {
            e.preventDefault();
            folderPage.classList.remove('drag-over-folder-page');
            const playlistId = e.dataTransfer.getData('text/playlist-id');
            const folderId = window.location.pathname.split('/')[2];
            if (playlistId && folderId) {
                try {
                    const updatedFolder = await db.addPlaylistToFolder(folderId, playlistId);
                    await syncManager.syncUserFolder(updatedFolder, 'update');
                    window.dispatchEvent(new HashChangeEvent('hashchange'));
                    showNotification('Playlist added to folder');
                } catch (error) {
                    console.error('Failed to add playlist to folder:', error);
                    showNotification('Failed to add playlist to folder', 'error');
                }
            }
        });
    }

    // Search and Library tabs
    document.querySelectorAll('.search-tab').forEach((tab) => {
        tab.addEventListener('click', () => {
            const page = tab.closest('.page');
            if (!page) return;

            page.querySelectorAll('.search-tab').forEach((t) => t.classList.remove('active'));
            page.querySelectorAll('.search-tab-content').forEach((c) => c.classList.remove('active'));

            tab.classList.add('active');

            const prefix = page.id === 'page-library' ? 'library-tab-' : 'search-tab-';
            const contentId = `${prefix}${tab.dataset.tab}`;
            document.getElementById(contentId)?.classList.add('active');
        });
    });

    // Settings tabs
    document.querySelectorAll('.settings-tab').forEach((tab) => {
        tab.addEventListener('click', () => {
            document.querySelectorAll('.settings-tab').forEach((t) => t.classList.remove('active'));
            document.querySelectorAll('.settings-tab-content').forEach((c) => c.classList.remove('active'));

            tab.classList.add('active');

            const contentId = `settings-tab-${tab.dataset.tab}`;
            document.getElementById(contentId)?.classList.add('active');

            // Save active tab
            import('./storage.js')
                .then(({ settingsUiState }) => {
                    settingsUiState.setActiveTab(tab.dataset.tab);
                })
                .catch(console.error);
        });
    });

    // Tooltip for truncated text (desktop hover only)
    const canUseHoverTooltips = window.matchMedia('(hover: hover) and (pointer: fine)').matches;
    let tooltipEl = null;

    if (canUseHoverTooltips) {
        tooltipEl = document.getElementById('custom-tooltip');
        if (!tooltipEl) {
            tooltipEl = document.createElement('div');
            tooltipEl.id = 'custom-tooltip';
            document.body.appendChild(tooltipEl);
        }

        const updateTooltipPosition = (e) => {
            const x = e.clientX + 15;
            const y = e.clientY + 15;

            // Prevent going off-screen
            const rect = tooltipEl.getBoundingClientRect();
            const winWidth = window.innerWidth;
            const winHeight = window.innerHeight;

            let finalX = x;
            let finalY = y;

            if (x + rect.width > winWidth) {
                finalX = e.clientX - rect.width - 10;
            }

            if (y + rect.height > winHeight) {
                finalY = e.clientY - rect.height - 10;
            }

            // Ensure it stays within viewport
            if (finalX < 5) finalX = 5;
            if (finalY < 5) finalY = 5;
            if (finalX + rect.width > winWidth - 5) finalX = winWidth - rect.width - 5;
            if (finalY + rect.height > winHeight - 5) finalY = winHeight - rect.height - 5;

            tooltipEl.style.transform = `translate(${finalX}px, ${finalY}px)`;
            // Reset top/left to 0 since we use transform
            tooltipEl.style.top = '0';
            tooltipEl.style.left = '0';
        };

        document.body.addEventListener('mouseover', (e) => {
            const selector =
                '.card-title, .card-subtitle, .track-item-details .title, .track-item-details .artist, .now-playing-bar .title, .now-playing-bar .artist, .now-playing-bar .album, .pinned-item-name';
            const target = e.target.closest(selector);

            if (target) {
                // Remove native title if present to avoid double tooltip
                if (target.hasAttribute('title')) {
                    target.removeAttribute('title');
                }

                if (target.scrollWidth > target.clientWidth) {
                    tooltipEl.innerHTML = target.innerHTML.trim();
                    tooltipEl.classList.add('visible');
                    updateTooltipPosition(e);

                    const moveHandler = (moveEvent) => {
                        updateTooltipPosition(moveEvent);
                    };

                    const outHandler = () => {
                        tooltipEl.classList.remove('visible');
                        target.removeEventListener('mousemove', moveHandler);
                        target.removeEventListener('mouseleave', outHandler);
                        target.removeEventListener('click', outHandler);
                    };

                    target.addEventListener('mousemove', moveHandler);
                    target.addEventListener('mouseleave', outHandler);
                    target.addEventListener('click', outHandler);
                }
            }
        });
    }

    // Hide tooltip and context menu on any click to be safe
    document.addEventListener('mousedown', (e) => {
        if (tooltipEl) {
            tooltipEl.classList.remove('visible');
        }

        const contextMenu = document.getElementById('context-menu');
        if (contextMenu && contextMenu.style.display === 'block' && !contextMenu.contains(e.target)) {
            contextMenu.style.display = 'none';
        }
    });
}
