// Media placeholder components — striped SVG for images, pattern with subtle motion for video.
// If `src` is provided, render the real media. Otherwise fall back to the labelled placeholder.
// Tone 0..7 nudges the placeholder fill so 8 cards don't look identical.

function MediaPlaceholder({ kind, tone = 0, src, label, videoAr, controls }) {
  if (src) {
    if (kind === "youtube") {
      // Accept either a full URL or just a video id
      const id = src.includes("/") || src.includes("=")
        ? (src.match(/(?:v=|youtu\.be\/|embed\/)([\w-]{11})/) || [])[1] || src
        : src;
      return (
        <FullscreenMedia>
          <iframe
            className="media-real media-iframe"
            src={`https://www.youtube-nocookie.com/embed/${id}?rel=0&modestbranding=1`}
            title="YouTube video"
            frameBorder="0"
            referrerPolicy="strict-origin-when-cross-origin"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
            allowFullScreen
          />
        </FullscreenMedia>
      );
    }
    if (kind === "vimeo") {
      // Accept full URL or just numeric id (with optional /h-hash for unlisted videos)
      const m = String(src).match(/vimeo\.com\/(?:video\/)?(\d+)(?:\/([\w]+))?/);
      const id = m ? m[1] : String(src).split("/")[0];
      const rawHash = m && m[2] ? m[2] : "";
      // Controls mode: full player UI, no autoplay, no background crop.
      if (controls) {
        const q = rawHash ? `?h=${rawHash}` : "";
        return (
          <FullscreenMedia>
            <iframe
              className="media-real media-iframe"
              src={`https://player.vimeo.com/video/${id}${q}`}
              title="Vimeo video"
              frameBorder="0"
              allow="autoplay; fullscreen; picture-in-picture"
              allowFullScreen
            />
          </FullscreenMedia>
        );
      }
      const hash = rawHash ? `&h=${rawHash}` : "";
      return (
        <div className="media-cover" style={{ "--video-ar": videoAr || "16 / 9" }}>
          <iframe
            className="media-real media-iframe"
            src={`https://player.vimeo.com/video/${id}?background=1&autoplay=1&loop=1&muted=1&autopause=0${hash}`}
            title="Vimeo video"
            frameBorder="0"
            allow="autoplay; fullscreen; picture-in-picture"
            allowFullScreen
          />
        </div>
      );
    }
    if (kind === "video") {
      return <AutoVideo src={src} />;
    }
    return <img className="media-real" src={src} alt="" />;
  }

  // base beige rgb(206,199,183) — vary lightness/hue tiny amounts so 8 cards have rhythm.
  const tones = [
    "oklch(0.82 0.020 80)",
    "oklch(0.80 0.018 75)",
    "oklch(0.83 0.022 85)",
    "oklch(0.78 0.020 78)",
    "oklch(0.81 0.024 82)",
    "oklch(0.79 0.018 70)",
    "oklch(0.84 0.020 88)",
    "oklch(0.77 0.022 76)",
  ];
  const fg = "rgba(0,0,0,0.06)";
  const bg = tones[tone % tones.length];

  return (
    <div className="media-placeholder" data-kind={kind}>
      <svg
        className="media-stripes"
        width="100%"
        height="100%"
        preserveAspectRatio="none"
        viewBox="0 0 100 100"
        aria-hidden="true"
      >
        <rect width="100" height="100" fill={bg} />
        <defs>
          <pattern id={`stripes-${tone}`} width="2" height="2" patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
            <line x1="0" y1="0" x2="0" y2="2" stroke={fg} strokeWidth="0.4" />
          </pattern>
        </defs>
        <rect width="100" height="100" fill={`url(#stripes-${tone})`} />
      </svg>
      {label !== false && (
        <div className="media-label">
          <span>{kind === "video" ? "VIDEO" : "IMAGE"}</span>
          <span className="dot">·</span>
          <span>{kind === "video" ? "drop .mp4 here" : "drop image here"}</span>
        </div>
      )}
      {kind === "video" && (
        <div className="media-vid-mark" aria-hidden="true">
          <svg width="14" height="14" viewBox="0 0 14 14"><circle cx="7" cy="7" r="3" fill="currentColor" /></svg>
          <span>00:00</span>
        </div>
      )}
    </div>
  );
}

window.MediaPlaceholder = MediaPlaceholder;

// Wraps a controls-mode video iframe and adds an explicit fullscreen toggle.
// Uses the Fullscreen API on the wrapper so it works regardless of whether the
// embedded player's own fullscreen button is reachable.
function FullscreenMedia({ children }) {
  const ref = React.useRef(null);
  const [isFs, setIsFs] = React.useState(false);
  const [cssFs, setCssFs] = React.useState(false);

  React.useEffect(() => {
    const onChange = () => setIsFs(document.fullscreenElement === ref.current);
    document.addEventListener("fullscreenchange", onChange);
    document.addEventListener("webkitfullscreenchange", onChange);
    return () => {
      document.removeEventListener("fullscreenchange", onChange);
      document.removeEventListener("webkitfullscreenchange", onChange);
    };
  }, []);

  // Esc exits CSS-fallback fullscreen
  React.useEffect(() => {
    if (!cssFs) return;
    const onKey = (e) => { if (e.key === "Escape") setCssFs(false); };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [cssFs]);

  const active = isFs || cssFs;

  const toggle = (e) => {
    e.preventDefault();
    e.stopPropagation();
    const el = ref.current;
    if (!el) return;
    if (active) {
      if (document.fullscreenElement === el || document.webkitFullscreenElement === el) {
        (document.exitFullscreen || document.webkitExitFullscreen || (() => {})).call(document);
      }
      setCssFs(false);
      return;
    }
    const req = el.requestFullscreen || el.webkitRequestFullscreen;
    if (req) {
      const p = req.call(el);
      if (p && p.catch) p.catch(() => setCssFs(true));
    } else {
      setCssFs(true);
    }
  };

  return (
    <div className={`media-fs-wrap${cssFs ? " is-css-fs" : ""}`} ref={ref}>
      {children}
      <button
        type="button"
        className="media-fs-btn"
        onClick={toggle}
        aria-label={active ? "Exit fullscreen" : "Fullscreen"}
        title={active ? "Exit fullscreen" : "Fullscreen"}
      >
        {active ? (
          <svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true">
            <path d="M6 1v4a1 1 0 0 1-1 1H1M10 1v4a1 1 0 0 0 1 1h4M6 15v-4a1 1 0 0 0-1-1H1M10 15v-4a1 1 0 0 1 1-1h4"
              fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
          </svg>
        ) : (
          <svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true">
            <path d="M1 5V2a1 1 0 0 1 1-1h3M15 5V2a1 1 0 0 0-1-1h-3M1 11v3a1 1 0 0 0 1 1h3M15 11v3a1 1 0 0 1-1 1h-3"
              fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
          </svg>
        )}
      </button>
    </div>
  );
}
window.FullscreenMedia = FullscreenMedia;

// Robust autoplaying video for iOS Safari.
// React doesn't always set the `muted` IDL property in time; we set it imperatively.
// We also call .play() once metadata is ready, and pause when the element scrolls out of view.
function AutoVideo({ src }) {
  const ref = React.useRef(null);

  React.useEffect(() => {
    const v = ref.current;
    if (!v) return;
    // CRUCIAL on iOS: set muted as the IDL property, not just the attribute.
    v.muted = true;
    v.defaultMuted = true;
    v.playsInline = true;

    const tryPlay = () => {
      const p = v.play();
      if (p && typeof p.catch === "function") p.catch(() => {});
    };

    // Try immediately and again on common readiness events.
    tryPlay();
    v.addEventListener("loadedmetadata", tryPlay);
    v.addEventListener("canplay", tryPlay);

    // Pause when scrolled offscreen, resume when back — saves battery on mobile.
    let io;
    if ("IntersectionObserver" in window) {
      io = new IntersectionObserver((entries) => {
        for (const e of entries) {
          if (e.isIntersecting) tryPlay();
          else v.pause();
        }
      }, { threshold: 0.01 });
      io.observe(v);
    }

    return () => {
      v.removeEventListener("loadedmetadata", tryPlay);
      v.removeEventListener("canplay", tryPlay);
      if (io) io.disconnect();
    };
  }, [src]);

  return (
    <video
      ref={ref}
      className="media-real"
      src={src}
      autoPlay
      muted
      loop
      playsInline
      preload="auto"
      webkit-playsinline="true"
      x5-playsinline="true"
      disableRemotePlayback
    />
  );
}
