(function () {
  // Songs are loaded dynamically from music-list.php on page load.
  // Drop an .mp3 into the /music folder and it appears here automatically.
  let SONGS = [];

  // Derive a readable title from the filename (just strips the extension).
  function titleFromFile(filename) {
    return filename.replace(/\.mp3$/i, "");
  }

  async function loadSongs() {
    let files = null;
    // 1. Try PHP first — the live server picks up new mp3s automatically.
    //    Skip on file:// since the browser logs CORS errors to console
    //    even when the catch swallows them.
    if (location.protocol !== "file:") {
      try {
        const response = await fetch("music-list.php", { cache: "no-store" });
        if (response.ok) {
          const data = await response.json();
          if (Array.isArray(data)) files = data;
        }
      } catch (err) {
        // PHP not available (offline, static host) — fall through.
      }
    }
    // 2. Fall back to the build-time bundled list (window.__musicList from
    //    music-list.js). Makes the offline zip work without PHP.
    if (!files && Array.isArray(window.__musicList)) {
      files = window.__musicList;
    }
    SONGS = (files || []).map((file) => ({ file: file, title: titleFromFile(file) }));
    renderList("");
    if (SONGS.length === 0) {
      const tt = (window.i18n && window.i18n.t) ? window.i18n.t : (k, f) => f;
      countEl.textContent = tt("page.music.empty", "No songs found");
    }
  }

  // Re-render when language changes (counter text uses translated strings)
  window.addEventListener("langchange", () => {
    if (SONGS.length === 0) {
      const tt = (window.i18n && window.i18n.t) ? window.i18n.t : (k, f) => f;
      countEl.textContent = tt("page.music.empty", "No songs found");
    } else {
      renderList(searchEl.value || "");
    }
  });

  const audio = new Audio();
  audio.preload = "metadata";
  let currentIndex = -1;
  let prevVolume = 0.85;

  // Persist volume + mute across visits
  const VOL_KEY = "wuys-volume";
  const MUTED_KEY = "wuys-muted";

  function savePref(key, value) {
    try { localStorage.setItem(key, String(value)); } catch (e) { /* private mode */ }
  }
  function loadPref(key) {
    try { return localStorage.getItem(key); } catch (e) { return null; }
  }

  // Restore saved volume (default 0.85 for first-time visitors)
  const savedVol = loadPref(VOL_KEY);
  if (savedVol !== null) {
    const v = parseFloat(savedVol);
    if (!isNaN(v) && v >= 0 && v <= 1) {
      audio.volume = v;
      if (v > 0) prevVolume = v;
    } else {
      audio.volume = 0.85;
    }
  } else {
    audio.volume = 0.85;
  }
  if (loadPref(MUTED_KEY) === "true") {
    audio.muted = true;
  }

  const listEl = document.getElementById("song-list");
  const searchEl = document.getElementById("music-search");
  const countEl = document.getElementById("music-count");
  const player = document.getElementById("sticky-player");
  const titleEl = document.getElementById("player-title");
  const timeEl = document.getElementById("player-time");
  const fillEl = document.getElementById("player-progress-fill");
  const progressEl = document.getElementById("player-progress");
  const playBtn = document.getElementById("player-play");
  const prevBtn = document.getElementById("player-prev");
  const nextBtn = document.getElementById("player-next");
  const closeBtn = document.getElementById("player-close");
  const toggleBtn = document.getElementById("player-toggle");
  const volSlider = document.getElementById("player-vol");
  const muteBtn = document.getElementById("player-mute");
  const downloadBtn = document.getElementById("player-download");

  function songURL(file) {
    return "music/" + encodeURIComponent(file);
  }

  // Force a real download (browsers often stream MP3s otherwise)
  async function downloadFile(filename, sourceEl) {
    const url = songURL(filename);
    if (sourceEl) sourceEl.classList.add("downloading");
    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error("Network response was not ok");
      const blob = await response.blob();
      const objectUrl = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = objectUrl;
      a.download = filename;
      a.style.display = "none";
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      setTimeout(() => URL.revokeObjectURL(objectUrl), 1500);
    } catch (err) {
      // Fallback: direct link with download attribute
      const a = document.createElement("a");
      a.href = url;
      a.download = filename;
      a.style.display = "none";
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    } finally {
      if (sourceEl) {
        setTimeout(() => sourceEl.classList.remove("downloading"), 600);
      }
    }
  }

  function fmt(t) {
    if (!isFinite(t) || t < 0) return "0:00";
    const m = Math.floor(t / 60);
    const s = Math.floor(t % 60).toString().padStart(2, "0");
    return m + ":" + s;
  }

  function renderList(filter) {
    const q = (filter || "").trim().toLowerCase();
    const rows = [];
    let visible = 0;
    SONGS.forEach((s, i) => {
      const hit = !q || s.title.toLowerCase().includes(q);
      if (!hit) return;
      visible++;
      rows.push(`
        <div class="song-row${i === currentIndex ? " playing" : ""}" data-index="${i}">
          <span class="song-num">${String(i + 1).padStart(2, "0")}</span>
          <button class="song-play" data-index="${i}" aria-label="Play ${s.title.replace(/"/g, "&quot;")}">
            <span class="song-play-icon">${i === currentIndex && !audio.paused ? "⏸" : "▶"}</span>
            <span class="eq-bars"><i></i><i></i><i></i><i></i></span>
          </button>
          <div class="song-title">${s.title}</div>
          <a class="song-download" href="${songURL(s.file)}" download="${s.file.replace(/"/g, "&quot;")}" aria-label="Download ${s.title.replace(/"/g, "&quot;")}">↓</a>
        </div>
      `);
    });
    listEl.innerHTML = rows.join("");
    const tt = (window.i18n && window.i18n.t) ? window.i18n.t : (k, f) => f;
    countEl.textContent = visible === SONGS.length
      ? SONGS.length + " " + tt("page.music.songs", "songs")
      : visible + " " + tt("page.music.of", "of") + " " + SONGS.length;
  }

  function playSong(index) {
    if (index < 0 || index >= SONGS.length) return;
    currentIndex = index;
    audio.src = songURL(SONGS[index].file);
    audio.play().catch(() => {});
    showPlayer();
    syncUI();
  }

  function togglePlay() {
    if (currentIndex < 0) {
      playSong(0);
      return;
    }
    if (audio.paused) audio.play().catch(() => {});
    else audio.pause();
  }

  function nextSong() {
    if (currentIndex < 0) return playSong(0);
    playSong((currentIndex + 1) % SONGS.length);
  }

  function prevSong() {
    if (currentIndex < 0) return playSong(0);
    playSong((currentIndex - 1 + SONGS.length) % SONGS.length);
  }

  function closePlayer() {
    audio.pause();
    audio.currentTime = 0;
    audio.removeAttribute("src");
    audio.load();
    currentIndex = -1;
    player.classList.remove("visible");
    player.setAttribute("aria-hidden", "true");
    syncUI();
  }

  function showPlayer() {
    player.classList.add("visible");
    player.setAttribute("aria-hidden", "false");
  }

  function syncUI() {
    const playing = currentIndex >= 0 && !audio.paused;
    if (currentIndex >= 0) {
      titleEl.textContent = SONGS[currentIndex].title;
    } else {
      titleEl.textContent = "—";
      fillEl.style.width = "0%";
      timeEl.textContent = "0:00 / 0:00";
    }
    playBtn.textContent = playing ? "⏸" : "▶";
    player.classList.toggle("paused", currentIndex >= 0 && audio.paused);
    downloadBtn.disabled = currentIndex < 0;

    // Update each song row's icon + playing class
    document.querySelectorAll(".song-row").forEach((row) => {
      const idx = parseInt(row.dataset.index, 10);
      const isCurrent = idx === currentIndex;
      row.classList.toggle("playing", isCurrent);
      row.classList.toggle("paused", isCurrent && audio.paused);
      const icon = row.querySelector(".song-play-icon");
      if (icon) icon.textContent = isCurrent && !audio.paused ? "⏸" : "▶";
    });
  }

  function syncVolume() {
    const v = audio.muted ? 0 : audio.volume;
    volSlider.value = audio.muted ? 0 : audio.volume;
    volSlider.style.setProperty("--vol", Math.round(v * 100) + "%");
    if (audio.muted || audio.volume === 0) {
      muteBtn.textContent = "🔇";
    } else if (audio.volume < 0.5) {
      muteBtn.textContent = "🔉";
    } else {
      muteBtn.textContent = "🔊";
    }
  }

  function toggleCollapse() {
    const collapsed = player.classList.toggle("collapsed");
    toggleBtn.textContent = collapsed ? "‹" : "›";
    toggleBtn.setAttribute("aria-label", collapsed ? "Expand player" : "Collapse player");
  }

  // ---- Event wiring ----

  // Click delegation for play and download buttons in the list
  listEl.addEventListener("click", (e) => {
    const dl = e.target.closest(".song-download");
    if (dl) {
      e.preventDefault();
      const row = dl.closest(".song-row");
      const idx = parseInt(row.dataset.index, 10);
      downloadFile(SONGS[idx].file, dl);
      return;
    }
    const btn = e.target.closest(".song-play");
    if (btn) {
      const idx = parseInt(btn.dataset.index, 10);
      if (idx === currentIndex) togglePlay();
      else playSong(idx);
      return;
    }
    // Clicking the title row also plays
    const row = e.target.closest(".song-row");
    if (row) {
      const idx = parseInt(row.dataset.index, 10);
      if (idx === currentIndex) togglePlay();
      else playSong(idx);
    }
  });

  searchEl.addEventListener("input", (e) => renderList(e.target.value));

  playBtn.addEventListener("click", togglePlay);
  prevBtn.addEventListener("click", prevSong);
  nextBtn.addEventListener("click", nextSong);
  closeBtn.addEventListener("click", closePlayer);
  toggleBtn.addEventListener("click", toggleCollapse);

  downloadBtn.addEventListener("click", () => {
    if (currentIndex < 0) return;
    downloadFile(SONGS[currentIndex].file, downloadBtn);
  });

  volSlider.addEventListener("input", (e) => {
    const v = parseFloat(e.target.value);
    audio.volume = v;
    if (v > 0 && audio.muted) {
      audio.muted = false;
      savePref(MUTED_KEY, "false");
    }
    if (v > 0) prevVolume = v;
    savePref(VOL_KEY, v);
    syncVolume();
  });

  muteBtn.addEventListener("click", () => {
    if (audio.muted || audio.volume === 0) {
      audio.muted = false;
      audio.volume = prevVolume > 0 ? prevVolume : 0.85;
      savePref(VOL_KEY, audio.volume);
      savePref(MUTED_KEY, "false");
    } else {
      prevVolume = audio.volume;
      audio.muted = true;
      savePref(MUTED_KEY, "true");
    }
    syncVolume();
  });

  progressEl.addEventListener("click", (e) => {
    if (!audio.duration) return;
    const rect = progressEl.getBoundingClientRect();
    const pct = (e.clientX - rect.left) / rect.width;
    audio.currentTime = Math.max(0, Math.min(1, pct)) * audio.duration;
  });

  audio.addEventListener("timeupdate", () => {
    if (!audio.duration) return;
    const pct = (audio.currentTime / audio.duration) * 100;
    fillEl.style.width = pct + "%";
    timeEl.textContent = fmt(audio.currentTime) + " / " + fmt(audio.duration);
  });

  audio.addEventListener("loadedmetadata", () => {
    timeEl.textContent = "0:00 / " + fmt(audio.duration);
  });

  audio.addEventListener("ended", nextSong);
  audio.addEventListener("play", syncUI);
  audio.addEventListener("pause", syncUI);

  // Initial render — fetch song list from PHP, then render
  syncVolume();
  loadSongs();
})();
