// Floating lobby-music player.
// Sits in the bottom-right of the page. When user toggles ON:
//  - our <audio> plays on loop
//  - any background YouTube embeds get paused via postMessage
// State persists in localStorage so it survives reload.

window.LobbyMusic = function LobbyMusic({ src = 'assets/lobby.ogg', accent = '#E63028', t }) {
  const [on, setOn] = React.useState(false);
  const [hover, setHover] = React.useState(false);
  const [bars, setBars] = React.useState([0.4, 0.7, 0.5, 0.9, 0.3]);

  // Web Audio refs — Chrome can't reliably play this Ogg via <audio>, so we
  // decode once and run a looping AudioBufferSourceNode through a GainNode.
  const ctxRef = React.useRef(null);
  const bufferRef = React.useRef(null);
  const sourceRef = React.useRef(null);
  const gainRef = React.useRef(null);
  const decodingRef = React.useRef(false);

  // Create AudioContext synchronously (must happen inside the user gesture)
  const ensureCtx = React.useCallback(() => {
    if (!ctxRef.current) {
      const Ctor = window.AudioContext || window.webkitAudioContext;
      ctxRef.current = new Ctor();
      gainRef.current = ctxRef.current.createGain();
      gainRef.current.gain.value = 0.55;
      gainRef.current.connect(ctxRef.current.destination);
    }
    return ctxRef.current;
  }, []);

  const ensureBuffer = React.useCallback(async () => {
    if (bufferRef.current) return bufferRef.current;
    if (decodingRef.current) {
      while (decodingRef.current) await new Promise(r => setTimeout(r, 50));
      return bufferRef.current;
    }
    decodingRef.current = true;
    try {
      ensureCtx();
      const res = await fetch(src);
      const ab = await res.arrayBuffer();
      const decoded = await ctxRef.current.decodeAudioData(ab);
      bufferRef.current = decoded;
      return decoded;
    } finally {
      decodingRef.current = false;
    }
  }, [src, ensureCtx]);

  const startPlayback = React.useCallback(async () => {
    try {
      // Resume the (already-created) context FIRST so the gesture reaches it
      const ctx = ensureCtx();
      if (ctx.state === 'suspended') await ctx.resume();
      const buf = await ensureBuffer();
      if (!buf) return;
      if (ctx.state === 'suspended') await ctx.resume();
      // stop any previous source
      if (sourceRef.current) { try { sourceRef.current.stop(); } catch(e) {} sourceRef.current.disconnect(); }
      const src = ctx.createBufferSource();
      src.buffer = buf;
      src.loop = true;
      src.connect(gainRef.current);
      src.start(0);
      sourceRef.current = src;
    } catch (e) { /* ignore */ }
  }, [ensureBuffer]);

  const stopPlayback = React.useCallback(() => {
    if (sourceRef.current) {
      try { sourceRef.current.stop(); } catch(e) {}
      try { sourceRef.current.disconnect(); } catch(e) {}
      sourceRef.current = null;
    }
  }, []);

  // Restore state — but never autoplay; user must click after a gesture
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem('oxide_music_on');
      if (saved === '1') setOn(true);
    } catch (e) {}
    return () => stopPlayback();
  }, []);

  // React to on/off
  React.useEffect(() => {
    if (on) {
      startPlayback();
      // pause background YouTube embeds
      document.querySelectorAll('iframe[src*="youtube"]').forEach(f => {
        try { f.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*'); } catch(e) {}
      });
    } else {
      stopPlayback();
      document.querySelectorAll('iframe[src*="youtube"]').forEach(f => {
        try {
          f.contentWindow.postMessage('{"event":"command","func":"mute","args":""}', '*');
          f.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
        } catch(e) {}
      });
    }
    try { localStorage.setItem('oxide_music_on', on ? '1' : '0'); } catch(e) {}
  }, [on, startPlayback, stopPlayback]);

  // Animate the equalizer bars while playing
  React.useEffect(() => {
    if (!on) { setBars([0.15, 0.15, 0.15, 0.15, 0.15]); return; }
    let raf;
    const tick = () => {
      setBars(b => b.map(() => 0.25 + Math.random() * 0.75));
      raf = setTimeout(tick, 140);
    };
    tick();
    return () => clearTimeout(raf);
  }, [on]);

  const label = on ? (t ? t('music_on') : 'Lobby music ON')
                   : (t ? t('music_off') : 'Lobby music OFF');

  return (
    <div style={{
      position: 'fixed', right: 24, bottom: 24, zIndex: 200,
      display: 'flex', alignItems: 'center', gap: 12,
      pointerEvents: 'none',
    }}>
      {/* Label pill — visible on hover or when on */}
      <div style={{
        opacity: (hover || on) ? 1 : 0,
        transform: (hover || on) ? 'translateX(0)' : 'translateX(8px)',
        transition: 'opacity .3s, transform .3s',
        background: 'rgba(10,8,7,0.85)',
        border: `1px solid ${on ? accent : 'rgba(237,230,221,0.18)'}`,
        backdropFilter: 'blur(10px)',
        padding: '8px 14px',
        fontFamily: 'ui-monospace, "JetBrains Mono", monospace',
        fontSize: 10,
        letterSpacing: '0.16em',
        textTransform: 'uppercase',
        color: on ? accent : '#b8ac9f',
        whiteSpace: 'nowrap',
        pointerEvents: 'none',
      }}>
        {label}
      </div>

      <button
        onClick={() => {
          // Touch the AudioContext synchronously inside the click handler
          // so the user gesture reaches the audio engine before any await.
          try {
            const ctx = ensureCtx();
            if (ctx.state === 'suspended') ctx.resume();
          } catch(e) {}
          setOn(v => !v);
        }}
        onMouseEnter={() => setHover(true)}
        onMouseLeave={() => setHover(false)}
        aria-label={label}
        aria-pressed={on}
        style={{
          width: 56, height: 56, borderRadius: '50%',
          background: on ? accent : 'rgba(10,8,7,0.85)',
          border: `2px solid ${on ? accent : 'rgba(237,230,221,0.25)'}`,
          pointerEvents: 'auto',
          backdropFilter: 'blur(10px)',
          cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          gap: 3,
          boxShadow: on ? `0 0 30px ${accent}80, 0 8px 30px rgba(0,0,0,.5)` : '0 8px 30px rgba(0,0,0,.5)',
          transition: 'background .25s, border-color .25s, box-shadow .25s, transform .25s',
          transform: hover ? 'scale(1.06)' : 'scale(1)',
          padding: 0,
        }}>
        {on ? (
          // Equalizer bars
          <React.Fragment>
            {bars.map((h, i) => (
              <span key={i} style={{
                display: 'inline-block', width: 3,
                height: `${10 + h * 18}px`,
                background: '#fff',
                transition: 'height .14s ease',
              }} />
            ))}
          </React.Fragment>
        ) : (
          // Music note / play glyph
          <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={hover ? accent : '#EDE6DD'} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ transition: 'stroke .2s' }}>
            <path d="M9 18V5l12-2v13"/>
            <circle cx="6" cy="18" r="3"/>
            <circle cx="18" cy="16" r="3"/>
          </svg>
        )}
      </button>
    </div>
  );
};
