/* ============================================================
   scene.jsx — HeroScene: ice mascot, melt-to-flow, balance card.
   One imperative rAF loop drives everything (60fps, no per-frame
   React re-render). Exposes window.HeroScene + window.__slyckMelt.
   ============================================================ */
const { useState, useRef, useEffect } = React;

const FINAL = 1352.40; // S$ counted up to
const CYCLE = 6.0; // seconds per melt loop

function IceSVG() {
  return (
    <svg className="ice-svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
      <defs>
        <linearGradient id="iceGrad" x1="18" y1="2" x2="82" y2="100" gradientUnits="userSpaceOnUse">
          <stop offset="0" stopColor="#EAF3FF" />
          <stop offset="0.52" stopColor="#A8CBFF" />
          <stop offset="1" stopColor="#6BA0F5" />
        </linearGradient>
        <radialGradient id="iceGlow" cx="37" cy="29" r="56" gradientUnits="userSpaceOnUse">
          <stop offset="0" stopColor="#ffffff" stopOpacity="0.85" />
          <stop offset="0.55" stopColor="#ffffff" stopOpacity="0" />
        </radialGradient>
        <filter id="specBlur" x="-50%" y="-50%" width="200%" height="200%">
          <feGaussianBlur stdDeviation="3.0" />
        </filter>
        <filter id="rimBlur" x="-50%" y="-50%" width="200%" height="200%">
          <feGaussianBlur stdDeviation="2.6" />
        </filter>
        <filter id="frost" x="-30%" y="-30%" width="160%" height="160%">
          <feGaussianBlur stdDeviation="0.7" />
        </filter>
      </defs>
      <rect x="0" y="0" width="100" height="100" fill="url(#iceGrad)" />
      <rect x="0" y="0" width="100" height="100" fill="url(#iceGlow)" data-comment-anchor="e238dcdcc1-rect-32-7" />
      {/* the stablecoin, frozen inside — "frozen value" made literal,
          and the coin motif that ties the hero to the logo mark */}
      <g filter="url(#frost)">
        <path d="M44 27 A 21 21 0 0 0 44 67" fill="none" stroke="#ffffff"
          strokeWidth="2.4" strokeLinecap="round" opacity="0.5" />
        <path d="M56 27 A 21 21 0 0 1 56 67" fill="none" stroke="#ffffff"
          strokeWidth="2.4" strokeLinecap="round" opacity="0.5" />
        <text x="50" y="47.5" textAnchor="middle" dominantBaseline="central"
          fontFamily="'Clash Display', sans-serif" fontWeight="600" fontSize="34"
          fill="#ffffff" opacity="0.62">$</text>
      </g>
      {/* faint deep-blue contact shade at the very bottom */}
      <ellipse cx="50" cy="99" rx="42" ry="10" fill="#5A8FE6" opacity="0.35" filter="url(#specBlur)" />
      {/* primary specular highlight, top-left */}
      <ellipse cx="32" cy="26" rx="20" ry="12.5" fill="#ffffff" opacity="0.82"
      filter="url(#specBlur)" transform="rotate(-24 32 26)" />
      {/* small secondary sparkle */}
      <ellipse cx="61" cy="19" rx="5" ry="3" fill="#ffffff" opacity="0.6" filter="url(#specBlur)" />
    </svg>);

}

function HeroScene() {
  const reduced = useReducedMotion();

  const sceneRef = useRef(null);
  const wrapRef = useRef(null); // parallax + breathing + rotation
  const bodyRef = useRef(null); // melt scaleY + squish
  const sweepRef = useRef(null);
  const shadowRef = useRef(null);
  const dropRef = useRef(null);
  const pillRef = useRef(null);
  const cardRef = useRef(null);
  const flashRef = useRef(null);
  const numRef = useRef(null);

  // shared mutable animation state
  const geom = useRef({ dx: 120, dy: 150 });
  const elapsed = useRef(0);
  const cycle0 = useRef(0); // elapsed value at start of current melt cycle
  const doCount = useRef(true); // count 0→FINAL this cycle?
  const ptrTgt = useRef({ x: 0, y: 0 });
  const ptrSp = useRef({ x: { value: 0, velocity: 0 }, y: { value: 0, velocity: 0 } });
  const squish = useRef({ value: 0, velocity: 0 });

  // measure the fall vector: droplet home → top of balance card
  function measure() {
    const d = dropRef.current,c = cardRef.current;
    if (!d || !c) return;
    const dr = d.getBoundingClientRect();
    const cr = c.getBoundingClientRect();
    const homeX = dr.left + dr.width / 2;
    const homeY = dr.top + dr.height / 2;
    geom.current = {
      dx: cr.left + cr.width * 0.5 - homeX,
      dy: cr.top + 8 - homeY
    };
  }

  /* ---- trigger a full (counting) melt cycle — called on load + CTA hover ---- */
  function triggerMelt() {
    cycle0.current = elapsed.current;
    doCount.current = true;
    if (numRef.current) numRef.current.textContent = fmtSGD(0);
    // excited squish kick
    squish.current.velocity = -7.5;
  }
  useEffect(() => {
    window.__slyckMelt = triggerMelt;
    return () => {if (window.__slyckMelt === triggerMelt) delete window.__slyckMelt;};
  }, []);

  /* ---- static fallback ---- */
  useEffect(() => {
    if (!reduced) return;
    if (numRef.current) numRef.current.textContent = fmtSGD(FINAL);
    if (dropRef.current) dropRef.current.style.opacity = "0";
    if (sweepRef.current) sweepRef.current.style.opacity = "0";
  }, [reduced]);

  /* ---- pointer parallax ---- */
  useEffect(() => {
    if (reduced || isTouch()) return;
    const onMove = (e) => {
      const r = sceneRef.current.getBoundingClientRect();
      const nx = clamp((e.clientX - (r.left + r.width / 2)) / (r.width / 2), -1.4, 1.4);
      const ny = clamp((e.clientY - (r.top + r.height / 2)) / (r.height / 2), -1.4, 1.4);
      ptrTgt.current = { x: nx, y: ny };
    };
    const onLeave = () => {ptrTgt.current = { x: 0, y: 0 };};
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseleave", onLeave);
    return () => {
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseleave", onLeave);
    };
  }, [reduced]);

  /* ---- the loop ---- */
  useEffect(() => {
    measure();
    const onResize = () => measure();
    window.addEventListener("resize", onResize);
    if (reduced) return () => window.removeEventListener("resize", onResize);

    let raf,last = null,paused = false;

    /* compute + write one frame at cycle-time t (deterministic; reused by
       the rAF loop and by the hidden-tab debug hook) */
    const applyFrame = (t, e, dt) => {
      /* ----- pointer spring (px) ----- */
      const PX = 13,PY = 9;
      const sx = stepSpring(ptrSp.current.x, ptrTgt.current.x * PX,
      { stiffness: 120, damping: 18, mass: 0.9 }, dt);
      const sy = stepSpring(ptrSp.current.y, ptrTgt.current.y * PY,
      { stiffness: 120, damping: 18, mass: 0.9 }, dt);
      const tilt = ptrTgt.current.x * 4.5;

      /* ----- idle breathing ----- */
      const breatheS = 1 + 0.0075 + 0.0075 * Math.sin(e * (2 * Math.PI / 4));
      const driftR = 1.5 * Math.sin(e * (2 * Math.PI / 8));

      if (wrapRef.current) {
        wrapRef.current.style.transform =
        `translate3d(${sx}px, ${sy}px, 0) rotate(${(driftR + tilt).toFixed(3)}deg) scale(${breatheS.toFixed(4)})`;
      }

      /* ----- squish spring ----- */
      const sq = stepSpring(squish.current, 0, { stiffness: 260, damping: 18, mass: 0.9 }, dt);

      /* ----- melt scaleY (slick→drip) ----- */
      let meltY = 1;
      if (t >= 0.4 && t < 0.9) meltY = lerp(1, 1.08, Ease.inOutSine((t - 0.4) / 0.5));else
      if (t >= 0.9 && t < 1.6) meltY = lerp(1.08, 1, Ease.inOutSine((t - 0.9) / 0.7));
      const bodyY = meltY * (1 + sq * 0.085);
      const bodyX = (2 - meltY) * (1 - sq * 0.06);
      if (bodyRef.current)
      bodyRef.current.style.transform = `scale(${bodyX.toFixed(4)}, ${bodyY.toFixed(4)})`;

      /* ----- frost sweep ----- */
      if (sweepRef.current) {
        if (t < 0.42) {
          const p = t / 0.42;
          sweepRef.current.style.opacity = (Math.sin(p * Math.PI) * 0.9).toFixed(3);
          sweepRef.current.style.transform =
          `rotate(18deg) translateX(${lerp(-180, 200, p).toFixed(1)}%)`;
        } else {
          sweepRef.current.style.opacity = "0";
        }
      }

      /* ----- drip droplet → value pill ----- */
      const { dx, dy } = geom.current;
      if (dropRef.current) {
        const d = dropRef.current;
        if (t < 0.9) {
          d.style.opacity = "0";
          d.style.transform = "translate(-50%, 0) scale(0.6)";
        } else if (t < 1.95) {
          const dp = clamp((t - 0.9) / 0.7, 0, 1);
          const fall = Ease.outBack(Math.min(dp, 1), 1.45);
          const drift = Ease.outCubic(Math.min(dp, 1));
          const x = dx * drift;
          const y = dy * fall;
          // morph circle → pill
          const m = Ease.outCubic(clamp((dp - 0.45) / 0.55, 0, 1));
          d.style.width = `${lerp(22, 134, m).toFixed(1)}px`;
          d.style.height = `${lerp(22, 40, m).toFixed(1)}px`;
          d.style.borderRadius = `${lerp(999, 13, m).toFixed(0)}px`;
          d.style.background = m > 0.55 ?
          "var(--surface)" :
          "linear-gradient(160deg, var(--ice-light), var(--ice-deep))";
          d.style.boxShadow = m > 0.55 ?
          "var(--shadow-press)" : "0 6px 14px rgba(46,107,255,0.28)";
          // appear, then fade as it merges into the card
          let op = clamp(dp / 0.12, 0, 1);
          if (t > 1.7) op *= clamp(1 - (t - 1.7) / 0.25, 0, 1);
          d.style.opacity = op.toFixed(3);
          d.style.transform = `translate(calc(-50% + ${x.toFixed(1)}px), ${y.toFixed(1)}px) scale(1)`;
          if (pillRef.current)
          pillRef.current.style.opacity = clamp((dp - 0.6) / 0.3, 0, 1).toFixed(3);
        } else {
          d.style.opacity = "0";
        }
      }

      /* ----- card land: lift + mint flash + count ----- */
      if (cardRef.current) {
        let lift = 0;
        if (t >= 1.55 && t < 2.1) lift = -8 * Math.sin(clamp((t - 1.55) / 0.55, 0, 1) * Math.PI);
        cardRef.current.style.transform = `translateY(${lift.toFixed(2)}px)`;
      }
      if (flashRef.current) {
        let fop = 0;
        if (t >= 1.55 && t < 2.0) fop = Math.sin(clamp((t - 1.55) / 0.45, 0, 1) * Math.PI);
        flashRef.current.style.opacity = fop.toFixed(3);
      }
      if (numRef.current && doCount.current) {
        if (t < 1.6) numRef.current.textContent = fmtSGD(0);else
        if (t < 2.4) numRef.current.textContent = fmtSGD(FINAL * Ease.outCubic((t - 1.6) / 0.8));else
        numRef.current.textContent = fmtSGD(FINAL);
      }
    }; // end applyFrame

    const loop = (ts) => {
      if (paused) {last = ts;raf = requestAnimationFrame(loop);return;}
      if (last == null) last = ts;
      let dt = (ts - last) / 1000;last = ts;
      dt = Math.min(dt, 1 / 30);
      elapsed.current += dt;
      const e = elapsed.current;
      let t = e - cycle0.current; // advance / wrap the melt cycle
      if (t >= CYCLE) {cycle0.current += CYCLE;t -= CYCLE;doCount.current = false;}
      applyFrame(t, e, dt);
      raf = requestAnimationFrame(loop);
    };

    // debug: deterministically paint a single cycle-time (verifies choreography
    // even when the tab is hidden and rAF is throttled)
    window.__slyckFrame = (ct, count = true) => {doCount.current = count;applyFrame(ct, ct, 0);};
    window.__slyckPause = (v = true) => {paused = v;};

    triggerMelt(); // kick first cycle on load
    raf = requestAnimationFrame(loop);
    return () => {cancelAnimationFrame(raf);window.removeEventListener("resize", onResize);};
  }, [reduced]);

  return (
    <div className="hero-scene" ref={sceneRef}>
      <div className="radial-wash" />

      <div className="ice-stage">
        <div className="ice-wrap" ref={wrapRef}>
          <div className="ice-body" ref={bodyRef}>
            <IceSVG />
            <div className="ice-sweep" ref={sweepRef} />
          </div>
          <div className="ice-shadow" ref={shadowRef} />
        </div>
      </div>

      <div className="droplet" ref={dropRef}>
        <span className="pill-text" ref={pillRef}>+1,000 USDT</span>
      </div>

      <div className="balance-card" ref={cardRef}>
        <div className="mint-flash" ref={flashRef} />
        <div className="bc-head">
          <span className="bc-label">Your balance</span>
          <span className="bc-badge"><span className="live-dot" />Cashed out</span>
        </div>
        <div className="bc-amount" ref={numRef}>{reduced ? fmtSGD(FINAL) : fmtSGD(0)}</div>
        <div className="bc-sub">
          <span className="from-usdt">1,000 USDT</span>
          <svg className="bc-arrow" width="20" height="12" viewBox="0 0 20 12" fill="none" aria-hidden="true">
            <path d="M1 6h16M13 1.5 18.5 6 13 10.5" stroke="currentColor" strokeWidth="1.6"
            strokeLinecap="round" strokeLinejoin="round" />
          </svg>
          <span>at S$1.3524 · in seconds</span>
        </div>
      </div>
    </div>);

}

window.HeroScene = HeroScene;
