// PRLX site — selected work grid with filter tags + hover-to-reveal metadata
// Tiles fade + rise in on scroll: 0.3s ease, staggered 100ms via a shared reveal clock.
function WorkTile({ w, hover, setHover, onOpen, revealClock }) {
  const { Icon, Still } = window;
  const ref = React.useRef(null);
  const reduce = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  const [shown, setShown] = React.useState(reduce);
  const [thumb, setThumb] = React.useState(null);
  const iframeRef = React.useRef(null);
  const playerRef = React.useRef(null);
  const hoverRef = React.useRef(false);
  hoverRef.current = hover === w.id;

  // Pull the poster frame from Vimeo (oEmbed) for projects with a video.
  React.useEffect(() => {
    if (!w.vimeo) return;
    let ok = true;
    const u = `https://vimeo.com/api/oembed.json?url=${encodeURIComponent(`https://vimeo.com/${w.vimeo}/${w.vhash || ""}`)}&width=1000`;
    fetch(u)
      .then((r) => (r.ok ? r.json() : null))
      .then((d) => { if (ok && d && d.thumbnail_url) setThumb(d.thumbnail_url); })
      .catch(() => {});
    return () => { ok = false; };
  }, [w.vimeo]);

  React.useEffect(() => {
    if (reduce || !ref.current) { setShown(true); return; }
    const node = ref.current;
    const scroller = node.closest("#prlx-scroll") || window;
    const target = scroller === window ? window : scroller;
    let raf = 0, done = false;
    const viewportBottom = () => scroller === window ? window.innerHeight : scroller.getBoundingClientRect().bottom;
    const cleanup = () => {
      target.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      cancelAnimationFrame(raf);
    };
    const check = () => {
      if (done || !ref.current) return;
      const r = ref.current.getBoundingClientRect();
      if (r.top < viewportBottom() - 40) {
        done = true;
        const now = performance.now();
        const start = Math.max(now, revealClock.current || now);
        revealClock.current = start + 100; // 100ms stagger between reveals
        window.setTimeout(() => setShown(true), start - now);
        cleanup();
      }
    };
    const onScroll = () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(check); };
    target.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    check(); // reveal any tiles already in view on mount
    return cleanup;
  }, [reduce, revealClock]);

  // Preload + control the Vimeo player via the SDK so hover playback is instant.
  // The iframe mounts (and buffers) as soon as the tile scrolls into view; the
  // player is paused on ready, then play()/pause() toggle with hover.
  React.useEffect(() => {
    if (!w.vimeo || !shown || !iframeRef.current || reduce) return;
    let cancelled = false, player = null;
    const init = () => {
      if (cancelled) return;
      if (!window.Vimeo || !window.Vimeo.Player) { setTimeout(init, 150); return; }
      player = new window.Vimeo.Player(iframeRef.current);
      playerRef.current = player;
      player.setVolume(0).catch(() => {});
      player.setLoop(true).catch(() => {});
      player.ready().then(() => {
        if (!cancelled && !hoverRef.current) player.pause().catch(() => {});
      }).catch(() => {});
    };
    init();
    return () => {
      cancelled = true;
      if (player) { try { player.destroy(); } catch (e) {} }
      playerRef.current = null;
    };
  }, [shown, w.vimeo, reduce]);

  React.useEffect(() => {
    const p = playerRef.current;
    if (!p) return;
    if (hover === w.id) p.play().catch(() => {});
    else { p.pause().catch(() => {}); p.setCurrentTime(0).catch(() => {}); }
  }, [hover]);

  return (
    <div
      ref={ref}
      onMouseEnter={() => setHover(w.id)}
      onMouseLeave={() => setHover(null)}
      onClick={() => onOpen(w)}
      style={{
        position: "relative", cursor: "pointer", overflow: "hidden", background: "#000",
        opacity: shown ? 1 : 0,
        transform: shown ? "translateY(0)" : "translateY(20px)",
        transition: "opacity 0.3s ease, transform 0.3s ease",
      }}
    >
      <div style={{ transform: hover === w.id ? "scale(1.04)" : "scale(1)", transition: "transform 720ms cubic-bezier(0.22,1,0.36,1)" }}>
        {w.vimeo ? (
          <div style={{ position: "relative", width: "100%", aspectRatio: "16 / 9", overflow: "hidden",
               background: `linear-gradient(135deg, ${w.tone[0]} 0%, ${w.tone[1]} 55%, ${w.tone[0]} 100%)` }}>
            {thumb && (
              <img src={thumb} alt={w.title}
                style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover",
                  opacity: hover === w.id ? 0 : 1, transition: "opacity 0.3s ease" }} />
            )}
            {shown && (
              <iframe
                ref={iframeRef}
                title={`${w.title} preview`}
                src={`https://player.vimeo.com/video/${w.vimeo}?h=${w.vhash || ""}&background=1&autoplay=1&muted=1&loop=1&autopause=0`}
                style={{ position: "absolute", inset: 0, width: "100%", height: "100%", border: 0, pointerEvents: "none",
                  opacity: hover === w.id ? 1 : 0, transition: "opacity 0.3s ease" }}
                allow="autoplay"
              />
            )}
            {/* play affordance when idle */}
            <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center",
                 opacity: hover === w.id ? 0 : 0.85, transition: "opacity 0.22s ease", pointerEvents: "none" }}>
              <div style={{ width: 56, height: 56, borderRadius: "50%", border: "2px solid rgba(255,255,255,0.85)",
                   display: "flex", alignItems: "center", justifyContent: "center", background: "rgba(10,10,10,0.22)" }}>
                <Icon name="Play" size={20} style={{ color: "#fff", marginLeft: 2 }} />
              </div>
            </div>
          </div>
        ) : (
          <Still tone={w.tone} hover={hover === w.id} />
        )}
      </div>
      <div style={{ position: "absolute", inset: 0, background: "var(--scrim-bottom)", pointerEvents: "none" }} />
      <div style={{ position: "absolute", left: 0, right: 0, bottom: 0, padding: 18, display: "flex", alignItems: "flex-end", justifyContent: "space-between", pointerEvents: "none" }}>
        <div>
          <div style={{ fontFamily: "var(--font-display)", fontWeight: 800, textTransform: "uppercase", letterSpacing: "-0.01em", fontSize: 17, color: "#fff", lineHeight: 1.1 }}>
            {w.title}
          </div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "var(--prlx-graphite-300)", marginTop: 5, letterSpacing: "0.04em" }}>
            {w.client}
          </div>
        </div>
        <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 8, opacity: hover === w.id ? 1 : 0, transform: hover === w.id ? "translateY(0)" : "translateY(6px)", transition: "all 220ms cubic-bezier(0.22,1,0.36,1)" }}>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "#fff", display: "flex", alignItems: "center", gap: 6 }}>
            <Icon name="Clock" size={12} /> {w.runtime}
          </span>
        </div>
      </div>
    </div>
  );
}

function WorkGrid({ onOpen, categories, density }) {
  const { Tag, Button } = window.PRLXDesignSystem_b1b8b9;
  const { useViewport } = window;
  const [cat, setCat] = React.useState("Featured");
  const [hover, setHover] = React.useState(null);
  const [visible, setVisible] = React.useState(12);
  const revealClock = React.useRef(0);
  const { isMobile } = useViewport();

  const cats = ["Featured", ...(categories || window.PRLX_CATS)];
  const allItems = (() => {
    const ORDER = window.PRLX_WORK_ORDER || {};
    if (cat === "Featured") {
      const feat = ORDER["Featured"];
      if (!feat || !feat.length) return window.PRLX_WORK; // not curated yet → show all as a fallback
      const byId = Object.fromEntries(window.PRLX_WORK.map((w) => [w.id, w]));
      return feat.map((id) => byId[id]).filter(Boolean);
    }
    const filtered = window.PRLX_WORK.filter((w) => w.cat === cat);
    const ord = ORDER[cat];
    if (!ord || !ord.length) return filtered;
    const pos = (id) => { const i = ord.indexOf(id); return i === -1 ? 1e9 : i; };
    return filtered.slice().sort((a, b) => pos(a.id) - pos(b.id));
  })();
  const items = allItems.slice(0, visible);

  // Reset the stagger clock + page size whenever the filter changes.
  React.useEffect(() => { revealClock.current = 0; setVisible(12); }, [cat]);

  return (
    <section data-screen-label="Work" id="work" style={{ padding: isMobile ? "64px 20px" : "96px 32px", background: "var(--prlx-ink)" }}>
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", flexWrap: "wrap", gap: isMobile ? 18 : 24, marginBottom: isMobile ? 26 : 36 }}>
        <div>
          <div style={{ fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 11, textTransform: "uppercase", letterSpacing: "0.32em", color: "var(--prlx-graphite-400)", marginBottom: 14 }}>
            ↳ Selected work
          </div>
          <h2 style={{ fontFamily: "var(--font-display)", fontWeight: 800, textTransform: "uppercase", letterSpacing: "-0.02em", fontSize: "clamp(32px, 5vw, 64px)", lineHeight: 1, margin: 0, color: "#fff" }}>
            Now playing
          </h2>
        </div>
        <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
          {cats.map((c) => (
            <Tag key={c} selected={cat === c} onClick={() => setCat(c)}>{c}</Tag>
          ))}
        </div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : `repeat(auto-fill, minmax(${({compact:280,regular:340,wide:440}[density]||340)}px, 1fr))`, gap: 2 }}>
        {items.map((w) => (
          <WorkTile
            key={`${cat}-${w.id}`}
            w={w}
            hover={hover}
            setHover={setHover}
            onOpen={onOpen}
            revealClock={revealClock}
          />
        ))}
      </div>

      {visible < allItems.length && (
        <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 14, marginTop: isMobile ? 36 : 52 }}>
          <Button variant="secondary" size={isMobile ? "md" : "lg"} onClick={() => setVisible((v) => v + 12)}>
            Show more work
          </Button>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--prlx-graphite-500)" }}>
            Showing {items.length} of {allItems.length}
          </span>
        </div>
      )}
    </section>
  );
}
Object.assign(window, { WorkGrid });
