/* MusicPopup — custom audio player with REAL playback via iTunes preview API.
   - Fetches each track's 30-second MP3 preview from iTunes Search API on demand
   - Also pulls the album artwork (artworkUrl100, upgraded to 600x600)
   - Standard <audio> element drives play/pause/seek/progress
   - Falls back to silent state if preview unavailable */

const { useState: useStateMP, useEffect: useEffectMP, useRef: useRefMP, useCallback: useCallbackMP } = React;

/* In-memory cache for iTunes lookups so we don't refetch on every track-change */
const ITUNES_CACHE = {};

async function fetchPreview(title, artist) {
  const key = title + '|' + artist;
  if (ITUNES_CACHE[key]) return ITUNES_CACHE[key];
  // Strip parenthetical/feat. annotations from artist for cleaner search
  const cleanArtist = artist.split(/[·•,]|feat\./i)[0].trim();
  const term = encodeURIComponent(`${title} ${cleanArtist}`);
  const url = `https://itunes.apple.com/search?term=${term}&entity=song&limit=1`;
  try {
    const r = await fetch(url);
    if (!r.ok) throw new Error(r.status);
    const j = await r.json();
    if (!j.results || !j.results.length) throw new Error('no results');
    const t = j.results[0];
    const out = {
      preview: t.previewUrl || null,
      art: (t.artworkUrl100 || '').replace('100x100', '600x600'),
      track: t.trackName,
      artist: t.artistName,
      album: t.collectionName,
      length: t.trackTimeMillis ? Math.round(t.trackTimeMillis / 1000) : null
    };
    ITUNES_CACHE[key] = out;
    return out;
  } catch (e) {
    const fallback = { preview: null, art: null, error: String(e) };
    ITUNES_CACHE[key] = fallback;
    return fallback;
  }
}

function fmtTime(s) {
  if (!s || !isFinite(s)) return '0:00';
  const m = Math.floor(s / 60);
  const sec = Math.floor(s % 60);
  return m + ':' + String(sec).padStart(2, '0');
}

function MusicPopup() {
  const queue = window.MUSIC_QUEUE || [];
  const [open, setOpen] = useStateMP(false);
  const [idx, setIdx] = useStateMP(0);
  const [meta, setMeta] = useStateMP({ loading: true, preview: null, art: null });
  const [playing, setPlaying] = useStateMP(false);
  const [time, setTime] = useStateMP(0);
  const [dur, setDur] = useStateMP(30); // iTunes previews are 30s
  const audioRef = useRefMP(null);
  const barRef = useRefMP(null);

  const cur = queue[idx] || { title: 'Radio', artist: '—', album: '—', dur: '—', jp: '音' };

  /* Fetch preview when track changes */
  useEffectMP(() => {
    let cancelled = false;
    setMeta({ loading: true, preview: null, art: null });
    setTime(0);
    fetchPreview(cur.title, cur.artist).then(r => {
      if (cancelled) return;
      setMeta({ loading: false, ...r });
    });
    return () => { cancelled = true; };
  }, [idx]);

  /* When preview URL arrives, load + autoplay if user has hit play before */
  useEffectMP(() => {
    const a = audioRef.current;
    if (!a || !meta.preview) return;
    a.src = meta.preview;
    a.load();
    if (playing) {
      a.play().catch(() => setPlaying(false));
    }
  }, [meta.preview]);

  /* Audio element event listeners */
  useEffectMP(() => {
    const a = audioRef.current;
    if (!a) return;
    const onTime = () => setTime(a.currentTime);
    const onMeta = () => setDur(a.duration || 30);
    const onEnd = () => {
      // auto-advance
      setIdx(i => (i + 1) % queue.length);
    };
    const onPlay = () => setPlaying(true);
    const onPause = () => setPlaying(false);
    a.addEventListener('timeupdate', onTime);
    a.addEventListener('loadedmetadata', onMeta);
    a.addEventListener('ended', onEnd);
    a.addEventListener('play', onPlay);
    a.addEventListener('pause', onPause);
    return () => {
      a.removeEventListener('timeupdate', onTime);
      a.removeEventListener('loadedmetadata', onMeta);
      a.removeEventListener('ended', onEnd);
      a.removeEventListener('play', onPlay);
      a.removeEventListener('pause', onPause);
    };
  }, [queue.length]);

  const togglePlay = () => {
    const a = audioRef.current;
    if (!a) return;
    if (a.paused) {
      a.play().then(() => setPlaying(true)).catch(() => setPlaying(false));
    } else {
      a.pause();
      setPlaying(false);
    }
  };
  const prev = () => setIdx(i => (i - 1 + queue.length) % queue.length);
  const next = () => setIdx(i => (i + 1) % queue.length);
  const seek = (e) => {
    const a = audioRef.current;
    if (!a || !barRef.current) return;
    const r = barRef.current.getBoundingClientRect();
    const ratio = Math.max(0, Math.min(1, (e.clientX - r.left) / r.width));
    a.currentTime = ratio * (a.duration || dur);
  };

  /* keyboard */
  useEffectMP(() => {
    if (!open) return;
    const onKey = (e) => {
      if (e.target.matches('input, textarea')) return;
      if (e.code === 'Escape') setOpen(false);
      else if (e.code === 'Space') { e.preventDefault(); togglePlay(); }
      else if (e.code === 'ArrowRight') next();
      else if (e.code === 'ArrowLeft') prev();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open]);

  const pct = dur ? (time / dur) * 100 : 0;

  return (
    <>
      {/* Floating trigger */}
      <button
        className={"mp-trigger " + (open ? "open" : "") + (playing ? " spinning" : "")}
        onClick={() => setOpen(o => !o)}
        aria-label="Open music player"
      >
        <span className="mp-disc">
          <span className="mp-disc-inner"></span>
          <span className="mp-disc-jp">{cur.jp}</span>
        </span>
        <span className="mp-trigger-meta">
          <span className="mp-trigger-now">{playing ? "NOW PLAYING" : "RADIO · IDLE"}</span>
          <span className="mp-trigger-title">{cur.title}</span>
        </span>
        <span className="mp-trigger-icon">{open ? "×" : "♪"}</span>
      </button>

      {/* Hidden audio element */}
      <audio ref={audioRef} preload="auto" crossOrigin="anonymous"></audio>

      {/* Slide-up panel */}
      <div className={"mp-panel " + (open ? "open" : "")} role="dialog" aria-label="Music player">
        <div className="mp-panel-head">
          <div className="mp-head-meta">
            <span className="num">005</span>
            <span className="lbl">RADIO · NOW PLAYING</span>
            <span className="jp">音楽</span>
          </div>
          <div className="mp-head-actions">
            <button className="mp-close" onClick={() => setOpen(false)} aria-label="Close">×</button>
          </div>
        </div>

        {/* Now-playing block */}
        <div className="mp-now">
          <div className="mp-art">
            <span className="mp-art-stripes"></span>
            <span className="mp-art-stamp">SIDE A · {String(idx + 1).padStart(2, '0')}</span>
            {meta.art ? (
              <img className="mp-art-img" src={meta.art} alt="" />
            ) : (
              <span className={"mp-art-disc " + (playing ? "spin" : "")}>
                <span className="mp-art-jp">{cur.jp}</span>
              </span>
            )}
          </div>
          <div className="mp-info">
            <div className="mp-status">
              <span className="dot"></span>
              {meta.loading ? "FETCHING …" : meta.preview ? (playing ? "PLAYING · 30S PREVIEW" : "READY · 30S PREVIEW") : "PREVIEW UNAVAILABLE"}
            </div>
            <div className="mp-title">{cur.title}</div>
            <div className="mp-artist">{cur.artist}</div>
            <div className="mp-album">{meta.album || cur.album} · {cur.dur}</div>

            <div className="mp-progress">
              <span className="mp-time">{fmtTime(time)}</span>
              <div ref={barRef} className="mp-bar" onClick={seek}>
                <div className="mp-bar-fill" style={{ width: pct + '%' }}></div>
                <div className="mp-bar-thumb" style={{ left: pct + '%' }}></div>
              </div>
              <span className="mp-time">{fmtTime(dur)}</span>
            </div>

            <div className="mp-controls">
              <button className="mp-btn" onClick={prev} title="Previous (←)">◀◀</button>
              <button
                className="mp-btn mp-btn-play"
                onClick={togglePlay}
                disabled={!meta.preview}
                title={playing ? "Pause (Space)" : "Play (Space)"}
              >
                {playing ? "❚❚" : "▶"}
              </button>
              <button className="mp-btn" onClick={next} title="Next (→)">▶▶</button>
              <span className="mp-spacer"></span>
              <button className="mp-btn mp-btn-ghost" title="Open on Spotify"
                onClick={() => {
                  const q = encodeURIComponent(cur.title + ' ' + cur.artist);
                  window.open('https://open.spotify.com/search/' + q, '_blank');
                }}
              >SPOTIFY ↗</button>
            </div>
          </div>
        </div>

        {/* Queue */}
        <div className="mp-queue-head">
          <span className="lbl">QUEUE</span>
          <span className="jp">列</span>
          <span className="dim">{queue.length} TRACKS</span>
        </div>
        <div className="mp-queue">
          {queue.map((t, i) => (
            <button
              key={i}
              className={"mp-row " + (i === idx ? "current" : "")}
              onClick={() => setIdx(i)}
            >
              <span className="mp-row-num">{String(i + 1).padStart(2, '0')}</span>
              <span className="mp-row-jp">{t.jp}</span>
              <span className="mp-row-title">{t.title}</span>
              <span className="mp-row-artist">{t.artist}</span>
              <span className="mp-row-dur">{t.dur}</span>
              {i === idx && playing && <span className="mp-row-eq"><span></span><span></span><span></span></span>}
            </button>
          ))}
        </div>
        <div className="mp-foot">
          <span>30-second previews via iTunes · click any track to play</span>
        </div>
      </div>

      {/* Backdrop */}
      <div className={"mp-backdrop " + (open ? "open" : "")} onClick={() => setOpen(false)}></div>
    </>
  );
}

window.MusicPopup = MusicPopup;
