// Entrance animation: video plays fullscreen, freezes on last frame,
// then shatters into glass shards revealing the page.

const { useState, useEffect, useRef, useMemo } = React;

// Build N shard polygons that tile the viewport with jittered cell boundaries.
// Each shard knows its outward direction (so it flies away from screen center).
function buildShards(cols = 8, rows = 6, seed = 19) {
  // Mulberry32-ish deterministic jitter so layout is stable.
  let s = seed;
  const rnd = () => {
    s = (s * 1664525 + 1013904223) >>> 0;
    return ((s >>> 8) & 0xffff) / 0xffff;
  };

  // Build a jittered grid of corner points.
  const pts = [];
  for (let r = 0; r <= rows; r++) {
    pts[r] = [];
    for (let c = 0; c <= cols; c++) {
      const onEdge = c === 0 || c === cols || r === 0 || r === rows;
      const jx = onEdge ? 0 : (rnd() - 0.5) * 14;
      const jy = onEdge ? 0 : (rnd() - 0.5) * 14;
      pts[r][c] = [(c / cols) * 100 + jx, (r / rows) * 100 + jy];
    }
  }

  const shards = [];
  for (let r = 0; r < rows; r++) {
    for (let c = 0; c < cols; c++) {
      const tl = pts[r][c];
      const tr = pts[r][c + 1];
      const br = pts[r + 1][c + 1];
      const bl = pts[r + 1][c];
      // Optional: split each cell along a diagonal for a more shattered feel.
      const splitDiag = (c + r) % 2 === 0;

      const center = [
        (tl[0] + tr[0] + br[0] + bl[0]) / 4,
        (tl[1] + tr[1] + br[1] + bl[1]) / 4,
      ];
      const dx = center[0] - 50;
      const dy = center[1] - 50;
      const len = Math.max(0.001, Math.hypot(dx, dy));
      const dir = [dx / len, dy / len];
      const dist = 60 + rnd() * 50; // vmax-ish travel

      if (splitDiag) {
        shards.push(makeShard([tl, tr, br], center, dir, dist, rnd));
        shards.push(makeShard([tl, br, bl], center, dir, dist, rnd));
      } else {
        shards.push(makeShard([tl, tr, bl], center, dir, dist, rnd));
        shards.push(makeShard([tr, br, bl], center, dir, dist, rnd));
      }
    }
  }
  return shards;
}

function makeShard(poly, center, dir, dist, rnd) {
  const clip =
    "polygon(" +
    poly.map(([x, y]) => `${x.toFixed(2)}% ${y.toFixed(2)}%`).join(", ") +
    ")";
  // Slight rotation tumble — ±540°
  const rot = (rnd() - 0.5) * 1080;
  const delay = rnd() * 0.18;
  // Travel distance scaled by how far from center
  const cx = center[0], cy = center[1];
  const radial = Math.hypot(cx - 50, cy - 50);
  const travel = dist * (0.55 + radial / 60);
  return {
    clip,
    tx: (dir[0] * travel).toFixed(1) + "vmax",
    ty: (dir[1] * travel + 12).toFixed(1) + "vmax", // slight gravity
    rot: rot.toFixed(0) + "deg",
    delay: delay.toFixed(2) + "s",
  };
}

function Entrance({ src, onComplete }) {
  const videoRef = useRef(null);
  const [phase, setPhase] = useState("loading"); // loading → playing → shatter → done
  const [progress, setProgress] = useState(0);
  const [snapshot, setSnapshot] = useState(null);
  const triggeredRef = useRef(false);

  const triggerShatter = () => {
    if (triggeredRef.current) return;
    triggeredRef.current = true;
    const v = videoRef.current;
    let dataUrl = null;
    if (v && v.videoWidth) {
      try {
        const c = document.createElement("canvas");
        const maxW = 1280;
        const scale = Math.min(1, maxW / v.videoWidth);
        c.width = Math.round(v.videoWidth * scale);
        c.height = Math.round(v.videoHeight * scale);
        c.getContext("2d").drawImage(v, 0, 0, c.width, c.height);
        dataUrl = c.toDataURL("image/jpeg", 0.82);
      } catch (e) {
        // CORS or other — fall back to colour wash.
      }
      try { v.pause(); } catch (e) {}
    }
    setSnapshot(dataUrl);
    setPhase("shatter");
    setTimeout(() => {
      setPhase("done");
      onComplete && onComplete();
    }, 3100);
  };

  // Loading phase: count up, then advance to playing.
  useEffect(() => {
    if (phase !== "loading") return;
    const start = performance.now();
    const dur = 2200;
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / dur);
      setProgress(p);
      if (p < 1) raf = requestAnimationFrame(tick);
      else {
        // Wait until the video has actually buffered a frame before swapping in.
        const v = videoRef.current;
        if (v && v.readyState >= 2) {
          setPhase("playing");
        } else if (v) {
          const onReady = () => { setPhase("playing"); v.removeEventListener("loadeddata", onReady); };
          v.addEventListener("loadeddata", onReady);
          // Hard fallback so we never deadlock.
          setTimeout(() => setPhase("playing"), 1200);
        } else {
          setPhase("playing");
        }
      }
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [phase]);

  useEffect(() => {
    if (phase !== "playing") return;
    const v = videoRef.current;
    if (!v) return;
    // Auto-shatter when video ends, OR after a hard ceiling, OR on click/key.
    const onEnded = () => triggerShatter();
    const onKey = (e) => { if (e.key === "Escape" || e.key === " ") triggerShatter(); };
    v.addEventListener("ended", onEnded);
    const onError = () => triggerShatter();
    v.addEventListener("error", onError);
    window.addEventListener("keydown", onKey);
    return () => {
      v.removeEventListener("ended", onEnded);
      v.removeEventListener("error", onError);
      window.removeEventListener("keydown", onKey);
    };
  }, [phase]);

  const shards = useMemo(() => buildShards(8, 6, 23), []);

  if (phase === "done") return null;

  return (
    <div
      className={"we-ev phase-" + phase}
      role="presentation"
      onClick={phase === "loading" ? undefined : triggerShatter}
    >
      {phase === "loading" && (
        <div className="we-ev-load">
          <img className="we-ev-load-bg" src="assets/img-stadium.jpg" alt="" />
          <div className="we-ev-load-tint" />
          <div className="we-ev-load-grain" />
          <div className="we-ev-load-tl">
            <span className="we-ev-load-mark-dot" />
            WE<i>26</i>
          </div>
          <div className="we-ev-load-tr">FIFA WORLD CUP · N°23</div>
          <div className="we-ev-load-mid">
            <div className="we-ev-load-ring">
              <svg viewBox="0 0 120 120">
                <circle cx="60" cy="60" r="54" stroke="rgba(241,235,221,.18)" strokeWidth="2" fill="none" />
                <circle
                  cx="60" cy="60" r="54"
                  stroke="#E2B441" strokeWidth="2" fill="none"
                  strokeDasharray={2 * Math.PI * 54}
                  strokeDashoffset={(1 - progress) * 2 * Math.PI * 54}
                  transform="rotate(-90 60 60)"
                  strokeLinecap="round"
                />
              </svg>
              <span className="we-ev-load-pct">{Math.round(progress * 100).toString().padStart(2, "0")}</span>
            </div>
            <div className="we-ev-load-cap">
              <span>Booting markets</span>
              <em>USA · CAN · MEX · Jun 11 — Jul 19, 2026</em>
            </div>
          </div>
        </div>
      )}

      {/* Video is mounted during loading too (hidden) so it preloads. */}
      {(phase === "loading" || phase === "playing") && (
        <video
          ref={videoRef}
          className="we-ev-video"
          src={src}
          autoPlay
          muted
          playsInline
          preload="auto"
          style={phase === "loading" ? { opacity: 0, pointerEvents: "none" } : undefined}
        />
      )}

      {phase === "shatter" && (
        <>
          {snapshot && (
            <div
              className="we-ev-frozen"
              style={{ backgroundImage: `url(${snapshot})` }}
            />
          )}
          <svg
            className="we-ev-cracks"
            viewBox="0 0 100 100"
            preserveAspectRatio="none"
            aria-hidden="true"
          >
            <g
              stroke="rgba(255,255,255,.95)"
              strokeWidth=".18"
              fill="none"
              strokeLinecap="round"
            >
              <path d="M50 50 L8 6" />
              <path d="M50 50 L94 9" />
              <path d="M50 50 L99 54" />
              <path d="M50 50 L74 98" />
              <path d="M50 50 L22 96" />
              <path d="M50 50 L2 60" />
              <path d="M50 50 L33 6" />
              <path d="M50 50 L66 6" />
              <path d="M14 30 L36 44 L52 28 L70 38 L88 22" />
              <path d="M12 70 L34 60 L50 78 L72 62 L92 78" />
            </g>
          </svg>
          <div className="we-ev-flash" />
          {shards.map((s, i) => (
            <div
              key={i}
              className="we-ev-shard"
              style={{
                clipPath: s.clip,
                WebkitClipPath: s.clip,
                backgroundImage: snapshot ? `url(${snapshot})` : undefined,
                "--tx": s.tx,
                "--ty": s.ty,
                "--rot": s.rot,
                "--delay": s.delay,
              }}
            />
          ))}
        </>
      )}
    </div>
  );
}

window.Entrance = Entrance;
