/* player.jsx — davidyblue cassette music player (real audio) */

const { useState, useEffect, useRef, useCallback } = React;

const TRACKS = [
  { title: "A BLACK MAN'S TALE",   sub: 'DAVIDYBLUE',    file: "MusicChanger/A Black Man's Tale.mp3" },
  { title: 'A NEW DAWN',           sub: 'NEW DAY',        file: 'MusicChanger/A New Dawn, A New Day.mp3' },
  { title: 'ATA',                  sub: 'DAVIDYBLUE',    file: 'MusicChanger/ATA.mp3' },
  { title: 'BLACK HORIZON',        sub: 'DAVIDYBLUE',    file: 'MusicChanger/Black Horizon.mp3' },
  { title: 'CALL HER HOME',        sub: 'DAVIDYBLUE',    file: 'MusicChanger/Call Her Home.mp3' },
  { title: 'CEREMONY',             sub: 'OF THE LOST',   file: 'MusicChanger/Ceremony of the Lost.mp3' },
  { title: 'CHAIN-RATTLE HOLLOW',  sub: 'DAVIDYBLUE',    file: 'MusicChanger/Chain-Rattle Hollow.mp3' },
  { title: 'CHAIN-RATTLE HYMN',    sub: 'DAVIDYBLUE',    file: 'MusicChanger/Chain-Rattle Hymn.mp3' },
  { title: 'CHAIN-REVERB',         sub: 'TRIUMPHANT',    file: 'MusicChanger/Chain-Reverb Triumphant.mp3' },
  { title: 'CHAIN-LINK AMEN',      sub: 'DAVIDYBLUE',    file: 'MusicChanger/Chain-link Amen.mp3' },
  { title: 'CRAWL',                sub: 'THE MURK',      file: 'MusicChanger/Crawl.mp3' },
  { title: 'DEAD BRASS',           sub: 'DAVIDYBLUE',    file: 'MusicChanger/Dead Brass.mp3' },
  { title: 'DROWN',                sub: 'THE MURK',      file: 'MusicChanger/Drown.mp3' },
  { title: 'EARTH-OPENING HUM',    sub: 'THE MURK',      file: 'MusicChanger/Earth-Opening Hum.mp3' },
  { title: 'ECHOES',               sub: 'OF THE BANDINGS', file: 'MusicChanger/Echoes of the Bandings.mp3' },
  { title: 'ELEGY ENGINE',         sub: 'DAVIDYBLUE',    file: 'MusicChanger/Elegy Engine.mp3' },
  { title: 'FASHION FLAME',        sub: 'DAVIDYBLUE',    file: 'MusicChanger/Fashion Flame.mp3' },
  { title: 'HYMN FOR THE RIDE',    sub: 'DAVIDYBLUE',    file: 'MusicChanger/Hymn for the Ride.mp3' },
  { title: 'IDIOMFLOW',            sub: 'DAVIDYBLUE',    file: 'MusicChanger/IdiomFlow.mp3' },
  { title: 'INTO THE MURK',        sub: 'THE MURK',      file: 'MusicChanger/Into the Murk.mp3' },
  { title: 'KORA UNDERSTEPS',      sub: 'AURA',          file: 'MusicChanger/Kora Understeps.mp3' },
  { title: 'LOVE IN THE MURK',     sub: 'THE MURK',      file: 'MusicChanger/Love in the Murk.mp3' },
  { title: 'MUD FREQUENCY',        sub: 'THE MURK',      file: 'MusicChanger/Mud Frequency.mp3' },
  { title: 'MURK AIR',             sub: 'THE MURK',      file: 'MusicChanger/Murk Air.mp3' },
  { title: "PEARLINE'S PRODIGAL",  sub: 'DAVIDYBLUE',    file: "MusicChanger/Pearline's Prodigal.mp3" },
  { title: 'PRICKLED DEEPS',       sub: 'DAVIDYBLUE',    file: 'MusicChanger/Prickled deeps.mp3' },
  { title: 'PRICKLED DEEPS CH.02', sub: 'DAVIDYBLUE',    file: 'MusicChanger/Prickled deeps Chapter 02.mp3' },
  { title: 'PROCESSION FOR HER',   sub: 'DAVIDYBLUE',    file: 'MusicChanger/Procession for Her.mp3' },
  { title: "RAIDER'S THEME",       sub: 'SLUGFEST',      file: "MusicChanger/Raider's Theme.mp3" },
  { title: 'REMEMBRANCE',          sub: 'DAVIDYBLUE',    file: 'MusicChanger/Remembrance.mp3' },
  { title: 'SLIDE AND SORROW',     sub: 'DAVIDYBLUE',    file: 'MusicChanger/Slide and Sorrow.mp3' },
  { title: 'SPIRITS IN THE STATIC',sub: 'BLACKTRACK',    file: 'MusicChanger/Spirits in the Static.mp3' },
  { title: 'TALKING DRUM EYES',    sub: 'AURA',          file: 'MusicChanger/Talking Drum Eyes.mp3' },
  { title: 'TALKING DRUM LULLABY', sub: 'AURA',          file: 'MusicChanger/Talking Drum Lullaby.mp3' },
  { title: 'TALKING DRUM UNSEEN',  sub: 'AURA',          file: 'MusicChanger/Talking Drum Unseen.mp3' },
  { title: 'TALKING DRUM VEIL',    sub: 'AURA',          file: 'MusicChanger/Talking Drum Veil.mp3' },
  { title: 'THE RAIDER\'S THEME',  sub: 'SLUGFEST',      file: "MusicChanger/The Raider's Theme.mp3" },
  { title: 'THE TORN APART',       sub: 'DAVIDYBLUE',    file: 'MusicChanger/The Torn Apart.mp3' },
  { title: 'WEIGHT OF THE MURK',   sub: 'THE MURK',      file: 'MusicChanger/The Weight of the Murk.mp3' },
  { title: 'UNCONTROLLED',         sub: 'DAVIDYBLUE',    file: 'MusicChanger/Uncontrolled.mp3' },
  { title: 'WATERLINE KORA',       sub: 'GHOSTS',        file: 'MusicChanger/Waterline Kora Ghosts.mp3' },
];

function fmt(s) {
  if (!s || isNaN(s)) return '0:00';
  const m = Math.floor(s / 60);
  return `${m}:${String(Math.floor(s % 60)).padStart(2, '0')}`;
}

function MusicPlayer({ darkMode, embedded = false }) {
  const [open,        setOpen]        = useState(true);
  const [playing,     setPlaying]     = useState(false);
  const [trackIdx,    setTrackIdx]    = useState(0);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration,    setDuration]    = useState(0);
  const [volume,      setVolume]      = useState(75);
  const [muted,       setMuted]       = useState(false);
  const [listOpen,    setListOpen]    = useState(false);
  const [pos,         setPos]         = useState(null); // null = default bottom:20,left:20
  const audioRef  = useRef(null);
  const playerRef = useRef(null);
  const dragRef   = useRef({ active: false, startX: 0, startY: 0, originLeft: 0, originTop: 0 });

  const onHeaderMouseDown = useCallback((e) => {
    if (embedded) return;
    if (e.button !== 0) return;
    e.preventDefault();
    const rect = playerRef.current.getBoundingClientRect();
    dragRef.current = { active: true, startX: e.clientX, startY: e.clientY, originLeft: rect.left, originTop: rect.top };

    const onMove = (e) => {
      if (!dragRef.current.active) return;
      const dx = e.clientX - dragRef.current.startX;
      const dy = e.clientY - dragRef.current.startY;
      const el = playerRef.current;
      const maxX = window.innerWidth  - (el ? el.offsetWidth  : 288);
      const maxY = window.innerHeight - (el ? el.offsetHeight : 400);
      setPos({
        x: Math.max(0, Math.min(maxX, dragRef.current.originLeft + dx)),
        y: Math.max(0, Math.min(maxY, dragRef.current.originTop  + dy)),
      });
    };

    const onUp = () => {
      dragRef.current.active = false;
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup',   onUp);
    };

    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup',   onUp);
  }, [embedded]);

  /* ── Pause on external signal (video/game modal open) ── */
  useEffect(() => {
    const onPause = () => {
      audioRef.current?.pause();
      setPlaying(false);
    };
    window.addEventListener('dyb-pause-music', onPause);
    return () => window.removeEventListener('dyb-pause-music', onPause);
  }, []);

  /* ── Create audio element once ── */
  useEffect(() => {
    const audio = new Audio(TRACKS[0].file);
    audio.volume = 0.75;
    audioRef.current = audio;

    const onTime  = () => setCurrentTime(audio.currentTime);
    const onMeta  = () => setDuration(audio.duration);
    const onEnded = () => {
      setTrackIdx(i => {
        const next = (i + 1) % TRACKS.length;
        audio.src = TRACKS[next].file;
        audio.play().catch(() => {});
        return next;
      });
      setCurrentTime(0);
    };

    audio.addEventListener('timeupdate',     onTime);
    audio.addEventListener('loadedmetadata', onMeta);
    audio.addEventListener('ended',          onEnded);

    return () => {
      audio.removeEventListener('timeupdate',     onTime);
      audio.removeEventListener('loadedmetadata', onMeta);
      audio.removeEventListener('ended',          onEnded);
      audio.pause();
    };
  }, []);

  /* ── Sync volume / mute to audio element ── */
  useEffect(() => {
    if (!audioRef.current) return;
    audioRef.current.volume = muted ? 0 : volume / 100;
  }, [volume, muted]);

  /* ── Play / pause ── */
  useEffect(() => {
    if (!audioRef.current) return;
    if (playing) {
      audioRef.current.play().catch(() => setPlaying(false));
    } else {
      audioRef.current.pause();
    }
  }, [playing]);

  const goTrack = useCallback((i) => {
    if (!audioRef.current) return;
    audioRef.current.src = TRACKS[i].file;
    audioRef.current.load();
    audioRef.current.play().catch(() => {});
    setTrackIdx(i);
    setCurrentTime(0);
    setDuration(0);
    setPlaying(true);
  }, []);

  const prev      = useCallback(() => goTrack((trackIdx - 1 + TRACKS.length) % TRACKS.length), [trackIdx, goTrack]);
  const next      = useCallback(() => goTrack((trackIdx + 1) % TRACKS.length), [trackIdx, goTrack]);
  const randomize = useCallback(() => {
    let idx;
    do { idx = Math.floor(Math.random() * TRACKS.length); } while (idx === trackIdx && TRACKS.length > 1);
    goTrack(idx);
  }, [trackIdx, goTrack]);

  const seek = useCallback((frac) => {
    if (!audioRef.current || !duration) return;
    audioRef.current.currentTime = frac * duration;
    setCurrentTime(frac * duration);
  }, [duration]);

  const handleSeekClick = useCallback((e) => {
    const r = e.currentTarget.getBoundingClientRect();
    seek(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
  }, [seek]);

  const handleVolumeClick = useCallback((e) => {
    const r = e.currentTarget.getBoundingClientRect();
    const v = Math.round(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)) * 100);
    setVolume(v);
    setMuted(false);
  }, []);

  const progress = duration > 0 ? currentTime / duration : 0;
  const track    = TRACKS[trackIdx];

  /* ── colours driven by darkMode prop ── */
  const ink    = darkMode ? '#F0EAD6' : '#1A1606';
  const inkA   = (a) => darkMode ? `rgba(240,234,214,${a})` : `rgba(20,16,6,${a})`;
  const bg     = darkMode ? '#100e0c' : '#EDE8D4';
  const shadow = darkMode
    ? '0 8px 32px rgba(0,0,0,0.7), 4px 4px 0 rgba(0,0,0,0.5)'
    : '0 8px 32px rgba(20,16,6,0.22), 4px 4px 0 rgba(20,16,6,0.18)';

  const reel = (idx) => ({
    width: 40, height: 40,
    borderRadius: '50%',
    border: `2px solid ${inkA(0.22)}`,
    background: `
      radial-gradient(circle at center, ${inkA(0.28)} 0 9px, transparent 9px),
      repeating-conic-gradient(${inkA(0.14)} 0deg 9deg, transparent 9deg 30deg)
    `,
    animation: playing ? `reelSpin ${idx === 0 ? 1.8 : 2.2}s linear infinite` : 'none',
    flexShrink: 0,
  });

  const btnStyle = (isMain) => ({
    fontFamily: "'VT323', monospace",
    fontSize: isMain ? 22 : 17,
    color: ink,
    background: isMain ? inkA(0.07) : 'none',
    border: `1px solid ${inkA(0.18)}`,
    cursor: 'pointer',
    padding: isMain ? '1px 14px' : '1px 8px',
    minWidth: isMain ? 46 : 32,
    letterSpacing: 0,
    transition: 'background 0.15s',
  });

  return (
    <div ref={playerRef} style={embedded ? {
      width: '100%',
      fontFamily: "'VT323', monospace",
      background: bg,
      border: `1px solid ${inkA(0.18)}`,
      borderRadius: 3,
      overflow: 'hidden',
      boxShadow: shadow,
    } : {
      position: 'fixed',
      ...(pos ? { top: pos.y, left: pos.x } : { bottom: 20, left: 20 }),
      zIndex: 9996,
      width: 288,
      fontFamily: "'VT323', monospace",
      background: bg,
      border: `1px solid ${inkA(0.18)}`,
      borderRadius: 3,
      overflow: 'hidden',
      boxShadow: shadow,
    }}>

      {/* ── HEADER (always visible) ── */}
      <div onMouseDown={onHeaderMouseDown} style={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        padding: '7px 10px 6px',
        borderBottom: `1px solid ${inkA(0.14)}`,
        background: inkA(0.04),
        gap: 8,
        cursor: embedded ? 'default' : 'grab',
      }}>
        <div style={{ display:'flex', flexDirection:'column', lineHeight:1.1, minWidth:0, flex:1 }}>
          <span style={{ color: ink, fontSize:15, letterSpacing:'0.06em', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
            {track.title}
          </span>
          <span style={{ color: inkA(0.42), fontSize:11, letterSpacing:'0.1em' }}>
            {track.sub}
          </span>
        </div>

        {/* play indicator dot */}
        <div style={{
          width: 7, height: 7,
          borderRadius: '50%',
          background: playing ? ink : 'transparent',
          border: `1px solid ${inkA(0.35)}`,
          flexShrink: 0,
          transition: 'background 0.2s',
        }} />

        {/* minimize toggle */}
        <button
          type="button"
          onClick={() => setOpen(o => !o)}
          style={{ ...btnStyle(false), fontSize: 20, minWidth: 28, padding: '0 6px', border: `1px solid ${inkA(0.2)}` }}
        >
          {open ? '−' : '+'}
        </button>
      </div>

      {/* ── EXPANDED BODY ── */}
      {open && (
        <>
          {/* cassette visual */}
          <div style={{ padding:'10px 14px 6px', display:'flex', justifyContent:'center' }}>
            <div style={{
              width: 210, height: 72,
              border: `1px solid ${inkA(0.16)}`,
              borderRadius: 5,
              display:'flex', alignItems:'center', justifyContent:'space-around',
              padding:'0 18px',
              background: inkA(0.03),
              position:'relative',
            }}>
              <div style={reel(0)} />

              {/* tape window */}
              <div style={{
                width: 66, height: 20,
                background: inkA(0.62),
                borderRadius: 2,
                position:'absolute', left:'50%',
                transform:'translateX(-50%)',
              }} />

              <div style={reel(1)} />

              {/* brand on cassette */}
              <span style={{
                position:'absolute', bottom:5, left:'50%',
                transform:'translateX(-50%)',
                fontSize:7, letterSpacing:'0.25em',
                color: inkA(0.22), whiteSpace:'nowrap',
              }}>
                DAVIDYBLUE
              </span>
            </div>
          </div>

          {/* progress */}
          <div style={{ padding:'4px 14px 8px' }}>
            <div style={{ display:'flex', justifyContent:'space-between', fontSize:11, color: inkA(0.45), marginBottom:5 }}>
              <span>{fmt(currentTime)}</span>
              <span>{fmt(duration)}</span>
            </div>
            <div
              onClick={handleSeekClick}
              style={{ height:2, background: inkA(0.18), cursor:'pointer', position:'relative' }}
            >
              <div style={{
                position:'absolute', top:0, left:0,
                height:'100%', width:`${progress * 100}%`,
                background: ink, transition:'width 0.5s linear',
              }} />
              <div style={{
                position:'absolute', top:'50%', left:`${progress * 100}%`,
                transform:'translate(-50%,-50%)',
                width:8, height:8, borderRadius:'50%', background: ink,
              }} />
            </div>
          </div>

          {/* controls */}
          <div style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:4, padding:'2px 14px 8px' }}>
            {[
              { label:'|<',           action: prev,                                        main:false },
              { label:'<<',           action: () => seek(Math.max(0, progress - 0.05)),    main:false },
              { label:playing?'||':'>', action: () => setPlaying(p => !p), active: true,   main:true  },
              { label:'RND',          action: randomize,                                   main:true  },
              { label:'>>',           action: () => seek(Math.min(1, progress + 0.05)),    main:false },
              { label:'>|',           action: next,                                        main:false },
            ].map(({ label, action, main, active }) => (
              <button
                type="button"
                key={label}
                onClick={action}
                style={{
                  fontFamily:"'VT323', monospace",
                  fontSize: 16,
                  color: ink,
                  background: active ? inkA(0.13) : inkA(0.04),
                  border: `1px solid ${inkA(0.18)}`,
                  cursor: 'pointer',
                  padding: '2px 0',
                  width: 36,
                  textAlign: 'center',
                  letterSpacing: 0,
                }}
              >
                {label}
              </button>
            ))}
          </div>

          {/* volume row */}
          <div style={{ display:'flex', alignItems:'center', gap:7, padding:'0 14px 10px' }}>
            <button
              type="button"
              onClick={() => setMuted(m => !m)}
              style={{ ...btnStyle(false), fontSize:15, minWidth:28, padding:'1px 5px', color: muted ? inkA(0.3) : ink }}
              title={muted ? 'Unmute' : 'Mute'}
            >
              {muted ? '(x' : '(('}
            </button>
            <span style={{ color: inkA(0.4), fontSize:11, letterSpacing:'0.15em', flexShrink:0 }}>VOL</span>
            <div
              onClick={handleVolumeClick}
              style={{ flex:1, height:2, background: inkA(0.16), cursor:'pointer', position:'relative' }}
            >
              <div style={{
                position:'absolute', top:0, left:0,
                height:'100%',
                width: muted ? '0%' : `${volume}%`,
                background: ink,
                transition:'width 0.15s',
              }} />
              <div style={{
                position:'absolute', top:'50%',
                left: muted ? '0%' : `${volume}%`,
                transform:'translate(-50%,-50%)',
                width:7, height:7, borderRadius:'50%', background: ink,
                transition:'left 0.15s',
              }} />
            </div>
            <span style={{ color: inkA(0.4), fontSize:11, minWidth:'2.8ch', textAlign:'right' }}>
              {muted ? '0' : volume}%
            </span>
          </div>

          {/* playlist accordion */}
          <div>
            {/* accordion header */}
            <button
              type="button"
              onClick={() => setListOpen(o => !o)}
              style={{
                width:'100%', display:'flex', alignItems:'center', justifyContent:'space-between',
                padding:'5px 10px', background: inkA(0.04), border:'none',
                borderTop:`1px solid ${inkA(0.14)}`, cursor:'pointer',
                fontFamily:"'VT323', monospace", fontSize:12,
                color: inkA(0.45), letterSpacing:'0.18em', textTransform:'uppercase',
              }}
            >
              <span>TRACKLIST — {TRACKS.length} SONGS</span>
              <span style={{ fontSize:14, lineHeight:1 }}>{listOpen ? '▲' : '▼'}</span>
            </button>

            {/* collapsible list */}
            {listOpen && (
              <div style={{ maxHeight:160, overflowY:'auto', borderTop:`1px solid ${inkA(0.08)}` }}>
                {TRACKS.map((t, i) => (
                  <div
                    key={i}
                    onClick={() => goTrack(i)}
                    style={{
                      display:'flex', justifyContent:'space-between', alignItems:'center',
                      padding:'5px 10px', cursor:'pointer',
                      background: i === trackIdx ? inkA(0.07) : 'transparent',
                      borderBottom:`1px solid ${inkA(0.08)}`,
                      fontSize:13, transition:'background 0.15s',
                    }}
                  >
                    <span style={{ color: i === trackIdx ? ink : inkA(0.42), letterSpacing:'0.04em', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', maxWidth:'80%' }}>
                      {String(i + 1).padStart(2,'0')}. {t.title}
                    </span>
                    <span style={{ color: inkA(0.3), fontSize:11, flexShrink:0 }}>{t.sub}</span>
                  </div>
                ))}
              </div>
            )}
          </div>
        </>
      )}
    </div>
  );
}

Object.assign(window, { MusicPlayer });
