// listen.jsx — standalone /listen/[id] smart-link page (Hyperfollow-style).
// Data source: Supabase tables `public.diaval_myths` + `public.diaval_myth_links`.

const DEFAULT_SLUG = "grain";

// Parse "3:42" → 222 seconds. 0 if missing/invalid.
function parseDurationSecsListen(s) {
  if (!s) return 0;
  const parts = String(s).split(":").map(n => parseInt(n, 10));
  if (parts.some(Number.isNaN)) return 0;
  if (parts.length === 2) return parts[0] * 60 + parts[1];
  if (parts.length === 3) return parts[0] * 3600 + parts[1] * 60 + parts[2];
  return parts[0] || 0;
}

// Async loader: pulls a myth (released OR presave-enabled) + its streaming links.
// Reads from the diaval_myths_public view so body+lyric come back NULL for presave-only rows.
async function fetchRelease(slug) {
  const { data: myth, error: mErr } = await window.diavalSupabase
    .from("diaval_myths_public")
    .select("id, title, year, duration, color, blurb, body, position, release_date, cover_url, cover_hue1, cover_hue2, cover_glyph, hyperfollow_url, total_clicks, spotify_preview_url, spotify_track_id, spotify_album_art_url, is_published, presave_enabled")
    .eq("id", slug)
    .maybeSingle();
  if (mErr) throw mErr;
  if (!myth) return null;

  const { data: links, error: lErr } = await window.diavalSupabase
    .from("diaval_myth_links")
    .select("platform, label, url, clicks, position")
    .eq("myth_id", slug)
    .order("position", { ascending: true });
  if (lErr) throw lErr;

  return {
    id: myth.id,
    title: myth.title,
    artist: "DIAVAL",
    date: myth.release_date || myth.year || "",
    release_date: myth.release_date,
    is_published: !!myth.is_published,
    presave_enabled: !!myth.presave_enabled,
    cover_url: myth.cover_url || myth.spotify_album_art_url || null,
    cover_fallback: {
      hue1: myth.cover_hue1 || myth.color || "#000d52",
      hue2: myth.cover_hue2 || "#1830ff",
      glyph: myth.cover_glyph || "◢",
    },
    blurb: myth.blurb || "",
    hyperfollow: myth.hyperfollow_url,
    total_clicks: myth.total_clicks ?? 0,
    duration: parseDurationSecsListen(myth.duration),
    preview_start: 0,
    spotify_preview_url: myth.spotify_preview_url ?? null,
    spotify_track_id: myth.spotify_track_id ?? null,
    spotify_album_url: null,
    links: (links ?? []).map(l => ({ platform: l.platform, label: l.label, url: l.url, clicks: l.clicks ?? 0 })),
  };
}

const PLATFORM_GLYPH = {
  spotify: "▶", apple: "◐", itunes: "♫", deezer: "≋", iheart: "♥",
  tidal: "◆", amazon: "▶", amazonstore: "▶", ytmusic: "►", youtube: "►",
  soundcloud: "≋", pandora: "P", anghami: "♪", audius: "◢",
  boomplay: "◉", napster: "N", yandex: "Я",
};

// ─── 30-second preview player ────────────────────────────────
// Renders the styled custom player when we have a real spotify_preview_url.
// When that's missing (Spotify removed previews for many late-2024+ tracks), the
// caller should render a Spotify iframe embed instead — see ListenPage main render.
function PreviewPlayer({ release, S, compact = false }) {
  const [playing, setPlaying] = React.useState(false);
  const [progress, setProgress] = React.useState(0); // 0..30
  const PREVIEW_LEN = 30;
  const audioRef = React.useRef(null);
  const hasPreview = !!release?.spotify_preview_url;

  // Real audio path — only branch (the simulated-progress fallback was removed; the
  // caller renders a Spotify iframe instead when there's no preview URL).
  React.useEffect(() => {
    if (!hasPreview) return;
    const a = audioRef.current;
    if (!a) return;
    if (playing) a.play().catch(() => setPlaying(false));
    else a.pause();
  }, [playing, hasPreview]);

  // PreviewPlayer only renders when we actually have a preview URL — the fake
  // setInterval-driven progress was removed. Caller handles the no-preview case
  // with a Spotify iframe fallback instead.
  if (!hasPreview) return null;

  const pct = (progress / PREVIEW_LEN) * 100;
  const sec = Math.floor(progress);
  const remain = PREVIEW_LEN - sec;

  // generate 60 waveform bars
  const bars = React.useMemo(() => {
    return Array.from({ length: compact ? 40 : 64 }, (_, i) => {
      const seed = (i * 37 + 11) % 100;
      const a = Math.sin(i * 0.5) * 0.3 + 0.5;
      const b = (seed / 100) * 0.5;
      return Math.max(0.15, Math.min(1, a + b));
    });
  }, [compact]);

  return (
    <div style={{
      border: `1px solid ${S.concreteHi}`,
      background: "rgba(10,10,10,0.7)", backdropFilter: "blur(6px)",
      padding: compact ? "12px 14px" : "16px 20px",
      display: "flex", alignItems: "center", gap: compact ? 12 : 16,
    }}>
      {/* play button */}
      <button onClick={() => setPlaying(p => !p)} style={{
        width: compact ? 38 : 46, height: compact ? 38 : 46, flexShrink: 0,
        background: S.bloodHot, border: "none", color: S.bone, cursor: "pointer",
        fontSize: compact ? 14 : 16, fontFamily: S.display,
        display: "flex", alignItems: "center", justifyContent: "center",
      }}>
        {playing ? "❚❚" : "▶"}
      </button>

      {/* waveform + meta */}
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          display: "flex", justifyContent: "space-between", alignItems: "baseline",
          fontSize: compact ? 12 : 12, color: S.ash, letterSpacing: "0.3em", marginBottom: compact ? 6 : 8,
        }}>
          <span>PREVIEW · 30 SEC{hasPreview ? "" : " · SIMULATED"}</span>
          <span>{playing ? `−0:${String(remain).padStart(2,"0")}` : "0:30"}</span>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 1.5, height: compact ? 22 : 28 }}>
          {bars.map((h, i) => {
            const barPct = (i / bars.length) * 100;
            const played = barPct < pct;
            return (
              <div key={i} style={{
                flex: 1,
                height: `${h * 100}%`,
                background: played ? S.bloodHot : (playing ? S.ash : S.ashDim),
                transition: "background 0.05s",
              }} />
            );
          })}
        </div>
      </div>

      {hasPreview && (
        <audio
          ref={audioRef}
          src={release.spotify_preview_url}
          preload="auto"
          onTimeUpdate={(e) => setProgress(e.currentTarget.currentTime)}
          onEnded={() => { setPlaying(false); setProgress(0); }}
          style={{ display: "none" }}
        />
      )}
    </div>
  );
}

// ─── Platform link button ────────────────────────────────────
function PortalButton({ link, onClick, S, compact = false }) {
  const [hover, setHover] = React.useState(false);
  return (
    <a href={link.url} target="_blank" rel="noreferrer" onClick={onClick}
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        display: "grid", gridTemplateColumns: compact ? "36px 1fr 16px" : "44px 1fr 20px", gap: compact ? 12 : 14,
        alignItems: "center", padding: compact ? "14px 14px" : "18px 20px",
        border: `1px solid ${hover ? S.bloodHot : S.concreteHi}`,
        background: hover ? "rgba(190,33,30,0.12)" : "rgba(10,10,10,0.7)",
        backdropFilter: "blur(4px)",
        textDecoration: "none", color: S.bone, transition: "all 0.12s",
      }}>
      <div style={{
        fontFamily: S.display, fontSize: compact ? 18 : 22, color: hover ? S.bloodHot : S.bone,
        textAlign: "center", lineHeight: 1,
      }}>
        {PLATFORM_GLYPH[link.platform] || "◢"}
      </div>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontFamily: S.display, fontSize: compact ? 13 : 15, color: S.bone, letterSpacing: "0.04em", lineHeight: 1.1 }}>
          {link.label}
        </div>
        <div style={{ fontSize: compact ? 12 : 12, color: S.ashDim, letterSpacing: "0.2em", marginTop: 3 }}>
          PLAY ON {link.label}
        </div>
      </div>
      <div style={{ fontFamily: S.display, fontSize: compact ? 12 : 14, color: hover ? S.bloodHot : S.ash }}>↗</div>
    </a>
  );
}

// ─── Shared inner content (used by both desktop + mobile) ────
function ListenContent({ release, slug, S, compact = false, onAboutClick }) {
  const trackClick = (platform) => console.log("[click]", platform, slug);
  const Socials = window.SocialIcons;

  const coverSize = compact ? 200 : 220;

  return (
    <div style={{
      width: "100%", maxWidth: compact ? "100%" : 560, margin: "0 auto",
      display: "flex", flexDirection: "column", alignItems: "center",
      padding: compact ? "0 20px" : 0, boxSizing: "border-box",
    }}>
      {/* cover */}
      <div style={{
        width: coverSize, height: coverSize, flexShrink: 0,
        marginBottom: compact ? 20 : 26,
        border: `1px solid ${S.concreteHi}`, position: "relative", overflow: "hidden",
        background: `radial-gradient(ellipse at 50% 40%, ${release.cover_fallback.hue2}, ${release.cover_fallback.hue1})`,
        boxShadow: "0 30px 60px rgba(0,0,0,0.6)",
      }}>
        {release.cover_url ? (
          <img src={release.cover_url} alt="" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
        ) : (
          <div style={{
            position: "absolute", inset: 0,
            display: "flex", alignItems: "center", justifyContent: "center",
            fontFamily: S.display, fontSize: coverSize * 0.55, color: S.bloodHot, opacity: 0.7,
          }}>
            {release.cover_fallback.glyph}
          </div>
        )}
      </div>

      {/* meta */}
      <div style={{ fontSize: 12, color: S.bloodHot, letterSpacing: "0.5em", marginBottom: 10 }}>
        ◢ OUT NOW · {release.date}
      </div>
      <h1 style={{
        margin: 0, fontFamily: S.display, fontSize: compact ? 32 : 44, color: S.bone,
        letterSpacing: "-0.02em", lineHeight: 1, textAlign: "center", marginBottom: 6,
      }}>
        {release.title}
      </h1>
      <div style={{ fontFamily: S.meta, fontSize: 12, color: S.ash, letterSpacing: "0.3em", marginBottom: compact ? 22 : 28 }}>
        BY {release.artist}
      </div>

      {/* Prerelease state (release_date > today, OR presave-only with no published date)
          → swap streaming list for a PRE-SAVE block + countdown + Spotify embed if track_id known.
          Released state → real preview audio player OR Spotify iframe fallback + DSP buttons. */}
      <PreSaveOrPlayer release={release} S={S} compact={compact} trackClick={trackClick} />

      {/* footer */}
      <div style={{ marginTop: 22, fontSize: 12, color: S.ash, letterSpacing: "0.3em", textAlign: "center", lineHeight: 1.9 }}>
        <a onClick={onAboutClick} style={{
          color: S.bone, cursor: "pointer", textDecoration: "none",
          borderBottom: `1px solid ${S.bloodHot}`, paddingBottom: 2,
        }}>
          ABOUT THE SONG ↗
        </a>
      </div>
      {Socials && (
        <div style={{ marginTop: 18, display: "flex", justifyContent: "center" }}>
          <Socials S={S} align="center" size="small" />
        </div>
      )}
    </div>
  );
}

// ─── Pre-save block OR playable preview, depending on release state ──
// - Prerelease (release_date in future) OR presave-only (presave_enabled && !is_published)
//     → PRE-SAVE eyebrow + countdown + PRE-SAVE button + (optional Spotify embed)
// - Released, has spotify_preview_url → styled custom 30s preview player + DSP buttons
// - Released, no preview_url but has spotify_track_id → Spotify iframe (full track) + DSP buttons
// - Released, no audio source at all → DSP buttons only
function PreSaveOrPlayer({ release, S, compact, trackClick }) {
  const isPre = (release.presave_enabled && !release.is_published) || isPrerelease(release.release_date);
  const cd = useCountdown(release.release_date);

  if (isPre) {
    return (
      <div style={{ width: "100%", marginBottom: compact ? 18 : 22 }}>
        <div style={{ border: `1px solid ${S.bloodHot}`, padding: compact ? 16 : 22, background: "rgba(10,10,10,0.7)" }}>
          <div style={{ fontSize: 12, color: S.bloodHot, letterSpacing: "0.3em", marginBottom: 12 }}>
            ◢ PRE-RELEASE{release.release_date ? ` · DROPS ${release.release_date}` : ""}
          </div>
          {cd && (
            <div style={{ display: "flex", gap: compact ? 14 : 22, marginBottom: 18, flexWrap: "wrap" }}>
              {[["DAYS", cd.days], ["HOURS", cd.hours], ["MINUTES", cd.minutes]].map(([label, v]) => (
                <div key={label}>
                  <div style={{ fontFamily: S.display, fontSize: compact ? 32 : 44, lineHeight: 1, color: S.bone, letterSpacing: "-0.01em" }}>
                    {String(v).padStart(2, "0")}
                  </div>
                  <div style={{ fontSize: 10, color: S.ash, letterSpacing: "0.3em", marginTop: 4 }}>{label}</div>
                </div>
              ))}
            </div>
          )}
          {release.hyperfollow ? (
            <a href={release.hyperfollow} target="_blank" rel="noreferrer" style={{
              display: "inline-flex", alignItems: "center", gap: 10,
              padding: "12px 18px", background: S.bloodHot, color: S.bone,
              fontFamily: S.meta, fontSize: 12, letterSpacing: "0.3em",
              textDecoration: "none", border: "none",
            }}>
              ↓ PRE-SAVE ON ALL PLATFORMS ↗
            </a>
          ) : (
            <div style={{ fontSize: 12, color: S.ash, letterSpacing: "0.18em" }}>PRE-SAVE LINK PENDING — ADMIN SYNC.</div>
          )}
          <div style={{ marginTop: 12, fontSize: 11, color: S.ash, letterSpacing: "0.18em" }}>
            spotify · apple music · iheart · everywhere you listen
          </div>
        </div>
        {/* Spotify embed (works as a secondary pre-save surface for prereleases when track_id exists) */}
        {release.spotify_track_id && (
          <div style={{ marginTop: 12 }}>
            <iframe
              src={`https://open.spotify.com/embed/track/${release.spotify_track_id}?theme=0`}
              width="100%" height="80"
              frameBorder="0" loading="lazy"
              allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
              style={{ display: "block", border: `1px solid ${S.concreteHi}` }}
            />
          </div>
        )}
      </div>
    );
  }

  // Released — pick the right player surface
  const hasPreview = !!release.spotify_preview_url;
  const hasEmbed = !hasPreview && !!release.spotify_track_id;
  return (
    <>
      <div style={{ width: "100%", marginBottom: compact ? 18 : 22 }}>
        {hasPreview && <PreviewPlayer release={release} S={S} compact={compact} />}
        {hasEmbed && (
          <iframe
            src={`https://open.spotify.com/embed/track/${release.spotify_track_id}?theme=0`}
            width="100%" height="80"
            frameBorder="0" loading="lazy"
            allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
            style={{ display: "block", border: `1px solid ${S.concreteHi}` }}
          />
        )}
      </div>
      <div style={{ width: "100%", display: "flex", flexDirection: "column", gap: 8 }}>
        {release.links.map(link => (
          <PortalButton key={link.platform} link={link} onClick={() => trackClick(link.platform)} S={S} compact={compact} />
        ))}
      </div>
    </>
  );
}

// ─── DESKTOP standalone page ─────────────────────────────────
function ListenPage({ slug = DEFAULT_SLUG, onMythologyClick, onHomeClick }) {
  const S = window.shellStyles;
  const [release, setRelease] = React.useState(null);
  const [loadError, setLoadError] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    fetchRelease(slug)
      .then(r => { if (!cancelled) setRelease(r || null); })
      .catch(err => { if (!cancelled) setLoadError(err.message); });
    // Fall back to default slug if requested slug missing.
    return () => { cancelled = true; };
  }, [slug]);

  if (loadError) {
    return (
      <div style={{ width: "100%", height: "100vh", background: "#000", color: S.bone, display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", gap: 12, padding: 40, fontFamily: S.meta }}>
        <div style={{ fontSize: 13, color: S.bloodHot, letterSpacing: "0.3em" }}>◢ RELEASE FEED CORRUPTED</div>
        <div style={{ fontSize: 13, color: S.ash, fontStyle: "italic", maxWidth: 600, textAlign: "center" }}>{loadError}</div>
      </div>
    );
  }
  if (!release) {
    return (
      <div style={{ width: "100%", height: "100vh", background: "#000", color: S.bone, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 13, color: S.ashDim, letterSpacing: "0.3em", fontFamily: S.meta }}>
        ⸺ TUNING SIGNAL ⸺
      </div>
    );
  }

  return (
    <div style={{
      width: "100%", height: "100vh", background: "#000", color: S.bone,
      fontFamily: S.meta, position: "relative", overflow: "hidden",
    }}>
      <NoiseFilter id="ind-noise" baseFreq="1.2" opacity="0.55" />

      {/* faded cover background */}
      <ListenBackground release={release} />

      {/* tiny top header */}
      <div style={{
        position: "absolute", top: 24, left: 40, right: 40, zIndex: 20,
        display: "flex", justifyContent: "space-between", alignItems: "center",
      }}>
        <div onClick={onHomeClick} style={{ display: "flex", alignItems: "baseline", gap: 12, cursor: "pointer" }}>
          <span style={{ fontFamily: S.display, fontSize: 18, letterSpacing: "0.18em", color: S.bone }}>D//V</span>
          <span style={{ fontFamily: S.meta, fontSize: 12, color: S.bloodHot, letterSpacing: "0.3em" }}>
            DIAVAL.AI/LISTEN/{slug.toUpperCase()}
          </span>
        </div>
        <div style={{ fontSize: 12, color: S.ash, letterSpacing: "0.3em" }}>
          SYNCED · {release.last_synced}
        </div>
      </div>

      {/* content */}
      <div style={{
        position: "absolute", top: 92, left: 0, right: 0, bottom: 40,
        display: "flex", justifyContent: "center", overflowY: "auto",
        padding: "0 40px",
        zIndex: 10,
      }}>
        <ListenContent release={release} slug={slug} S={S} compact={false}
          onAboutClick={() => onMythologyClick && onMythologyClick(slug)} />
      </div>

      {/* bottom strip */}
      <div style={{
        position: "absolute", bottom: 14, left: 40, right: 40,
        fontSize: 12, color: S.ashDim, letterSpacing: "0.3em",
        display: "flex", justifyContent: "space-between", zIndex: 10,
      }}>
        <span>DIAVAL.AI // LSN ⸺ COME APART. WE'RE ALL BETTER IN PIECES.</span>
        <span>MMXXVI</span>
      </div>
    </div>
  );
}

// ─── MOBILE standalone page (390 wide, scrollable) ───────────
function ListenPageMobile({ slug = DEFAULT_SLUG, onMythologyClick, onHomeClick }) {
  const S = window.shellStyles;
  const [release, setRelease] = React.useState(null);
  const [loadError, setLoadError] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    fetchRelease(slug)
      .then(r => { if (!cancelled) setRelease(r || null); })
      .catch(err => { if (!cancelled) setLoadError(err.message); });
    return () => { cancelled = true; };
  }, [slug]);

  if (loadError || !release) {
    return (
      <div style={{ width: "100%", minHeight: "100%", background: "#000", color: S.bone, fontFamily: S.meta, padding: 40, textAlign: "center", fontSize: 13, color: S.ashDim, letterSpacing: "0.3em" }}>
        {loadError ? `◢ ${loadError}` : "⸺ TUNING SIGNAL ⸺"}
      </div>
    );
  }

  return (
    <div style={{
      width: "100%", minHeight: "100%", background: "#000", color: S.bone,
      fontFamily: S.meta, position: "relative", boxSizing: "border-box",
    }}>
      <NoiseFilter id="ind-noise-m" baseFreq="1.2" opacity="0.55" />

      {/* faded cover bg */}
      <div style={{ position: "absolute", inset: 0, overflow: "hidden", pointerEvents: "none" }}>
        <div style={{
          position: "absolute", inset: 0,
          background: `radial-gradient(ellipse at 50% 25%, ${release.cover_fallback.hue2}, ${release.cover_fallback.hue1} 60%, #000)`,
        }} />
        <div style={{
          position: "absolute", inset: 0,
          background: "linear-gradient(180deg, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.85) 50%, rgba(0,0,0,0.97) 100%)",
        }} />
        <div style={{ position: "absolute", inset: 0, filter: "url(#ind-noise-m)", opacity: 0.4, mixBlendMode: "overlay" }} />
      </div>

      {/* top header — pushed down to clear iOS status bar / dynamic island */}
      <div style={{
        position: "relative", zIndex: 20, padding: "70px 20px 0",
        display: "flex", justifyContent: "space-between", alignItems: "center",
      }}>
        <div onClick={onHomeClick} style={{ display: "flex", alignItems: "baseline", gap: 8, cursor: "pointer" }}>
          <span style={{ fontFamily: S.display, fontSize: 16, letterSpacing: "0.18em", color: S.bone }}>D//V</span>
          <span style={{ fontFamily: S.meta, fontSize: 7, color: S.bloodHot, letterSpacing: "0.3em" }}>DIAVAL.AI</span>
        </div>
        <div style={{ fontSize: 7, color: S.ash, letterSpacing: "0.25em" }}>
          /LISTEN
        </div>
      </div>

      {/* content */}
      <div style={{ position: "relative", zIndex: 10, padding: "32px 0 24px" }}>
        <ListenContent release={release} slug={slug} S={S} compact={true}
          onAboutClick={() => onMythologyClick && onMythologyClick(slug)} />
      </div>

      {/* bottom strip */}
      <div style={{
        position: "relative", zIndex: 10, padding: "0 20px 24px",
        fontSize: 12, color: S.ashDim, letterSpacing: "0.3em", textAlign: "center",
      }}>
        COME APART. WE'RE ALL BETTER IN PIECES.
      </div>
    </div>
  );
}

// shared faded background
function ListenBackground({ release }) {
  return (
    <div style={{ position: "absolute", inset: 0, overflow: "hidden" }}>
      {release.cover_url ? (
        <img src={release.cover_url} alt="" style={{
          position: "absolute", inset: 0, width: "100%", height: "100%",
          objectFit: "cover", opacity: 0.18, filter: "blur(2px) saturate(0.8)",
        }} />
      ) : (
        <div style={{
          position: "absolute", inset: 0,
          background: `radial-gradient(ellipse at 50% 40%, ${release.cover_fallback.hue2}, ${release.cover_fallback.hue1} 60%, #000)`,
        }} />
      )}
      <div style={{
        position: "absolute", inset: 0,
        background: "linear-gradient(180deg, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0.8) 50%, rgba(0,0,0,0.95) 100%)",
      }} />
      <div style={{ position: "absolute", inset: 0, filter: "url(#ind-noise)", opacity: 0.4, mixBlendMode: "overlay" }} />
    </div>
  );
}

window.ListenPage = ListenPage;
window.ListenPageMobile = ListenPageMobile;
window.fetchRelease = fetchRelease;
