// primitives.jsx — Reusable building blocks for the cinema site.
// StillPlaceholder, GrainOverlay, RevealOnScroll, CustomCursor, Marquee, FilmFrame.

// ── Still / image placeholders ─────────────────────────────────────────────
// All imagery is placeholder — subtly-striped frames with monospace caption.
function StillPlaceholder({ ratio = "2.35", label = "still", tone = "warm", src, objectPosition = "center", className = "", style = {} }) {
  const aspect = ratio === "1.0" ? "1 / 1"
               : ratio === "2.35" ? "2.35 / 1"
               : ratio === "2.39" ? "2.39 / 1"
               : ratio === "1.66" ? "1.66 / 1"
               : ratio === "16/9" ? "16 / 9"
               : ratio;
  const stripes =
    tone === "cool"
      ? "repeating-linear-gradient(135deg, rgba(26,34,48,.85) 0 28px, rgba(46,75,107,.7) 28px 56px)"
      : tone === "dark"
      ? "repeating-linear-gradient(135deg, rgba(14,13,10,.9) 0 28px, rgba(44,39,33,.7) 28px 56px)"
      : "repeating-linear-gradient(135deg, rgba(44,39,33,.9) 0 28px, rgba(138,107,74,.55) 28px 56px)";
  return (
    <div
      className={"still-placeholder " + className}
      style={{
        aspectRatio: aspect,
        background: src ? "#000" : stripes,
        position: "relative",
        overflow: "hidden",
        width: "100%",
        ...style,
      }}
    >
      {src ? (
        <img src={src} alt={label}
             style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", objectPosition, display: "block" }} />
      ) : (<>
        <div
          style={{
            position: "absolute",
            inset: 0,
            background:
              "radial-gradient(ellipse at 30% 20%, rgba(255,255,255,.08), transparent 60%)",
          }}
        />
        <div
          style={{
            position: "absolute",
            left: 14,
            top: 12,
            right: 14,
            display: "flex",
            justifyContent: "space-between",
            fontFamily: "var(--font-mono)",
            fontSize: 10,
            letterSpacing: ".12em",
            color: "rgba(255,255,255,.7)",
            textTransform: "uppercase",
            mixBlendMode: "screen",
          }}
        >
          <span>◎ img</span>
          <span>{ratio}</span>
        </div>
        <div
          style={{
            position: "absolute",
            left: 14,
            bottom: 12,
            right: 14,
            fontFamily: "var(--font-mono)",
            fontSize: 10,
            letterSpacing: ".08em",
            color: "rgba(255,255,255,.85)",
            textTransform: "uppercase",
            mixBlendMode: "screen",
          }}
        >
          {label}
        </div>
      </>)}
    </div>
  );
}

// ── Video clip placeholder (BTS clips etc) ─────────────────────────────────
function ClipPlaceholder({ label, duration, tone = "warm" }) {
  const [hover, setHover] = React.useState(false);
  return (
    <div
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{ position: "relative", cursor: "none" }}
    >
      <StillPlaceholder ratio="16/9" label={label} tone={tone} />
      <div
        style={{
          position: "absolute",
          inset: 0,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          pointerEvents: "none",
        }}
      >
        <div
          style={{
            width: 56,
            height: 56,
            borderRadius: "50%",
            border: "1px solid rgba(255,255,255,.8)",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            background: hover ? "rgba(255,255,255,.15)" : "rgba(0,0,0,.2)",
            backdropFilter: "blur(6px)",
            transition: "all .3s ease",
            transform: hover ? "scale(1.08)" : "scale(1)",
          }}
        >
          <div
            style={{
              width: 0,
              height: 0,
              borderLeft: "10px solid white",
              borderTop: "7px solid transparent",
              borderBottom: "7px solid transparent",
              marginLeft: 3,
            }}
          />
        </div>
      </div>
      <div
        style={{
          position: "absolute",
          right: 10,
          bottom: 10,
          fontFamily: "var(--font-mono)",
          fontSize: 10,
          letterSpacing: ".08em",
          color: "white",
          background: "rgba(0,0,0,.55)",
          padding: "3px 7px",
          borderRadius: 2,
        }}
      >
        {duration}
      </div>
    </div>
  );
}

// ── Grain / film texture overlay ───────────────────────────────────────────
function GrainOverlay({ intensity = 0.12 }) {
  // Animated grain via CSS; SVG turbulence driven by a keyframe
  return (
    <>
      <style>{`
        @keyframes grain {
          0%,100% { transform: translate(0,0) }
          10% { transform: translate(-3%,-2%) }
          20% { transform: translate(2%,3%) }
          30% { transform: translate(-2%,2%) }
          40% { transform: translate(3%,-2%) }
          50% { transform: translate(-3%,1%) }
          60% { transform: translate(1%,-3%) }
          70% { transform: translate(-1%,3%) }
          80% { transform: translate(2%,-1%) }
          90% { transform: translate(-2%,-1%) }
        }
      `}</style>
      <div
        aria-hidden
        style={{
          position: "fixed",
          inset: "-10%",
          pointerEvents: "none",
          zIndex: 9998,
          opacity: intensity,
          mixBlendMode: "overlay",
          backgroundImage:
            'url("data:image/svg+xml;utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%22200%22 height=%22200%22><filter id=%22n%22><feTurbulence type=%22fractalNoise%22 baseFrequency=%220.9%22 numOctaves=%222%22 stitchTiles=%22stitch%22/></filter><rect width=%22100%25%22 height=%22100%25%22 filter=%22url(%23n)%22 opacity=%22.9%22/></svg>")',
          backgroundSize: "240px 240px",
          animation: "grain 1.2s steps(6) infinite",
        }}
      />
    </>
  );
}

// ── Fade / slide in on scroll ──────────────────────────────────────────────
function RevealOnScroll({ children, delay = 0, y = 24, as: Tag = "div", ...rest }) {
  const ref = React.useRef(null);
  const [visible, setVisible] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      ([e]) => {
        if (e.isIntersecting) {
          setVisible(true);
          io.disconnect();
        }
      },
      { threshold: 0.12, rootMargin: "0px 0px -50px 0px" }
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return (
    <Tag
      ref={ref}
      {...rest}
      style={{
        opacity: visible ? 1 : 0,
        transform: visible ? "translateY(0)" : `translateY(${y}px)`,
        transition: `opacity .9s cubic-bezier(.2,.7,.2,1) ${delay}ms, transform 1s cubic-bezier(.2,.7,.2,1) ${delay}ms`,
        ...(rest.style || {}),
      }}
    >
      {children}
    </Tag>
  );
}

// ── Custom cinema cursor ───────────────────────────────────────────────────
function CustomCursor() {
  const hoverCapable = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(hover: hover)").matches;
  if (!hoverCapable) return null;
  const dotRef = React.useRef(null);
  const ringRef = React.useRef(null);
  const [label, setLabel] = React.useState("");
  const [hover, setHover] = React.useState(false);

  React.useEffect(() => {
    let rx = 0, ry = 0, dx = 0, dy = 0, raf;
    const onMove = (e) => {
      dx = e.clientX; dy = e.clientY;
      const t = e.target.closest("[data-cursor]");
      if (t) {
        setHover(true);
        setLabel(t.getAttribute("data-cursor") || "");
      } else {
        setHover(false);
        setLabel("");
      }
    };
    const tick = () => {
      rx += (dx - rx) * 0.18;
      ry += (dy - ry) * 0.18;
      if (dotRef.current) dotRef.current.style.transform = `translate(${dx}px,${dy}px)`;
      if (ringRef.current) ringRef.current.style.transform = `translate(${rx}px,${ry}px)`;
      raf = requestAnimationFrame(tick);
    };
    window.addEventListener("mousemove", onMove);
    raf = requestAnimationFrame(tick);
    return () => {
      window.removeEventListener("mousemove", onMove);
      cancelAnimationFrame(raf);
    };
  }, []);

  return (
    <>
      <div
        ref={dotRef}
        style={{
          position: "fixed",
          left: -4, top: -4,
          width: 8, height: 8, borderRadius: "50%",
          background: "var(--accent)",
          pointerEvents: "none",
          zIndex: 9999,
          mixBlendMode: "difference",
        }}
      />
      <div
        ref={ringRef}
        style={{
          position: "fixed",
          left: hover ? -40 : -18,
          top: hover ? -40 : -18,
          width: hover ? 80 : 36,
          height: hover ? 80 : 36,
          border: "1px solid var(--fg)",
          borderRadius: "50%",
          pointerEvents: "none",
          zIndex: 9999,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          fontFamily: "var(--font-mono)",
          fontSize: 9,
          letterSpacing: ".1em",
          textTransform: "uppercase",
          color: "var(--fg)",
          transition: "width .3s ease, height .3s ease, left .3s ease, top .3s ease, background .3s",
          background: hover ? "rgba(255,255,255,.04)" : "transparent",
          mixBlendMode: "difference",
        }}
      >
        {hover ? label : ""}
      </div>
    </>
  );
}

// ── Marquee strip (for festival names etc) ─────────────────────────────────
function Marquee({ items, speed = 60 }) {
  const content = [...items, ...items, ...items];
  return (
    <div style={{ overflow: "hidden", width: "100%" }}>
      <style>{`@keyframes marquee { 0% { transform: translateX(0) } 100% { transform: translateX(-33.333%) } }`}</style>
      <div
        style={{
          display: "flex",
          gap: 48,
          whiteSpace: "nowrap",
          animation: `marquee ${speed}s linear infinite`,
          width: "fit-content",
        }}
      >
        {content.map((t, i) => (
          <span
            key={i}
            style={{
              fontFamily: "var(--font-display)",
              fontSize: 14,
              letterSpacing: ".18em",
              textTransform: "uppercase",
              color: "var(--fg-dim)",
              display: "inline-flex",
              alignItems: "center",
              gap: 48,
            }}
          >
            {t}
            <span style={{ opacity: 0.4 }}>✦</span>
          </span>
        ))}
      </div>
    </div>
  );
}

// ── Section kicker (eyebrow label) ─────────────────────────────────────────
function Kicker({ index, label, style = {} }) {
  return (
    <div
      style={{
        display: "flex",
        alignItems: "baseline",
        gap: 14,
        fontFamily: "var(--font-mono)",
        fontSize: 11,
        letterSpacing: ".16em",
        textTransform: "uppercase",
        color: "var(--fg-dim)",
        ...style,
      }}
    >
      {index && <span style={{ color: "var(--accent)" }}>[{index}]</span>}
      <span>{label}</span>
    </div>
  );
}

Object.assign(window, {
  StillPlaceholder,
  ClipPlaceholder,
  GrainOverlay,
  RevealOnScroll,
  CustomCursor,
  Marquee,
  Kicker,
});
