// MusicRoom - Queue module
// Queue and library display using trackContainer

(function() {
  const M = window.MusicRoom;
  
  // Download state - only one at a time
  let isDownloading = false;
  let exportQueue = [];
  let isExporting = false;
  
  // Container instances
  let queueContainer = null;
  let libraryContainer = null;
  
  // Library search state
  M.librarySearchQuery = "";

  // Download a track to user's device (uses cache if available)
  async function downloadTrack(trackId, filename) {
    if (isDownloading) {
      M.showToast("Download already in progress", "warning");
      return;
    }
    
    isDownloading = true;
    M.showToast(`Downloading: ${filename}`);
    
    try {
      let blob = null;
      
      // Try to get from cache first
      if (M.cachedTracks.has(trackId)) {
        try {
          const cached = await TrackStorage.get(trackId);
          if (cached && cached.blob) {
            blob = cached.blob;
          }
        } catch (e) {
          console.log("Cache miss, fetching from server");
        }
      }
      
      // Fall back to fetching from server
      if (!blob) {
        const res = await fetch(`/api/tracks/${encodeURIComponent(trackId)}`);
        if (!res.ok) throw new Error(`Server returned ${res.status}`);
        blob = await res.blob();
      }
      
      if (!blob || blob.size === 0) {
        throw new Error("Empty blob");
      }
      
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = filename;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
      
      M.showToast(`Downloaded: ${filename}`);
    } catch (e) {
      console.error("Download error:", e);
      M.showToast(`Download failed: ${e.message}`, "error");
    } finally {
      isDownloading = false;
    }
  }
  
  // Export all cached tracks
  M.exportAllCached = async function() {
    if (isExporting) {
      M.showToast("Export already in progress", "warning");
      return;
    }
    
    const cachedIds = [...M.cachedTracks];
    if (cachedIds.length === 0) {
      M.showToast("No cached tracks to export", "warning");
      return;
    }
    
    const trackMap = new Map();
    M.library.forEach(t => { if (t.filename) trackMap.set(t.id, t.filename); });
    M.queue.forEach(t => { if (t.filename && !trackMap.has(t.id)) trackMap.set(t.id, t.filename); });
    
    exportQueue = cachedIds
      .filter(id => trackMap.has(id))
      .map(id => ({ id, filename: trackMap.get(id) }));
    
    if (exportQueue.length === 0) {
      M.showToast("No exportable tracks found", "warning");
      return;
    }
    
    isExporting = true;
    M.showToast(`Exporting ${exportQueue.length} tracks...`);
    
    let exported = 0;
    for (const { id, filename } of exportQueue) {
      if (!isExporting) break;
      
      try {
        const cached = await TrackStorage.get(id);
        if (cached && cached.blob) {
          const url = URL.createObjectURL(cached.blob);
          const a = document.createElement("a");
          a.href = url;
          a.download = filename;
          document.body.appendChild(a);
          a.click();
          document.body.removeChild(a);
          URL.revokeObjectURL(url);
          exported++;
          await new Promise(r => setTimeout(r, 500));
        }
      } catch (e) {
        console.error(`Export error for ${filename}:`, e);
      }
    }
    
    isExporting = false;
    exportQueue = [];
    M.showToast(`Exported ${exported} tracks`);
  };
  
  M.cancelExport = function() {
    if (isExporting) {
      isExporting = false;
      M.showToast("Export cancelled");
    }
  };

  // Update cache status for all tracks
  M.updateCacheStatus = async function() {
    const cached = await TrackStorage.list();
    
    // Migration: remove old filename-based cache entries
    const oldEntries = cached.filter(id => !id.startsWith("sha256:"));
    if (oldEntries.length > 0) {
      console.log("[Cache] Migrating: removing", oldEntries.length, "old entries");
      for (const oldId of oldEntries) {
        await TrackStorage.remove(oldId);
      }
      const updated = await TrackStorage.list();
      M.cachedTracks = new Set(updated);
    } else {
      M.cachedTracks = new Set(cached);
    }
    console.log("[Cache] Updated:", M.cachedTracks.size, "tracks cached");
  };

  // Debug functions
  M.debugCacheStatus = function() {
    if (!M.currentTrackId) {
      console.log("[Cache Debug] No current track");
      return;
    }
    const trackCache = M.getTrackCache(M.currentTrackId);
    console.log("[Cache Debug]", {
      trackId: M.currentTrackId.slice(0, 16) + "...",
      segments: `${trackCache.size}/${M.SEGMENTS}`,
      inCachedTracks: M.cachedTracks.has(M.currentTrackId),
      hasBlobUrl: M.trackBlobs.has(M.currentTrackId)
    });
  };

  M.debugCacheMismatch = function() {
    console.log("[Cache Mismatch Debug]");
    console.log("M.cachedTracks:", M.cachedTracks);
    console.log("M.queue tracks:");
    M.queue.forEach((t, i) => {
      const id = t.id || t.filename;
      console.log(`  [${i}] ${t.title?.slice(0, 30)} | cached: ${M.cachedTracks.has(id)}`);
    });
  };

  M.clearAllCaches = async function() {
    await TrackStorage.clear();
    M.cachedTracks.clear();
    M.trackCaches.clear();
    M.trackBlobs.clear();
    M.bulkDownloadStarted.clear();
    M.renderQueue();
    M.renderLibrary();
    console.log("[Cache] Cleared. Refresh the page.");
  };

  // Initialize containers
  function initContainers() {
    const queueEl = M.$("#queue");
    const libraryEl = M.$("#library");
    
    if (queueEl && !queueContainer) {
      queueContainer = M.trackContainer.createContainer({
        type: 'queue',
        element: queueEl,
        getTracks: () => M.queue,
        canReorder: true,
        onRender: () => M.updateNowPlayingBar()
      });
    }
    
    if (libraryEl && !libraryContainer) {
      libraryContainer = M.trackContainer.createContainer({
        type: 'library',
        element: libraryEl,
        getTracks: () => M.library,
        getFilteredTracks: () => {
          const query = M.librarySearchQuery.toLowerCase();
          if (!query) {
            return M.library.map((track, i) => ({ track, originalIndex: i }));
          }
          return M.library
            .map((track, i) => ({ track, originalIndex: i }))
            .filter(({ track }) => {
              const title = track.title?.trim() || track.filename || '';
              return title.toLowerCase().includes(query);
            });
        }
      });
    }
  }

  // Render functions
  M.renderQueue = function() {
    initContainers();
    if (queueContainer) {
      queueContainer.render();
    }
    updateQueueDuration();
  };

  function updateQueueDuration() {
    const el = M.$("#queue-duration");
    if (!el) return;
    const totalSecs = M.queue.reduce((sum, t) => sum + (t.duration || 0), 0);
    if (totalSecs === 0) {
      el.textContent = "";
      return;
    }
    const hours = Math.floor(totalSecs / 3600);
    const mins = Math.floor((totalSecs % 3600) / 60);
    const secs = Math.floor(totalSecs % 60);
    let text = "";
    if (hours > 0) text = `${hours}h ${mins}m`;
    else if (mins > 0) text = `${mins}m ${secs}s`;
    else text = `${secs}s`;
    el.textContent = `(${M.queue.length} tracks · ${text})`;
  }

  M.renderLibrary = function() {
    initContainers();
    if (libraryContainer) {
      libraryContainer.render();
    }
  };

  // Now-playing bar
  M.updateNowPlayingBar = function() {
    const bar = M.$("#now-playing-bar");
    if (!bar) return;
    
    const track = M.queue[M.currentIndex];
    if (!track) {
      bar.classList.add("hidden");
      return;
    }
    
    const title = track.title?.trim() || (track.id || track.filename || "Unknown").replace(/\.[^.]+$/, "");
    bar.innerHTML = `<span class="label">Now playing:</span> ${title}`;
    bar.title = title;
    bar.classList.remove("hidden");
  };

  M.scrollToCurrentTrack = function() {
    const container = M.$("#queue");
    if (!container) return;
    
    const activeTrack = container.querySelector(".track.active");
    if (activeTrack) {
      const containerRect = container.getBoundingClientRect();
      const trackRect = activeTrack.getBoundingClientRect();
      const trackTop = trackRect.top - containerRect.top + container.scrollTop;
      const targetTop = trackTop - (container.clientHeight - activeTrack.offsetHeight) / 2;
      const maxTop = Math.max(0, container.scrollHeight - container.clientHeight);

      container.scrollTo({
        top: Math.min(Math.max(0, targetTop), maxTop),
        behavior: "smooth"
      });
      container.scrollLeft = 0;

      if (window.scrollX !== 0) {
        window.scrollTo({ left: 0, top: window.scrollY, behavior: "auto" });
      }
    }
  };

  // Backwards compatibility
  M.clearSelections = function() {
    M.clearAllSelections();
    M.renderQueue();
    M.renderLibrary();
  };

  // Load library from server
  M.loadLibrary = async function() {
    try {
      const res = await fetch("/api/library");
      M.library = await res.json();
      M.renderLibrary();
    } catch (e) {
      console.warn("Failed to load library");
    }
  };

  // Setup event listeners
  document.addEventListener("DOMContentLoaded", () => {
    const bar = M.$("#now-playing-bar");
    if (bar) {
      bar.onclick = () => M.scrollToCurrentTrack();
    }
    
    const searchInput = M.$("#library-search");
    if (searchInput) {
      searchInput.addEventListener("input", (e) => {
        M.librarySearchQuery = e.target.value;
        M.renderLibrary();
      });
    }
  });
})();
