/* @file: audio-player.jsx — Exposes: window.__app.AudioPlayer
 * Looping playlist of background tracks. Accepts srcs={[...]} (array of mp4
 * paths). Plays in sequence, loops to start after last track. Tracks that
 * error (missing file, decode failure) are skipped after a short delay.
 * Autoplay-on-gesture fallback, pause on tab hidden, mute toggle persisted
 * in localStorage. Backwards-compatible single src= prop for one track.
 */
(() => {
  const STYLE_ID = "audio-player-styles";
  const MUTE_KEY = "max-site:audio-muted";

  const CSS = `
    .ap-mute {
      position: fixed;
      left: 5vw;
      bottom: 5vh;
      font-family: "Cormorant Garamond", "Georgia", serif;
      font-style: italic;
      font-weight: 400;
      font-size: 13px;
      letter-spacing: 0.06em;
      color: #2a2520;
      background: transparent;
      border: none;
      padding: 4px 0;
      cursor: pointer;
      pointer-events: auto;
      user-select: none;
      opacity: 0.5;
      transition: opacity 220ms ease;
      z-index: 200;
      display: inline-flex;
      align-items: center;
      gap: 8px;
    }
    .ap-mute:hover, .ap-mute:focus-visible { opacity: 1; outline: none; }
    .ap-mute__rule {
      display: inline-block;
      width: 26px;
      height: 1px;
      background: #c81f1f;
      transition: opacity 220ms ease, transform 220ms ease;
      transform-origin: left center;
    }
    .ap-mute--off .ap-mute__rule {
      opacity: 0.25;
      transform: scaleX(0.4);
      background: #2a2520;
    }
  `;

  function ensureStyles() {
    if (document.getElementById(STYLE_ID)) return;
    const style = document.createElement("style");
    style.id = STYLE_ID;
    style.textContent = CSS;
    document.head.appendChild(style);
  }

  function readMuted() {
    try {
      return localStorage.getItem(MUTE_KEY) === "1";
    } catch (e) {
      return false;
    }
  }

  function writeMuted(muted) {
    try {
      localStorage.setItem(MUTE_KEY, muted ? "1" : "0");
    } catch (e) {}
  }

  function AudioPlayer(props) {
    const srcs = Array.isArray(props.srcs)
      ? props.srcs.filter(Boolean)
      : (typeof props.src === "string" && props.src ? [props.src] : []);
    const volume = typeof props.volume === "number" ? props.volume : 0.3;

    const [trackIdx, setTrackIdx] = React.useState(0);
    const audioRef = React.useRef(null);
    const [muted, setMuted] = React.useState(readMuted);

    const currentSrc = srcs.length > 0 ? srcs[trackIdx % srcs.length] : null;

    React.useEffect(() => { ensureStyles(); }, []);

    React.useEffect(() => {
      const a = audioRef.current;
      if (!a) return;
      a.volume = Math.max(0, Math.min(1, volume));
    }, [volume]);

    React.useEffect(() => {
      const a = audioRef.current;
      if (!a) return;
      a.muted = muted;
      writeMuted(muted);
    }, [muted]);

    /* Playlist advancement: on natural end, advance to next track. On error
       (missing file, decode failure) skip ahead after a short delay so we
       don't tight-loop through an entire broken playlist. */
    React.useEffect(() => {
      const a = audioRef.current;
      if (!a) return undefined;
      const next = () => setTrackIdx((i) => (i + 1) % Math.max(1, srcs.length));
      const onEnded = () => {
        console.log("[audio] track ended, advancing");
        next();
      };
      const onError = () => {
        console.warn("[audio] error on", currentSrc, "(code:", a.error && a.error.code + ")", "— skipping");
        setTimeout(next, 300);
      };
      a.addEventListener("ended", onEnded);
      a.addEventListener("error", onError);
      return () => {
        a.removeEventListener("ended", onEnded);
        a.removeEventListener("error", onError);
      };
    }, [srcs.length, currentSrc]);

    /* Autoplay: try immediately on each track change. If rejected (typical
       on first load before any user gesture), wait for the first click/key/
       touch and retry. */
    React.useEffect(() => {
      const a = audioRef.current;
      if (!a || !currentSrc) return undefined;
      let cleanup = () => {};
      const tryPlay = () => {
        const p = a.play();
        if (p && typeof p.then === "function") {
          p.then(
            () => console.log("[audio] play() resolved for", currentSrc),
            (err) => {
              console.warn("[audio] autoplay blocked for", currentSrc, err.name);
              const onGesture = () => {
                const p2 = a.play();
                if (p2 && typeof p2.then === "function") {
                  p2.then(
                    () => console.log("[audio] play() on gesture resolved"),
                    (err2) => console.error("[audio] play() on gesture REJECTED", err2.name, err2.message)
                  );
                }
                document.removeEventListener("click", onGesture, true);
                document.removeEventListener("keydown", onGesture, true);
                document.removeEventListener("touchstart", onGesture, true);
              };
              document.addEventListener("click", onGesture, true);
              document.addEventListener("keydown", onGesture, true);
              document.addEventListener("touchstart", onGesture, true);
              cleanup = () => {
                document.removeEventListener("click", onGesture, true);
                document.removeEventListener("keydown", onGesture, true);
                document.removeEventListener("touchstart", onGesture, true);
              };
            }
          );
        }
      };
      tryPlay();
      return () => cleanup();
    }, [currentSrc]);

    React.useEffect(() => {
      const onVis = () => {
        const a = audioRef.current;
        if (!a) return;
        if (document.visibilityState === "visible") {
          if (!a.muted) {
            const p = a.play();
            if (p && typeof p.then === "function") p.then(() => {}, () => {});
          }
        } else {
          a.pause();
        }
      };
      document.addEventListener("visibilitychange", onVis);
      return () => document.removeEventListener("visibilitychange", onVis);
    }, []);

    return (
      <>
        <audio ref={audioRef} src={currentSrc || undefined} preload="auto" />
        <button
          type="button"
          className={"ap-mute" + (muted ? " ap-mute--off" : "")}
          onClick={() => setMuted((m) => !m)}
          aria-label={muted ? "Unmute background music" : "Mute background music"}
          title={muted ? "Unmute" : "Mute"}
        >
          <span>music</span>
          <span className="ap-mute__rule" />
        </button>
      </>
    );
  }

  window.__app = window.__app || {};
  window.__app.AudioPlayer = AudioPlayer;
})();
