/* Common utilities + helpers — shared by all sections. */

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

// Easing
const easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);

// Hook: animate a number from start to end, triggered by `active`
function useCountUp(target, { duration = 1500, start = 0, active = true } = {}) {
  const [value, setValue] = useState(active ? start : target);
  useEffect(() => {
    if (!active) return;
    let raf, started;
    const step = (ts) => {
      if (!started) started = ts;
      const t = Math.min(1, (ts - started) / duration);
      setValue(start + (target - start) * easeOutCubic(t));
      if (t < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [target, active, duration, start]);
  return value;
}

// Hook: detect when an element enters the viewport (once)
function useInView(opts = { threshold: 0.2, once: true }) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setInView(true);
          if (opts.once) obs.disconnect();
        } else if (!opts.once) {
          setInView(false);
        }
      },
      { threshold: opts.threshold ?? 0.2 }
    );
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, inView];
}

// Format helpers
const fmtMoney = (n) => {
  if (n >= 1e6) return "$" + (n / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
  if (n >= 1e3) return "$" + (n / 1e3).toFixed(0) + "K";
  return "$" + Math.round(n).toLocaleString();
};
const fmtInt = (n) => Math.round(n).toLocaleString();
const fmtPct = (n) => Math.round(n) + "%";
const fmtMin = (n) => n.toFixed(1) + " min";

// ===== Section wrapper — label above, right-justified title =====
function Section({ id, num, title, kicker, children }) {
  return (
    <section className="section" id={id}>
      <div className="wrap">
        <div className="sec-head">
          <div className="sec-head__num">
            <span>{num}</span>
            {kicker && <span style={{marginLeft:14, color:"var(--ss-blue)"}}>{kicker}</span>}
          </div>
          <h2 className="sec-head__title">{title}</h2>
        </div>
        {children}
      </div>
    </section>
  );
}

// ===== Sticky nav =====
function Nav({ active, onJump }) {
  const items = [
    ["challenge", "[01] CHALLENGE"],
    ["solution", "[02] SOLUTION"],
    ["results", "[03] RESULTS"],
    ["trust", "[04] TRUST"],
  ];
  return (
    <nav className="nav">
      <div className="nav__brand">
        <img src="assets/superscript-logo.svg" alt="Superscript" className="nav__logo" />
        <span style={{color:"var(--ss-grey-3)"}}>/ CASE STUDY</span>
      </div>
      <div className="nav__crumbs">
        {items.map(([id, label]) => (
          <button key={id} className={"nav__crumb " + (active === id ? "is-active" : "")}
                  onClick={() => onJump(id)}>
            <span className="dot"></span><span className="nav__crumb-label">{label}</span>
          </button>
        ))}
      </div>
      <div className="nav__meta">
        <span>CLIENT / <b>FOOTHILLS NEUROLOGY</b></span>
      </div>
    </nav>
  );
}

// ===== Animated number that triggers when in view =====
function CountStat({ to, from = 0, prefix = "", suffix = "", duration = 1500, decimals = 0 }) {
  const [ref, inView] = useInView();
  const v = useCountUp(to, { start: from, duration, active: inView });
  const display = decimals > 0 ? v.toFixed(decimals) : Math.round(v).toLocaleString();
  return <span ref={ref}>{prefix}{display}{suffix}</span>;
}

Object.assign(window, {
  useState, useEffect, useRef, useMemo, useCallback,
  useCountUp, useInView,
  fmtMoney, fmtInt, fmtPct, fmtMin,
  Section, Nav, CountStat,
});
