// Onboarding Loading Animation — RedGone hero
// New mechanic: a single solid red flood (deepest red on RIGHT, lighter on LEFT)
// is REVEALED as white from the left as the angel "pushes" rightward.
// We achieve this by overlaying var(--white-pure) clipped to the white-side
// of the boundary on top of the full-bleed red. The boundary moves; the white
// reveals; the numeral's color flips at the boundary line per glyph.

const OnboardingFrame = ({ percent = 0, label = "Scanning your communication history.", live = false }) => {
  const W = 1200, H = 760;
  const numeralStr = `${Math.round(percent)}%`;
  const numeralFontSize = 220;
  const ease = "clip-path 220ms cubic-bezier(0.16,1,0.3,1), left 220ms cubic-bezier(0.16,1,0.3,1)";

  return (
    <div style={{
      position: "relative",
      width: W, height: H,
      overflow: "hidden",
      background: "var(--white-pure)",
    }}>
      {/* Full-bleed red flood: lighter/transparent-pink on left, dense red on right */}
      <div style={{
        position: "absolute", inset: 0,
        background: "var(--onboarding-flood)",
      }}/>

      {/* Subtle grain over the red */}
      <svg style={{ position: "absolute", inset: 0, mixBlendMode: "overlay", opacity: 0.45, pointerEvents: "none" }}
        width="100%" height="100%">
        <defs>
          <filter id="grain">
            <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" seed="3"/>
            <feColorMatrix values="0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.06 0"/>
          </filter>
        </defs>
        <rect width="100%" height="100%" filter="url(#grain)" />
      </svg>

      {/* WHITE REVEAL — covers the left portion (pushed-clean side) */}
      <div style={{
        position: "absolute", inset: 0,
        background: "var(--white-pure)",
        clipPath: `polygon(0 0, ${(percent/100)*100}% 0, ${(percent/100)*100}% 100%, 0 100%)`,
        transition: live ? ease : "none",
      }}/>

      {/* Soft "vapor" wisp at the boundary, on the white side, like the red is being purified */}
      {percent > 1 && percent < 100 && (
        <div style={{
          position: "absolute", top: 0, bottom: 0,
          left: `calc(${(percent/100)*100}% - 80px)`, width: 160,
          background: "radial-gradient(ellipse at right, rgba(255,255,255,0.85) 0%, rgba(255,255,255,0.0) 70%)",
          pointerEvents: "none",
          transition: live ? "left 220ms cubic-bezier(0.16,1,0.3,1)" : "none",
        }}/>
      )}

      {/* Boundary hairline — barely there */}
      <div style={{
        position: "absolute", top: "12%", bottom: "12%",
        left: `${(percent/100)*100}%`, width: 1,
        background: percent < 50 ? "rgba(10,22,40,0.10)" : "rgba(10,22,40,0.06)",
        transition: live ? "left 220ms cubic-bezier(0.16,1,0.3,1)" : "none",
      }}/>

      {/* Numeral — split at the boundary line.
          Numeral lives in a full-bleed layer; clip is taken from the same
          % of full container width so the split aligns with the white reveal. */}
      <div style={{
        position: "absolute", inset: 0,
        display: "flex", alignItems: "center", justifyContent: "center",
        pointerEvents: "none",
        color: "#FFFFFF",
      }}>
        <div className="serif" style={{
          fontSize: numeralFontSize, fontWeight: 600, letterSpacing: "-0.04em",
          color: "#FFFFFF", lineHeight: 1,
        }}>{numeralStr}</div>
      </div>
      {/* Midnight numeral, clipped to white side, sits ABOVE the white reveal */}
      <div style={{
        position: "absolute", inset: 0,
        display: "flex", alignItems: "center", justifyContent: "center",
        pointerEvents: "none",
        clipPath: `polygon(0 0, ${(percent/100)*100}% 0, ${(percent/100)*100}% 100%, 0 100%)`,
        transition: live ? ease : "none",
      }}>
        <div className="serif" style={{
          fontSize: numeralFontSize, fontWeight: 600, letterSpacing: "-0.04em",
          color: "var(--midnight)", lineHeight: 1,
        }}>{numeralStr}</div>
      </div>

      {/* Sub label */}
      <div style={{
        position: "absolute", left: 0, right: 0, bottom: 130,
        textAlign: "center", pointerEvents: "none",
      }}>
        {percent < 100 ? (
          <div className="serif" style={{
            fontSize: 22, fontWeight: 500,
            color: percent < 50 ? "rgba(255,255,255,0.92)" : "var(--midnight-soft)",
            letterSpacing: "-0.01em",
          }}>{label}</div>
        ) : (
          <div className="serif" style={{ fontSize: 30, fontWeight: 600, color: "var(--midnight)", letterSpacing: "-0.03em" }}>
            Your inbox is clear.
          </div>
        )}
      </div>

      {/* Angel — sits at boundary, side profile, leaning right, pushing */}
      <div style={{
        position: "absolute", top: "50%",
        left: `calc(${(percent/100)*100}% - 110px)`,
        transform: "translateY(-50%)",
        transition: live ? "left 220ms cubic-bezier(0.16,1,0.3,1)" : "none",
        filter: "drop-shadow(0 14px 24px rgba(10,22,40,0.18))",
      }}>
        <AngelRobot size={percent === 100 ? 220 : 180} view={percent === 100 ? "front" : "side"} />
      </div>

      {/* CTA at 100% */}
      {percent >= 100 && (
        <div style={{
          position: "absolute", left: 0, right: 0, bottom: 60,
          display: "flex", justifyContent: "center",
        }}>
          <button className="neu-btn neu-btn-primary" style={{ fontSize: 14, padding: "16px 26px" }}>
            See your compliance score →
          </button>
        </div>
      )}

      {/* Wordmark + counter */}
      <div style={{ position: "absolute", top: 32, left: 40, display: "flex", alignItems: "center", gap: 10 }}>
        <span style={{
          width: 10, height: 10, borderRadius: 999,
          background: percent < 50 ? "#FFFFFF" : "var(--red-core)",
          boxShadow: percent < 50 ? "0 0 0 4px rgba(255,255,255,0.2)" : "0 0 0 4px rgba(230,57,70,0.18)",
        }}/>
        <span className="micro" style={{ color: percent < 50 ? "rgba(255,255,255,0.9)" : "var(--midnight)" }}>RedGone</span>
      </div>
      <div className="mono" style={{
        position: "absolute", top: 32, right: 40,
        color: percent < 50 ? "rgba(255,255,255,0.9)" : "var(--midnight-soft)",
        fontSize: 12, letterSpacing: "0.06em",
      }}>
        {percent < 100 ? `SCAN · ${Math.round(percent).toString().padStart(3, "0")}%` : "SCAN · COMPLETE"}
      </div>
    </div>
  );
};

const OnboardingLive = () => {
  const [pct, setPct] = React.useState(0);
  const [running, setRunning] = React.useState(true);

  React.useEffect(() => {
    if (!running) return;
    let raf;
    let t0 = performance.now();
    const segments = [
      { from: 0, to: 22, dur: 1200 },
      { from: 22, to: 24, dur: 600 },
      { from: 24, to: 58, dur: 1900 },
      { from: 58, to: 62, dur: 700 },
      { from: 62, to: 88, dur: 1700 },
      { from: 88, to: 91, dur: 500 },
      { from: 91, to: 100, dur: 1100 },
    ];
    const total = segments.reduce((s, x) => s + x.dur, 0);
    const tick = () => {
      const e = performance.now() - t0;
      let acc = 0; let v = 100;
      for (const seg of segments) {
        if (e < acc + seg.dur) {
          const k = (e - acc) / seg.dur;
          const ease = 1 - Math.pow(1 - k, 3);
          v = seg.from + (seg.to - seg.from) * ease;
          break;
        }
        acc += seg.dur;
      }
      if (e >= total) v = 100;
      setPct(v);
      if (e < total + 1500) raf = requestAnimationFrame(tick);
      else setRunning(false);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [running]);

  return (
    <div style={{ position: "relative" }}>
      <OnboardingFrame percent={pct} live={true}/>
      <button
        onClick={() => { setPct(0); setRunning(true); }}
        className="neu-chip"
        style={{ position: "absolute", bottom: 16, right: 16, fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase" }}
      >Replay</button>
    </div>
  );
};

window.OnboardingFrame = OnboardingFrame;
window.OnboardingLive = OnboardingLive;

// ──────────────────────────────────────────────────────────────────────
// OnboardingHero — full-viewport, manual-start, smooth motion.
// Used by /onboarding route. Original OnboardingFrame/Live preserved
// above for /canvas compatibility.
// ──────────────────────────────────────────────────────────────────────

// Mascot motion keyframes live in tokens.css (rg-float-soft, rg-bounce-push).

const OnboardingHero = () => {
  const route = (typeof useRoute === "function") ? useRoute() : null;
  const navigate = route ? route.navigate : (p) => { window.location.href = p; };

  const [state, setState] = React.useState("idle"); // idle | scanning | done
  const [pct, setPct] = React.useState(0);
  const rafRef = React.useRef(null);

  const startScan = () => {
    if (state !== "idle") return;
    setState("scanning");

    const segments = [
      { from: 0,  to: 22,  dur: 1400 },
      { from: 22, to: 24,  dur: 600  },
      { from: 24, to: 58,  dur: 2100 },
      { from: 58, to: 62,  dur: 700  },
      { from: 62, to: 88,  dur: 1900 },
      { from: 88, to: 91,  dur: 500  },
      { from: 91, to: 100, dur: 1300 },
    ];
    const total = segments.reduce((s, x) => s + x.dur, 0);
    const t0 = performance.now();

    const tick = () => {
      const e = performance.now() - t0;
      let acc = 0; let v = 100;
      for (const seg of segments) {
        if (e < acc + seg.dur) {
          const k = (e - acc) / seg.dur;
          const ease = 1 - Math.pow(1 - k, 3);
          v = seg.from + (seg.to - seg.from) * ease;
          break;
        }
        acc += seg.dur;
      }
      if (e >= total) v = 100;
      setPct(v);
      if (e < total) {
        rafRef.current = requestAnimationFrame(tick);
      } else {
        rafRef.current = null;
        setTimeout(() => setState("done"), 450);
      }
    };
    rafRef.current = requestAnimationFrame(tick);
  };

  const reset = () => {
    if (rafRef.current) cancelAnimationFrame(rafRef.current);
    rafRef.current = null;
    setState("idle");
    setPct(0);
  };

  React.useEffect(() => () => {
    if (rafRef.current) cancelAnimationFrame(rafRef.current);
  }, []);

  // Mascot positioning. Layout strategy:
  //  - idle:     not rendered — page is fully red, the angel only appears
  //              once scanning begins to push the red back
  //  - scanning: tracks the boundary at pct% with a leftward offset, push-bounce
  //  - done:     glides to upper-right of the big numeral, flips left-facing
  const mascotSize = 160;
  const mascotBox = Math.round(mascotSize * 1.35);
  const mascotOffsetLeft = mascotBox + 56; // distance from boundary

  let mascotLeft, mascotTop, mascotView, mascotAnim, mascotTransform;
  if (state === "scanning") {
    // Always ride the boundary. At pct=0 the mascot's left edge is at
    // -mascotOffsetLeft (off-screen left); as pct climbs the mascot slides
    // in behind the red→white line, pushing it. No anchor/jump in the
    // middle of the run.
    mascotLeft = `calc(${pct}% - ${mascotOffsetLeft}px)`;
    mascotTop = "50%";
    mascotView = "side";
    mascotAnim = "rg-bounce-push 620ms ease-in-out infinite";
    mascotTransform = "translateY(-50%)";
  } else if (state === "done") {
    // Upper-right of the big percentage. Sit clearly past the numeral's
    // right edge with breathing room, and noticeably above its top edge.
    mascotLeft = "calc(50% + min(22vw, 320px))";
    mascotTop = "calc(50% - min(14vw, 200px))";
    mascotView = "front";
    mascotAnim = "rg-float-soft 2.6s ease-in-out infinite";
    mascotTransform = "translate(-50%, -50%)";
  }

  // Mascot transition: only animate the `done` glide. During scanning, rAF
  // drives `left` directly and CSS transitions fight that.
  const mascotTransition =
    state === "done" ? "left 900ms cubic-bezier(0.16,1,0.3,1), top 900ms cubic-bezier(0.16,1,0.3,1)"
    : "none";

  // Numeral text: show 0% at idle, current pct during scanning, 100% at done
  const numeralStr = `${Math.round(pct)}%`;

  // Color states:
  const onRed = state === "idle" || (state === "scanning" && pct < 50);

  return (
    <div style={{
      position: "relative", width: "100vw", height: "100vh",
      overflow: "hidden", background: "var(--white-pure)",
    }}>
      {/* Red flood */}
      <div style={{
        position: "absolute", inset: 0,
        background: "var(--onboarding-flood)",
      }}/>

      {/* Grain overlay */}
      <svg style={{ position: "absolute", inset: 0, mixBlendMode: "overlay", opacity: 0.45, pointerEvents: "none" }} width="100%" height="100%">
        <defs>
          <filter id="ob-grain">
            <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" seed="3"/>
            <feColorMatrix values="0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.06 0"/>
          </filter>
        </defs>
        <rect width="100%" height="100%" filter="url(#ob-grain)"/>
      </svg>

      {/* White reveal — clip-path tracks pct. Transition only on done settle. */}
      <div style={{
        position: "absolute", inset: 0,
        background: "var(--white-pure)",
        clipPath: `polygon(0 0, ${pct}% 0, ${pct}% 100%, 0 100%)`,
        transition: state === "done" ? "clip-path 600ms cubic-bezier(0.16,1,0.3,1)" : "none",
      }}/>

      {/* Vapor wisp at boundary while scanning */}
      {state === "scanning" && pct > 1 && pct < 100 && (
        <div style={{
          position: "absolute", top: 0, bottom: 0,
          left: `calc(${pct}% - 80px)`, width: 160,
          background: "radial-gradient(ellipse at right, rgba(255,255,255,0.85) 0%, rgba(255,255,255,0) 70%)",
          pointerEvents: "none",
        }}/>
      )}

      {/* Boundary hairline */}
      {state === "scanning" && (
        <div style={{
          position: "absolute", top: "12%", bottom: "12%",
          left: `${pct}%`, width: 1,
          background: pct < 50 ? "rgba(10,22,40,0.10)" : "rgba(10,22,40,0.06)",
        }}/>
      )}

      {/* Numeral — white version, full bleed (visible on red side) */}
      <div style={{
        position: "absolute", inset: 0,
        display: "flex", alignItems: "center", justifyContent: "center",
        pointerEvents: "none",
      }}>
        <div className="serif" style={{
          fontSize: "min(26vw, 340px)", fontWeight: 600, letterSpacing: "-0.04em",
          lineHeight: 1, color: "#FFFFFF",
        }}>{numeralStr}</div>
      </div>

      {/* Numeral — midnight version, clipped to white side */}
      <div style={{
        position: "absolute", inset: 0,
        display: "flex", alignItems: "center", justifyContent: "center",
        pointerEvents: "none",
        clipPath: `polygon(0 0, ${pct}% 0, ${pct}% 100%, 0 100%)`,
        transition: state === "done" ? "clip-path 600ms cubic-bezier(0.16,1,0.3,1)" : "none",
      }}>
        <div className="serif" style={{
          fontSize: "min(26vw, 340px)", fontWeight: 600, letterSpacing: "-0.04em",
          lineHeight: 1, color: "var(--midnight)",
        }}>{numeralStr}</div>
      </div>

      {/* Sub-label */}
      <div style={{
        position: "absolute", left: 0, right: 0,
        top: "calc(50% + min(16vw, 220px))",
        textAlign: "center", pointerEvents: "none",
      }}>
        <div className="serif" style={{
          fontSize: state === "done" ? 30 : 22,
          fontWeight: state === "done" ? 600 : 500,
          color: state === "done"
            ? "var(--midnight)"
            : (onRed ? "rgba(255,255,255,0.92)" : "var(--midnight-soft)"),
          letterSpacing: "-0.01em",
        }}>
          {state === "idle"
            ? "Ready when you are."
            : state === "scanning"
            ? "Scanning your communication history."
            : "Compliance scan complete."}
        </div>
      </div>

      {/* Mascot — hidden at idle (no angel until scanning pushes the red) */}
      {state !== "idle" && (
        <div style={{
          position: "absolute", top: mascotTop, left: mascotLeft,
          transform: mascotTransform,
          filter: "drop-shadow(0 14px 24px rgba(10,22,40,0.18))",
          transition: mascotTransition,
          zIndex: 5,
        }}>
          <div style={{ animation: mascotAnim }}>
            <AngelRobot size={mascotSize} view={mascotView}/>
          </div>
        </div>
      )}

      {/* Idle CTA */}
      {state === "idle" && (
        <div style={{
          position: "absolute", left: 0, right: 0,
          top: "calc(50% + min(22vw, 300px))",
          display: "flex", justifyContent: "center",
        }}>
          <button onClick={startScan} className="neu-btn-redglow neu-btn-redglow-lg">
            <span>Begin scan</span>
            <span style={{ opacity: 0.85 }}>→</span>
          </button>
        </div>
      )}

      {/* Done CTA */}
      {state === "done" && (
        <div style={{
          position: "absolute", left: 0, right: 0,
          top: "calc(50% + min(24vw, 320px))",
          display: "flex", justifyContent: "center",
        }}>
          <button onClick={() => navigate("/dashboard")} className="neu-btn neu-btn-primary" style={{
            padding: "16px 26px", fontSize: 14,
            display: "inline-flex", alignItems: "center", gap: 10,
          }}>
            <span>See your compliance score</span>
            <span>→</span>
          </button>
        </div>
      )}

      {/* Wordmark */}
      <a href="/landing" data-link style={{
        position: "absolute", top: 28, left: 36,
        display: "flex", alignItems: "center", gap: 10,
        zIndex: 10, textDecoration: "none", color: "inherit",
      }}>
        <span style={{
          width: 10, height: 10, borderRadius: 999,
          background: onRed ? "#FFFFFF" : "var(--red-core)",
          boxShadow: onRed ? "0 0 0 4px rgba(255,255,255,0.2)" : "0 0 0 4px rgba(230,57,70,0.18)",
        }}/>
        <span className="micro" style={{ color: onRed ? "rgba(255,255,255,0.9)" : "var(--midnight)" }}>RedGone</span>
      </a>

      {/* Counter */}
      <div className="mono" style={{
        position: "absolute", top: 28, right: 36,
        color: onRed ? "rgba(255,255,255,0.9)" : "var(--midnight-soft)",
        fontSize: 12, letterSpacing: "0.06em", zIndex: 10,
      }}>
        {state === "idle"
          ? "READY"
          : state === "scanning"
          ? `SCAN · ${Math.round(pct).toString().padStart(3, "0")}%`
          : "SCAN · COMPLETE"}
      </div>

      {/* Skip */}
      {state !== "done" && (
        <a href="/dashboard" data-link className="neu-chip" style={{
          position: "absolute", bottom: 24, left: 24,
          fontSize: 11, fontWeight: 600, letterSpacing: "0.08em",
          textTransform: "uppercase", textDecoration: "none", color: "inherit",
          zIndex: 10,
        }}>Skip →</a>
      )}

      {/* Replay (done) */}
      {state === "done" && (
        <button onClick={reset} className="neu-chip" style={{
          position: "absolute", bottom: 24, right: 24,
          fontSize: 11, fontWeight: 600, letterSpacing: "0.08em",
          textTransform: "uppercase", zIndex: 10,
        }}>Replay</button>
      )}
    </div>
  );
};

window.OnboardingHero = OnboardingHero;
