// Playlists UI module
(function() {
  const M = window.MusicRoom;
  const $ = M.$;
  const formatTime = M.fmt;
  const showToast = M.showToast;

  let myPlaylists = [];
  let sharedPlaylists = [];
  let selectedPlaylistId = null;
  let selectedPlaylist = null;

  async function loadPlaylists() {
    try {
      const res = await fetch('/api/playlists');
      if (!res.ok) {
        if (res.status === 401) {
          // Not logged in yet
          return;
        }
        throw new Error('Failed to load playlists');
      }
      const data = await res.json();
      myPlaylists = data.mine || [];
      sharedPlaylists = data.shared || [];
      renderPlaylistList();
    } catch (err) {
      console.error('Failed to load playlists:', err);
    }
  }

  function renderPlaylistList() {
    const myContainer = $('#my-playlists');
    const sharedContainer = $('#shared-playlists');
    if (!myContainer || !sharedContainer) return;
    if (M.updatePermissionUI) M.updatePermissionUI();

    // My playlists
    if (myPlaylists.length === 0) {
      myContainer.innerHTML = '<div class="empty-playlists">No playlists yet</div>';
    } else {
      myContainer.innerHTML = myPlaylists.map(p => `
        <div class="playlist-item${p.id === selectedPlaylistId ? ' selected' : ''}" data-id="${p.id}">
          <span class="playlist-name">${escapeHtml(p.name)}</span>
          ${p.isPublic ? '<span class="playlist-public-icon" title="Public">🌐</span>' : ''}
          <span class="playlist-count">${p.trackIds.length}</span>
        </div>
      `).join('');
    }

    // Shared playlists
    if (sharedPlaylists.length === 0) {
      sharedContainer.innerHTML = '<div class="empty-playlists">No shared playlists</div>';
    } else {
      sharedContainer.innerHTML = sharedPlaylists.map(p => `
        <div class="playlist-item${p.id === selectedPlaylistId ? ' selected' : ''}" data-id="${p.id}">
          <span class="playlist-name">${escapeHtml(p.name)}</span>
          <span class="playlist-owner">by ${escapeHtml(p.ownerName || 'Unknown')}</span>
          <span class="playlist-count">${p.trackIds.length}</span>
        </div>
      `).join('');
    }

    // Attach click handlers
    myContainer.querySelectorAll('.playlist-item').forEach(el => {
      el.onclick = () => selectPlaylist(el.dataset.id);
      el.oncontextmenu = (e) => showPlaylistContextMenu(e, el.dataset.id, true);
    });
    sharedContainer.querySelectorAll('.playlist-item').forEach(el => {
      el.onclick = () => selectPlaylist(el.dataset.id);
      el.oncontextmenu = (e) => showPlaylistContextMenu(e, el.dataset.id, false);
    });
  }

  async function selectPlaylist(id) {
    selectedPlaylistId = id;
    
    // Update selection in list
    document.querySelectorAll('.playlist-item').forEach(el => {
      el.classList.toggle('selected', el.dataset.id === id);
    });

    // Load playlist details
    try {
      const res = await fetch(`/api/playlists/${id}`);
      if (!res.ok) throw new Error('Failed to load playlist');
      selectedPlaylist = await res.json();
      renderPlaylistContents();
    } catch (err) {
      console.error('Failed to load playlist:', err);
      showToast('Failed to load playlist', 'error');
    }
  }

  // Playlist tracks container instance
  let playlistContainer = null;

  function renderPlaylistContents() {
    const header = $('#selected-playlist-name');
    const actions = $('#playlist-actions');
    const containerEl = $('#playlist-tracks');
    
    if (!selectedPlaylist) {
      header.textContent = 'Select a playlist';
      actions.classList.add('hidden');
      containerEl.innerHTML = '';
      return;
    }

    header.textContent = selectedPlaylist.name;
    actions.classList.toggle('hidden', !M.canControl());

    const isMine = myPlaylists.some(p => p.id === selectedPlaylistId);

    // Create or update container (even for empty playlists, to enable drag-drop)
    playlistContainer = M.trackContainer.createContainer({
      type: 'playlist',
      element: containerEl,
      getTracks: () => {
        return selectedPlaylist.trackIds.map((id, i) => {
          const track = M.library.find(t => t.id === id);
          return { track: track || { id, title: 'Unknown track', duration: 0 }, originalIndex: i };
        });
      },
      isPlaylistOwner: isMine,
      playlistId: selectedPlaylistId
    });
    
    playlistContainer.render();
  }

  function reloadCurrentPlaylist() {
    if (selectedPlaylistId) {
      selectPlaylist(selectedPlaylistId);
    }
  }

  function showPlaylistContextMenu(e, playlistId, isMine) {
    e.preventDefault();
    M.contextMenu.hide();

    const playlist = isMine 
      ? myPlaylists.find(p => p.id === playlistId)
      : sharedPlaylists.find(p => p.id === playlistId);
    if (!playlist) return;

    const items = [];
    const canEditQueue = M.canControl();

    // Add to queue options
    if (canEditQueue) {
      items.push({
        label: '▶ Add to Queue',
        action: () => addPlaylistToQueue(playlistId)
      });
      items.push({
        label: '⏭ Play Next',
        action: () => addPlaylistToQueue(playlistId, true)
      });
    }

    if (canEditQueue && (isMine || M.canCreateUserContent())) {
      items.push({ separator: true });
    }

    if (isMine) {
      // Rename
      items.push({
        label: '✏️ Rename',
        action: () => startRenamePlaylist(playlistId)
      });
      
      // Share/unshare
      if (playlist.isPublic) {
        items.push({
          label: '🔒 Make Private',
          action: () => togglePlaylistPublic(playlistId, false)
        });
      } else {
        items.push({
          label: '🌐 Make Public',
          action: () => togglePlaylistPublic(playlistId, true)
        });
      }

      items.push({ separator: true });

      // Delete
      items.push({
        label: '🗑️ Delete',
        action: () => deletePlaylist(playlistId),
        danger: true
      });
    } else if (M.canCreateUserContent()) {
      // Copy to my playlists
      items.push({
        label: '📋 Copy to My Playlists',
        action: () => copyPlaylist(playlistId)
      });
    }

    while (items[0]?.separator) items.shift();
    while (items[items.length - 1]?.separator) items.pop();
    if (items.length === 0) return;

    M.contextMenu.show(e, items);
  }

  async function addPlaylistToQueue(playlistId, playNext = false) {
    if (!M.canControl()) {
      M.flashPermissionDenied();
      showToast('Sign in to control playback', 'warning');
      return;
    }

    const playlist = [...myPlaylists, ...sharedPlaylists].find(p => p.id === playlistId);
    if (!playlist || playlist.trackIds.length === 0) {
      showToast('Playlist is empty', 'error');
      return;
    }

    try {
      const body = playNext 
        ? { add: playlist.trackIds, insertAt: M.currentIndex + 1 }
        : { add: playlist.trackIds };
      
      const res = await fetch(`/api/channels/${M.currentChannelId}/queue`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body)
      });
      
      if (!res.ok) throw new Error('Failed to add to queue');
      showToast(`Added ${playlist.trackIds.length} tracks to queue`);
    } catch (err) {
      console.error('Failed to add playlist to queue:', err);
      showToast('Failed to add to queue', 'error');
    }
  }

  async function addTracksToQueue(trackIds, playNext = false) {
    try {
      const body = playNext 
        ? { add: trackIds, insertAt: M.currentIndex + 1 }
        : { add: trackIds };
      
      const res = await fetch(`/api/channels/${M.currentChannelId}/queue`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body)
      });
      
      if (!res.ok) throw new Error('Failed to add to queue');
      showToast(`Added ${trackIds.length} track${trackIds.length > 1 ? 's' : ''} to queue`);
    } catch (err) {
      console.error('Failed to add to queue:', err);
      showToast('Failed to add to queue', 'error');
    }
  }

  function playTrackFromPlaylist(trackId) {
    // Desynced playback of single track
    if (M.playDirectTrack) {
      M.playDirectTrack(trackId);
    }
  }

  async function createPlaylist(name) {
    try {
      const res = await fetch('/api/playlists', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name })
      });
      if (!res.ok) throw new Error('Failed to create playlist');
      const playlist = await res.json();
      showToast(`Created playlist "${name}"`);
      await loadPlaylists();
      selectPlaylist(playlist.id);
      return playlist;
    } catch (err) {
      console.error('Failed to create playlist:', err);
      showToast('Failed to create playlist', 'error');
      return null;
    }
  }

  async function deletePlaylist(playlistId) {
    const playlist = myPlaylists.find(p => p.id === playlistId);
    if (!playlist) return;

    M.showConfirmToast(`Delete playlist "${playlist.name}"?`, async () => {
      try {
        const res = await fetch(`/api/playlists/${playlistId}`, { method: 'DELETE' });
        if (!res.ok) throw new Error('Failed to delete playlist');
        showToast(`Deleted playlist "${playlist.name}"`);

        if (selectedPlaylistId === playlistId) {
          selectedPlaylistId = null;
          selectedPlaylist = null;
          renderPlaylistContents();
        }
        await loadPlaylists();
      } catch (err) {
        console.error('Failed to delete playlist:', err);
        showToast('Failed to delete playlist', 'error');
      }
    }, { confirmText: 'Delete', duration: 15000 });
  }

  function startRenamePlaylist(playlistId) {
    const el = document.querySelector(`.playlist-item[data-id="${playlistId}"] .playlist-name`);
    if (!el) return;

    const playlist = myPlaylists.find(p => p.id === playlistId);
    if (!playlist) return;

    const input = document.createElement('input');
    input.type = 'text';
    input.className = 'playlist-rename-input';
    input.value = playlist.name;
    
    const originalText = el.textContent;
    el.textContent = '';
    el.appendChild(input);
    input.focus();
    input.select();

    const finish = async (save) => {
      const newName = input.value.trim();
      el.textContent = save && newName ? newName : originalText;
      
      if (save && newName && newName !== originalText) {
        try {
          const res = await fetch(`/api/playlists/${playlistId}`, {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ name: newName })
          });
          if (!res.ok) throw new Error('Failed to rename');
          showToast(`Renamed to "${newName}"`);
          await loadPlaylists();
          if (selectedPlaylistId === playlistId && selectedPlaylist) {
            selectedPlaylist.name = newName;
            renderPlaylistContents();
          }
        } catch (err) {
          el.textContent = originalText;
          showToast('Failed to rename playlist', 'error');
        }
      }
    };

    input.onblur = () => finish(true);
    input.onkeydown = (e) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        input.blur();
      } else if (e.key === 'Escape') {
        finish(false);
      }
    };
  }

  async function togglePlaylistPublic(playlistId, isPublic) {
    try {
      const res = await fetch(`/api/playlists/${playlistId}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ isPublic })
      });
      if (!res.ok) throw new Error('Failed to update');
      showToast(isPublic ? 'Playlist is now public' : 'Playlist is now private');
      await loadPlaylists();
    } catch (err) {
      showToast('Failed to update playlist', 'error');
    }
  }

  async function generateShareLink(playlistId) {
    try {
      const res = await fetch(`/api/playlists/${playlistId}/share`, { method: 'POST' });
      if (!res.ok) throw new Error('Failed to generate link');
      const data = await res.json();
      const url = `${window.location.origin}/playlist/${data.shareToken}`;
      await navigator.clipboard.writeText(url);
      showToast('Share link copied to clipboard');
      await loadPlaylists();
    } catch (err) {
      showToast('Failed to generate share link', 'error');
    }
  }

  function copyShareLink(token) {
    const url = `${window.location.origin}/playlist/${token}`;
    navigator.clipboard.writeText(url).then(() => {
      showToast('Share link copied to clipboard');
    });
  }

  async function copyPlaylist(playlistId) {
    const playlist = sharedPlaylists.find(p => p.id === playlistId);
    if (!playlist) return;

    try {
      if (playlist.shareToken) {
        const res = await fetch(`/api/playlists/shared/${playlist.shareToken}`, { method: 'POST' });
        if (!res.ok) throw new Error('Failed to copy');
      } else {
        // Create new playlist and copy tracks
        const newPlaylist = await createPlaylist(`${playlist.name} (Copy)`);
        if (newPlaylist) {
          await fetch(`/api/playlists/${newPlaylist.id}/tracks`, {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ set: playlist.trackIds })
          });
        }
      }
      showToast(`Copied "${playlist.name}" to your playlists`);
      await loadPlaylists();
    } catch (err) {
      showToast('Failed to copy playlist', 'error');
    }
  }

  async function removeTrackFromPlaylist(index) {
    if (!selectedPlaylistId) return;

    try {
      const res = await fetch(`/api/playlists/${selectedPlaylistId}/tracks`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ remove: [index] })
      });
      if (!res.ok) throw new Error('Failed to remove track');
      showToast('Track removed from playlist');
      await selectPlaylist(selectedPlaylistId);
      await loadPlaylists();
    } catch (err) {
      showToast('Failed to remove track', 'error');
    }
  }

  // Add tracks to playlist (used from library/queue context menu)
  async function addTracksToPlaylist(playlistId, trackIds) {
    try {
      const res = await fetch(`/api/playlists/${playlistId}/tracks`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ add: trackIds })
      });
      if (!res.ok) throw new Error('Failed to add tracks');
      
      const playlist = myPlaylists.find(p => p.id === playlistId);
      showToast(`Added ${trackIds.length} track${trackIds.length > 1 ? 's' : ''} to "${playlist?.name || 'playlist'}"`);
      
      if (selectedPlaylistId === playlistId) {
        await selectPlaylist(playlistId);
      }
      await loadPlaylists();
    } catch (err) {
      showToast('Failed to add tracks to playlist', 'error');
    }
  }

  // Show "Add to Playlist" submenu
  function showAddToPlaylistMenu(trackIds) {
    if (!M.canCreateUserContent()) return null;
    if (myPlaylists.length === 0) {
      showToast('Create a playlist first', 'info');
      return null;
    }

    return myPlaylists.map(p => ({
      label: p.name,
      action: () => addTracksToPlaylist(p.id, trackIds)
    }));
  }

  function escapeHtml(str) {
    if (!str) return '';
    return str.replace(/[&<>"']/g, c => ({
      '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'
    }[c]));
  }

  function initPlaylists() {
    // New playlist button
    const btnNew = $('#btn-new-playlist');
    if (btnNew) {
      btnNew.onclick = () => {
        if (!M.canCreateUserContent()) {
          showToast('Sign in to create playlists', 'warning');
          return;
        }

        // Inline input for new playlist name
        const container = $('#my-playlists');
        const input = document.createElement('input');
        input.type = 'text';
        input.className = 'new-playlist-input';
        input.placeholder = 'Playlist name...';
        container.insertBefore(input, container.firstChild);
        input.focus();

        const finish = async (create) => {
          const name = input.value.trim();
          input.remove();
          if (create && name) {
            await createPlaylist(name);
          }
        };

        input.onblur = () => finish(true);
        input.onkeydown = (e) => {
          if (e.key === 'Enter') {
            e.preventDefault();
            input.blur();
          } else if (e.key === 'Escape') {
            finish(false);
          }
        };
      };
    }

    // Add to queue buttons
    const btnAddQueue = $('#btn-playlist-add-queue');
    const btnPlayNext = $('#btn-playlist-play-next');
    
    if (btnAddQueue) {
      btnAddQueue.onclick = () => {
        if (selectedPlaylistId) addPlaylistToQueue(selectedPlaylistId);
      };
    }
    if (btnPlayNext) {
      btnPlayNext.onclick = () => {
        if (selectedPlaylistId) addPlaylistToQueue(selectedPlaylistId, true);
      };
    }

    // Load playlists when tab is shown
    document.querySelectorAll('.panel-tab[data-tab="playlists"]').forEach(tab => {
      tab.addEventListener('click', () => {
        loadPlaylists();
      });
    });
  }

  // Expose for other modules
  M.playlists = {
    load: loadPlaylists,
    init: initPlaylists,
    getMyPlaylists: () => myPlaylists,
    showAddToPlaylistMenu,
    addTracksToPlaylist,
    renderPlaylistContents,
    reloadCurrentPlaylist
  };
})();
