/**
 * ================================================================
 * NEOMORPH PLAYER – script.js
 * Logika utama pemutar musik dengan localStorage playlist
 * ================================================================
 * Fitur:
 *  - Playlist bawaan (demo) + penyimpanan localStorage
 *  - Play / Pause / Prev / Next
 *  - Progress bar interaktif (drag + klik)
 *  - Volume control interaktif (drag + klik)
 *  - Shuffle & Repeat (one / all)
 *  - Dark / Light mode (tersimpan di localStorage)
 *  - Animasi vinyl, equalizer bars, canvas album art
 *  - Like, Share, Toast notification
 *  - Pencarian playlist real-time
 *  - Animasi cover album berubah saat ganti lagu
 * ================================================================
 */

/* ============================================================
   1. DATA PLAYLIST BAWAAN
   Tambahkan / ubah data lagu di sini.
   - src   : path ke file audio (isi dengan file di assets/music/)
   - cover : warna gradient SVG yang digunakan jika tidak ada gambar
   - image : path ke gambar cover (kosongkan jika pakai SVG)
============================================================ */
const DEFAULT_PLAYLIST = [
  {
    id: 1,
    title: "Neon Dreams",
    artist: "Synthwave Studio",
    album: "Digital Horizons",
    genre: "Synthwave",
    duration: "3:42",
    durationSec: 222,
    src: "assets/music/song1.mp3",
    image: "",
    color1: "#7c5cbf",
    color2: "#e44d7b"
  },
  {
    id: 2,
    title: "Midnight Pulse",
    artist: "Luna Beats",
    album: "Dark Frequency",
    genre: "Electronic",
    duration: "4:15",
    durationSec: 255,
    src: "assets/music/song2.mp3",
    image: "",
    color1: "#06b6d4",
    color2: "#3b82f6"
  },
  {
    id: 3,
    title: "Golden Hour",
    artist: "Aria Waves",
    album: "Sunset Sessions",
    genre: "Chill",
    duration: "3:58",
    durationSec: 238,
    src: "assets/music/song3.mp3",
    image: "",
    color1: "#f59e0b",
    color2: "#ef4444"
  },
  {
    id: 4,
    title: "Cosmic Journey",
    artist: "Stellar Sound",
    album: "Universe",
    genre: "Ambient",
    duration: "5:20",
    durationSec: 320,
    src: "assets/music/song4.mp3",
    image: "",
    color1: "#8b5cf6",
    color2: "#06b6d4"
  },
  {
    id: 5,
    title: "Urban Flow",
    artist: "City Beats",
    album: "Metropolitan",
    genre: "Hip-Hop",
    duration: "3:30",
    durationSec: 210,
    src: "assets/music/song5.mp3",
    image: "",
    color1: "#10b981",
    color2: "#3b82f6"
  },
  {
    id: 6,
    title: "Tropical Breeze",
    artist: "Island Groove",
    album: "Paradise",
    genre: "Pop",
    duration: "2:55",
    durationSec: 175,
    src: "assets/music/song6.mp3",
    image: "",
    color1: "#f97316",
    color2: "#eab308"
  },
  {
    id: 7,
    title: "Deep Space",
    artist: "Nebula Orchestra",
    album: "Infinity",
    genre: "Orchestral",
    duration: "6:10",
    durationSec: 370,
    src: "assets/music/song7.mp3",
    image: "",
    color1: "#1d4ed8",
    color2: "#7c3aed"
  },
  {
    id: 8,
    title: "Electric Soul",
    artist: "Voltage Band",
    album: "Power Surge",
    genre: "Rock",
    duration: "4:02",
    durationSec: 242,
    src: "assets/music/song8.mp3",
    image: "",
    color1: "#dc2626",
    color2: "#ea580c"
  }
];

/* ============================================================
   2. STATE APLIKASI
============================================================ */
const state = {
  playlist:      [],          // Daftar lagu (dari localStorage atau default)
  currentIndex:  0,           // Indeks lagu yang sedang aktif
  isPlaying:     false,       // Status putar
  isShuffle:     false,       // Mode acak
  repeatMode:    'none',      // 'none' | 'one' | 'all'
  volume:        0.8,         // Volume (0 – 1)
  isMuted:       false,       // Status mute
  isLiked:       false,       // Status suka lagu ini
  progressDragging: false,    // Sedang drag progress bar?
  volumeDragging:   false,    // Sedang drag volume bar?
  filterText:    ''           // Teks pencarian playlist
};

/* ============================================================
   3. REFERENSI ELEMEN DOM
============================================================ */
const DOM = {
  body:           document.getElementById('app-body'),
  themeToggle:    document.getElementById('theme-toggle'),
  themeIcon:      document.getElementById('theme-icon'),

  // Player
  audio:          document.getElementById('audio-player'),
  albumRing:      document.getElementById('album-ring'),
  albumCanvas:    document.getElementById('album-canvas'),
  eqBars:         document.getElementById('eq-bars'),
  songTitle:      document.getElementById('song-title'),
  songArtist:     document.getElementById('song-artist'),
  songAlbum:      document.getElementById('song-album'),
  songGenre:      document.getElementById('song-genre'),

  btnPlay:        document.getElementById('btn-play'),
  playIcon:       document.getElementById('play-icon'),
  btnPrev:        document.getElementById('btn-prev'),
  btnNext:        document.getElementById('btn-next'),
  btnShuffle:     document.getElementById('btn-shuffle'),
  btnRepeat:      document.getElementById('btn-repeat'),

  // Progress
  progressContainer: document.getElementById('progress-container'),
  progressFill:      document.getElementById('progress-fill'),
  progressThumb:     document.getElementById('progress-thumb'),
  currentTime:       document.getElementById('current-time'),
  totalTime:         document.getElementById('total-time'),

  // Volume
  volumeContainer: document.getElementById('volume-container'),
  volumeFill:      document.getElementById('volume-fill'),
  volumeThumb:     document.getElementById('volume-thumb'),
  volumeLabel:     document.getElementById('volume-label'),
  volumeIcon:      document.getElementById('volume-icon'),
  btnMute:         document.getElementById('btn-mute'),

  // Actions
  btnLike:         document.getElementById('btn-like'),
  likeIcon:        document.getElementById('like-icon'),
  btnShare:        document.getElementById('btn-share'),

  // Playlist
  playlistPanel:   document.getElementById('playlist-panel'),
  btnTogglePlaylist: document.getElementById('btn-toggle-playlist'),
  btnClosePlaylist: document.getElementById('btn-close-playlist'),
  playlistList:    document.getElementById('playlist-list'),
  playlistCount:   document.getElementById('playlist-count'),
  playlistSearch:  document.getElementById('playlist-search'),
  storageInfo:     document.getElementById('storage-info-text'),

  toast:           document.getElementById('toast')
};

/* ============================================================
   4. INISIALISASI APLIKASI
============================================================ */
function init() {
  loadTheme();
  loadPlaylist();
  loadVolume();
  renderPlaylist();
  loadCurrentIndex();
  loadSong(state.currentIndex, false);
  bindEvents();
  console.log('✅ NeumorphPlayer siap digunakan!');
}

/* ============================================================
   5. TEMA (DARK / LIGHT MODE)
============================================================ */
function loadTheme() {
  const saved = localStorage.getItem('nm_theme') || 'light-mode';
  DOM.body.className = saved;
  updateThemeIcon(saved);
}

function toggleTheme() {
  const isDark = DOM.body.classList.contains('dark-mode');
  const newTheme = isDark ? 'light-mode' : 'dark-mode';
  DOM.body.className = newTheme;
  localStorage.setItem('nm_theme', newTheme);
  updateThemeIcon(newTheme);
  showToast(isDark ? '☀️ Mode Terang aktif' : '🌙 Mode Gelap aktif');
}

function updateThemeIcon(theme) {
  DOM.themeIcon.className = theme === 'dark-mode'
    ? 'fa-solid fa-sun'
    : 'fa-solid fa-moon';
}

/* ============================================================
   6. PLAYLIST – LOAD & SIMPAN
============================================================ */
function loadPlaylist() {
  // Coba ambil dari localStorage, jika tidak ada gunakan default
  try {
    const saved = localStorage.getItem('nm_playlist');
    state.playlist = saved ? JSON.parse(saved) : DEFAULT_PLAYLIST;
  } catch (e) {
    console.warn('localStorage error, menggunakan playlist default:', e);
    state.playlist = DEFAULT_PLAYLIST;
  }

  // Simpan kembali (pastikan tersimpan)
  savePlaylist();
}

function savePlaylist() {
  try {
    localStorage.setItem('nm_playlist', JSON.stringify(state.playlist));
    DOM.storageInfo.textContent =
      `${state.playlist.length} lagu tersimpan di localStorage`;
  } catch (e) {
    console.warn('Gagal menyimpan playlist:', e);
  }
}

function loadCurrentIndex() {
  const saved = parseInt(localStorage.getItem('nm_index') || '0', 10);
  state.currentIndex = isNaN(saved) ? 0 : Math.min(saved, state.playlist.length - 1);
}

function saveCurrentIndex() {
  localStorage.setItem('nm_index', state.currentIndex);
}

function loadVolume() {
  const saved = parseFloat(localStorage.getItem('nm_volume') || '0.8');
  state.volume = isNaN(saved) ? 0.8 : saved;
  DOM.audio.volume = state.volume;
  updateVolumeUI(state.volume);
}

function saveVolume() {
  localStorage.setItem('nm_volume', state.volume);
}

/* ============================================================
   7. RENDER PLAYLIST
============================================================ */
function renderPlaylist() {
  const filter = state.filterText.toLowerCase().trim();

  // Filter lagu berdasarkan teks pencarian
  const items = state.playlist.filter(song =>
    song.title.toLowerCase().includes(filter) ||
    song.artist.toLowerCase().includes(filter) ||
    song.album.toLowerCase().includes(filter)
  );

  DOM.playlistList.innerHTML = '';
  DOM.playlistCount.textContent = `${state.playlist.length} lagu`;

  if (items.length === 0) {
    // Tampilkan empty state
    DOM.playlistList.innerHTML = `
      <li class="playlist-empty">
        <i class="fa-solid fa-music-slash"></i>
        <p>Tidak ada lagu ditemukan</p>
      </li>`;
    return;
  }

  items.forEach((song, idx) => {
    // Hitung indeks asli (bukan indeks hasil filter)
    const realIndex = state.playlist.findIndex(s => s.id === song.id);
    const isActive  = realIndex === state.currentIndex;
    const li = document.createElement('li');
    li.className = `playlist-item${isActive ? ' active' : ''}`;
    li.setAttribute('role', 'option');
    li.setAttribute('aria-selected', isActive ? 'true' : 'false');
    li.setAttribute('tabindex', '0');
    li.dataset.index = realIndex;

    // Gambar cover (SVG gradient sebagai fallback)
    const coverHtml = song.image
      ? `<img src="${song.image}" alt="Cover ${song.title}" class="item-cover" loading="lazy" />`
      : `<div class="item-cover-fallback" style="background:linear-gradient(135deg,${song.color1},${song.color2})">
           <i class="fa-solid fa-music"></i>
         </div>`;

    li.innerHTML = `
      <!-- Nomor urut / indikator equalizer saat aktif -->
      <div class="item-number">${idx + 1}</div>
      <div class="item-eq" aria-hidden="true">
        <span></span><span></span><span></span>
      </div>
      ${coverHtml}
      <div class="item-info">
        <div class="item-title">${escapeHtml(song.title)}</div>
        <div class="item-artist">${escapeHtml(song.artist)}</div>
      </div>
      <div class="item-duration">${song.duration}</div>
    `;

    // Klik item → putar lagu
    li.addEventListener('click', () => {
      playSongAtIndex(realIndex);
    });

    // Keyboard: Enter atau Spasi
    li.addEventListener('keydown', (e) => {
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        playSongAtIndex(realIndex);
      }
    });

    DOM.playlistList.appendChild(li);
  });

  // Scroll ke item aktif
  scrollToActive();
}

function scrollToActive() {
  const active = DOM.playlistList.querySelector('.playlist-item.active');
  if (active) {
    active.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
  }
}

/* ============================================================
   8. LOAD & TAMPILKAN LAGU
============================================================ */
function loadSong(index, autoPlay = false) {
  if (state.playlist.length === 0) return;

  const song = state.playlist[index];
  if (!song) return;

  // Update info lagu
  DOM.songTitle.textContent  = song.title;
  DOM.songArtist.textContent = song.artist;
  DOM.songAlbum.textContent  = song.album;
  DOM.songGenre.textContent  = song.genre;

  // Marquee untuk judul panjang
  if (song.title.length > 22) {
    DOM.songTitle.classList.add('marquee');
  } else {
    DOM.songTitle.classList.remove('marquee');
  }

  // Update durasi
  DOM.totalTime.textContent = song.duration;
  DOM.currentTime.textContent = '0:00';

  // Update progress
  updateProgress(0, song.durationSec);

  // Gambar cover di canvas
  drawAlbumArt(song);

  // Animasi cover pop saat ganti lagu
  DOM.albumRing.classList.add('track-change');
  setTimeout(() => DOM.albumRing.classList.remove('track-change'), 400);

  // Set sumber audio
  DOM.audio.src = song.src;
  DOM.audio.volume = state.isMuted ? 0 : state.volume;
  DOM.audio.load();

  // Reset like per lagu
  state.isLiked = false;
  updateLikeUI();

  // Simpan indeks saat ini
  saveCurrentIndex();

  if (autoPlay) {
    DOM.audio.play().then(() => {
      setPlayState(true);
    }).catch(err => {
      console.warn('Autoplay diblokir:', err);
      setPlayState(false);
      showToast('⚠️ Tambahkan file audio di assets/music/');
    });
  } else {
    setPlayState(false);
  }

  // Auto-close playlist di mobile jika dipilih
  if (DOM.playlistPanel.classList.contains('show-playlist')) {
    DOM.playlistPanel.classList.remove('show-playlist');
  }

  // Highlight list
  renderPlaylist();
}

/* ============================================================
   9. CANVAS – ALBUM ART (SVG Gradient Fallback)
============================================================ */
function drawAlbumArt(song) {
  const canvas = DOM.albumCanvas;
  const ctx    = canvas.getContext('2d');
  const W = canvas.width, H = canvas.height;
  const cx = W / 2, cy = H / 2, r = W / 2;

  // Jika ada gambar → gambar ke canvas
  if (song.image) {
    const img = new Image();
    img.onload = () => {
      ctx.clearRect(0, 0, W, H);
      ctx.save();
      ctx.beginPath();
      ctx.arc(cx, cy, r, 0, Math.PI * 2);
      ctx.closePath();
      ctx.clip();
      ctx.drawImage(img, 0, 0, W, H);
      ctx.restore();
      drawVinylOverlay(ctx, cx, cy, r);
    };
    img.onerror = () => drawGradientArt(ctx, W, H, cx, cy, r, song);
    img.src = song.image;
  } else {
    drawGradientArt(ctx, W, H, cx, cy, r, song);
  }
}

/* Gambar cover gradient dengan pola dekoratif */
function drawGradientArt(ctx, W, H, cx, cy, r, song) {
  ctx.clearRect(0, 0, W, H);
  ctx.save();

  // Clip lingkaran
  ctx.beginPath();
  ctx.arc(cx, cy, r, 0, Math.PI * 2);
  ctx.closePath();
  ctx.clip();

  // Gradient radial utama
  const grad = ctx.createRadialGradient(cx * 0.6, cy * 0.6, 0, cx, cy, r);
  grad.addColorStop(0, song.color1);
  grad.addColorStop(1, song.color2);
  ctx.fillStyle = grad;
  ctx.fillRect(0, 0, W, H);

  // Pola gelombang dekoratif
  ctx.globalAlpha = 0.12;
  for (let i = 0; i < 5; i++) {
    ctx.beginPath();
    ctx.arc(cx + (i - 2) * 20, cy + (i - 2) * 10, r * (0.3 + i * 0.12), 0, Math.PI * 2);
    ctx.strokeStyle = '#ffffff';
    ctx.lineWidth = 2;
    ctx.stroke();
  }

  // Ikon musik di tengah
  ctx.globalAlpha = 0.9;
  ctx.fillStyle = 'rgba(255,255,255,0.85)';
  ctx.font = `bold ${W * 0.28}px "Font Awesome 6 Free"`;
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText('\uf001', cx, cy); // fa-music unicode

  ctx.restore();

  // Overlay vinyl
  drawVinylOverlay(ctx, cx, cy, r);
}

/* Overlay cincin vinyl di atas cover */
function drawVinylOverlay(ctx, cx, cy, r) {
  ctx.save();

  // Cincin luar gelap
  ctx.beginPath();
  ctx.arc(cx, cy, r - 2, 0, Math.PI * 2);
  ctx.strokeStyle = 'rgba(0,0,0,0.25)';
  ctx.lineWidth = 4;
  ctx.stroke();

  // Lubang tengah vinyl
  ctx.beginPath();
  ctx.arc(cx, cy, r * 0.12, 0, Math.PI * 2);
  ctx.fillStyle = 'rgba(0,0,0,0.5)';
  ctx.fill();

  // Highlight tengah
  ctx.beginPath();
  ctx.arc(cx, cy, r * 0.06, 0, Math.PI * 2);
  ctx.fillStyle = 'rgba(255,255,255,0.7)';
  ctx.fill();

  ctx.restore();
}

/* ============================================================
   10. KONTROL PUTAR
============================================================ */
function togglePlayPause() {
  if (!state.playlist.length) {
    showToast('⚠️ Playlist kosong!');
    return;
  }

  if (DOM.audio.paused || DOM.audio.ended) {
    DOM.audio.play().then(() => {
      setPlayState(true);
    }).catch(err => {
      console.warn('Play gagal:', err);
      showToast('⚠️ File audio tidak ditemukan di assets/music/');
    });
  } else {
    DOM.audio.pause();
    setPlayState(false);
  }
}

function setPlayState(playing) {
  state.isPlaying = playing;
  DOM.playIcon.className = playing ? 'fa-solid fa-pause' : 'fa-solid fa-play';

  // Animasi vinyl berputar
  if (playing) {
    DOM.albumRing.classList.add('spinning');
    DOM.eqBars.classList.add('active');
  } else {
    DOM.albumRing.classList.remove('spinning');
    DOM.eqBars.classList.remove('active');
  }
}

function playNext() {
  if (!state.playlist.length) return;
  let next;

  if (state.isShuffle) {
    // Pilih acak yang berbeda dari saat ini
    do {
      next = Math.floor(Math.random() * state.playlist.length);
    } while (next === state.currentIndex && state.playlist.length > 1);
  } else {
    next = (state.currentIndex + 1) % state.playlist.length;
  }

  state.currentIndex = next;
  loadSong(state.currentIndex, true);
}

function playPrev() {
  if (!state.playlist.length) return;

  // Jika sudah lebih dari 3 detik → restart lagu saat ini
  if (DOM.audio.currentTime > 3) {
    DOM.audio.currentTime = 0;
    return;
  }

  let prev;
  if (state.isShuffle) {
    do {
      prev = Math.floor(Math.random() * state.playlist.length);
    } while (prev === state.currentIndex && state.playlist.length > 1);
  } else {
    prev = (state.currentIndex - 1 + state.playlist.length) % state.playlist.length;
  }

  state.currentIndex = prev;
  loadSong(state.currentIndex, true);
}

function playSongAtIndex(index) {
  if (index === state.currentIndex && state.isPlaying) {
    // Lagu sama → toggle play/pause
    togglePlayPause();
    return;
  }
  state.currentIndex = index;
  loadSong(index, true);
}

/* ============================================================
   11. SHUFFLE & REPEAT
============================================================ */
function toggleShuffle() {
  state.isShuffle = !state.isShuffle;
  DOM.btnShuffle.classList.toggle('is-active', state.isShuffle);
  showToast(state.isShuffle ? '🔀 Mode Acak aktif' : '🔀 Mode Acak nonaktif');
}

function toggleRepeat() {
  // Siklus: none → all → one → none
  const modes = ['none', 'all', 'one'];
  const i = modes.indexOf(state.repeatMode);
  state.repeatMode = modes[(i + 1) % modes.length];

  const icons = {
    none: 'fa-solid fa-repeat',
    all:  'fa-solid fa-repeat',
    one:  'fa-solid fa-repeat-1'
  };
  const labels = {
    none: '➡️ Ulangi: Tidak',
    all:  '🔁 Ulangi Semua aktif',
    one:  '🔂 Ulangi Satu aktif'
  };

  DOM.btnRepeat.querySelector('i').className = icons[state.repeatMode];
  DOM.btnRepeat.classList.toggle('is-active', state.repeatMode !== 'none');
  showToast(labels[state.repeatMode]);
}

/* ============================================================
   12. PROGRESS BAR
============================================================ */
function updateProgress(currentSec, totalSec) {
  if (!totalSec || isNaN(totalSec)) return;
  const pct = Math.min((currentSec / totalSec) * 100, 100);
  DOM.progressFill.style.width  = pct + '%';
  DOM.progressThumb.style.left  = pct + '%';
  DOM.progressContainer.setAttribute('aria-valuenow', Math.round(pct));
  DOM.currentTime.textContent = formatTime(currentSec);
}

function seekToPosition(clientX) {
  const rect = DOM.progressContainer.querySelector('.progress-track').getBoundingClientRect();
  const ratio = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
  const duration = DOM.audio.duration || state.playlist[state.currentIndex]?.durationSec || 0;
  DOM.audio.currentTime = ratio * duration;
}

/* ============================================================
   13. VOLUME CONTROL
============================================================ */
function setVolume(ratio) {
  state.volume = Math.max(0, Math.min(1, ratio));
  DOM.audio.volume = state.isMuted ? 0 : state.volume;
  updateVolumeUI(state.volume);
  saveVolume();

  // Auto unmute saat volume digeser
  if (state.isMuted && state.volume > 0) {
    state.isMuted = false;
    updateVolumeIcon();
  }
}

function updateVolumeUI(vol) {
  const pct = vol * 100;
  DOM.volumeFill.style.width  = pct + '%';
  DOM.volumeThumb.style.left  = pct + '%';
  DOM.volumeLabel.textContent = Math.round(pct) + '%';
  DOM.volumeContainer.setAttribute('aria-valuenow', Math.round(pct));
  updateVolumeIcon();
}

function updateVolumeIcon() {
  const v = state.isMuted ? 0 : state.volume;
  if (v === 0)       DOM.volumeIcon.className = 'fa-solid fa-volume-xmark';
  else if (v < 0.4)  DOM.volumeIcon.className = 'fa-solid fa-volume-low';
  else               DOM.volumeIcon.className = 'fa-solid fa-volume-high';
}

function seekVolume(clientX) {
  const rect = DOM.volumeContainer.querySelector('.volume-track').getBoundingClientRect();
  const ratio = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
  setVolume(ratio);
}

function toggleMute() {
  state.isMuted = !state.isMuted;
  DOM.audio.volume = state.isMuted ? 0 : state.volume;
  updateVolumeIcon();
  showToast(state.isMuted ? '🔇 Suara dimatikan' : '🔊 Suara dihidupkan');
}

/* ============================================================
   14. LIKE & SHARE
============================================================ */
function toggleLike() {
  state.isLiked = !state.isLiked;
  updateLikeUI();
  const song = state.playlist[state.currentIndex];
  showToast(state.isLiked
    ? `❤️ "${song?.title}" disukai!`
    : `🤍 Like dihapus`
  );
}

function updateLikeUI() {
  DOM.likeIcon.className = state.isLiked
    ? 'fa-solid fa-heart'
    : 'fa-regular fa-heart';
  DOM.likeIcon.style.color = state.isLiked ? '#e44d7b' : '';
}

function shareSong() {
  const song = state.playlist[state.currentIndex];
  if (!song) return;
  const text = `Dengarkan "${song.title}" oleh ${song.artist} di NeumorphPlayer!`;

  if (navigator.share) {
    navigator.share({ title: song.title, text }).catch(() => {});
  } else {
    navigator.clipboard.writeText(text)
      .then(() => showToast('📋 Info lagu disalin!'))
      .catch(() => showToast('ℹ️ ' + text));
  }
}

/* ============================================================
   15. FORMAT WAKTU
============================================================ */
function formatTime(seconds) {
  if (!seconds || isNaN(seconds)) return '0:00';
  const m = Math.floor(seconds / 60);
  const s = Math.floor(seconds % 60).toString().padStart(2, '0');
  return `${m}:${s}`;
}

/* ============================================================
   16. TOAST NOTIFICATION
============================================================ */
let toastTimer = null;
function showToast(message, duration = 2500) {
  clearTimeout(toastTimer);
  DOM.toast.textContent = message;
  DOM.toast.classList.add('show');
  toastTimer = setTimeout(() => DOM.toast.classList.remove('show'), duration);
}

/* ============================================================
   17. PENCARIAN PLAYLIST
============================================================ */
function handleSearch(e) {
  state.filterText = e.target.value;
  renderPlaylist();
}

/* ============================================================
   18. ESCAPE HTML (keamanan)
============================================================ */
function escapeHtml(str) {
  return String(str)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

/* ============================================================
   19. BINDING SEMUA EVENT LISTENER
============================================================ */
function bindEvents() {

  /* ── Tema ─────────────────────────────────────────────── */
  DOM.themeToggle.addEventListener('click', toggleTheme);

  /* ── Kontrol Putar ────────────────────────────────────── */
  DOM.btnPlay.addEventListener('click', togglePlayPause);
  DOM.btnNext.addEventListener('click', playNext);
  DOM.btnPrev.addEventListener('click', playPrev);
  DOM.btnShuffle.addEventListener('click', toggleShuffle);
  DOM.btnRepeat.addEventListener('click', toggleRepeat);

  /* ── Like & Share ─────────────────────────────────────── */
  DOM.btnLike.addEventListener('click', toggleLike);
  DOM.btnShare.addEventListener('click', shareSong);

  /* ── Mute ─────────────────────────────────────────────── */
  DOM.btnMute.addEventListener('click', toggleMute);

  /* ── Playlist Slide-Up (Mobile) ───────────────────────── */
  if (DOM.btnTogglePlaylist) {
    DOM.btnTogglePlaylist.addEventListener('click', () => {
      DOM.playlistPanel.classList.add('show-playlist');
    });
  }
  if (DOM.btnClosePlaylist) {
    DOM.btnClosePlaylist.addEventListener('click', () => {
      DOM.playlistPanel.classList.remove('show-playlist');
    });
  }

  /* ── Audio Events ─────────────────────────────────────── */
  DOM.audio.addEventListener('timeupdate', () => {
    if (state.progressDragging) return;
    const cur  = DOM.audio.currentTime;
    const dur  = DOM.audio.duration || state.playlist[state.currentIndex]?.durationSec || 0;
    updateProgress(cur, dur);
  });

  DOM.audio.addEventListener('loadedmetadata', () => {
    const dur = DOM.audio.duration;
    DOM.totalTime.textContent = formatTime(dur);
    updateProgress(0, dur);
  });

  DOM.audio.addEventListener('ended', handleSongEnd);

  DOM.audio.addEventListener('error', () => {
    showToast('⚠️ File audio tidak ditemukan. Tambahkan MP3 ke assets/music/');
    setPlayState(false);
  });

  /* ── Pencarian Playlist ───────────────────────────────── */
  DOM.playlistSearch.addEventListener('input', handleSearch);

  /* ── Progress Bar (Mouse + Touch) ────────────────────── */
  DOM.progressContainer.addEventListener('click', (e) => {
    if (!state.progressDragging) seekToPosition(e.clientX);
  });

  DOM.progressContainer.addEventListener('mousedown', (e) => {
    state.progressDragging = true;
    seekToPosition(e.clientX);
  });

  document.addEventListener('mousemove', (e) => {
    if (state.progressDragging) seekToPosition(e.clientX);
  });

  document.addEventListener('mouseup', () => {
    state.progressDragging = false;
  });

  // Touch support untuk progress bar
  DOM.progressContainer.addEventListener('touchstart', (e) => {
    state.progressDragging = true;
    seekToPosition(e.touches[0].clientX);
  }, { passive: true });

  document.addEventListener('touchmove', (e) => {
    if (state.progressDragging) seekToPosition(e.touches[0].clientX);
  }, { passive: true });

  document.addEventListener('touchend', () => {
    state.progressDragging = false;
  });

  /* ── Volume Bar (Mouse + Touch) ──────────────────────── */
  DOM.volumeContainer.addEventListener('click', (e) => {
    if (!state.volumeDragging) seekVolume(e.clientX);
  });

  DOM.volumeContainer.addEventListener('mousedown', (e) => {
    state.volumeDragging = true;
    seekVolume(e.clientX);
  });

  document.addEventListener('mousemove', (e) => {
    if (state.volumeDragging) seekVolume(e.clientX);
  });

  document.addEventListener('mouseup', () => {
    state.volumeDragging = false;
  });

  // Touch support untuk volume bar
  DOM.volumeContainer.addEventListener('touchstart', (e) => {
    state.volumeDragging = true;
    seekVolume(e.touches[0].clientX);
  }, { passive: true });

  document.addEventListener('touchmove', (e) => {
    if (state.volumeDragging) seekVolume(e.touches[0].clientX);
  }, { passive: true });

  document.addEventListener('touchend', () => {
    state.volumeDragging = false;
  });

  /* ── Keyboard Shortcut ────────────────────────────────── */
  document.addEventListener('keydown', (e) => {
    // Abaikan jika sedang mengetik di input
    if (['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)) return;

    switch (e.code) {
      case 'Space':       e.preventDefault(); togglePlayPause(); break;
      case 'ArrowRight':  e.preventDefault(); playNext();         break;
      case 'ArrowLeft':   e.preventDefault(); playPrev();         break;
      case 'ArrowUp':     e.preventDefault(); setVolume(state.volume + 0.05); break;
      case 'ArrowDown':   e.preventDefault(); setVolume(state.volume - 0.05); break;
      case 'KeyM':        toggleMute();         break;
      case 'KeyS':        toggleShuffle();      break;
      case 'KeyR':        toggleRepeat();       break;
      case 'KeyL':        toggleLike();         break;
    }
  });

  /* ── Media Session API (notifikasi sistem OS) ─────────── */
  if ('mediaSession' in navigator) {
    navigator.mediaSession.setActionHandler('play',         togglePlayPause);
    navigator.mediaSession.setActionHandler('pause',        togglePlayPause);
    navigator.mediaSession.setActionHandler('nexttrack',    playNext);
    navigator.mediaSession.setActionHandler('previoustrack',playPrev);
  }
}

/* ============================================================
   20. SAAT LAGU SELESAI
============================================================ */
function handleSongEnd() {
  switch (state.repeatMode) {
    case 'one':
      // Ulangi lagu yang sama
      DOM.audio.currentTime = 0;
      DOM.audio.play().then(() => setPlayState(true)).catch(() => {});
      break;
    case 'all':
      // Lagu berikutnya (loop)
      playNext();
      break;
    default:
      // Lagu berikutnya, jika sudah akhir berhenti
      if (state.currentIndex < state.playlist.length - 1) {
        playNext();
      } else {
        setPlayState(false);
        updateProgress(0, DOM.audio.duration);
        DOM.audio.currentTime = 0;
        showToast('✅ Playlist selesai diputar');
      }
  }
}

/* ============================================================
   21. MEDIA SESSION UPDATE (metadata untuk OS)
============================================================ */
function updateMediaSession(song) {
  if (!('mediaSession' in navigator) || !song) return;
  navigator.mediaSession.metadata = new MediaMetadata({
    title:  song.title,
    artist: song.artist,
    album:  song.album
  });
}

/* ============================================================
   22. JALANKAN APLIKASI
============================================================ */
document.addEventListener('DOMContentLoaded', init);
