/* global React */
const { useState, useEffect, useRef, useCallback } = React;

/* ---------------- Scroll reveal manager ----------------
   IntersectionObserver is unreliable inside some preview iframes, so we drive
   reveals from a throttled scroll/resize check on getBoundingClientRect. */
const revealManager = (() => {
  const items = new Set();
  let last = 0;
  const check = () => {
    const h = window.innerHeight || document.documentElement.clientHeight;
    items.forEach((it) => {
      const r = it.el.getBoundingClientRect();
      if (r.top < h * 0.9) { it.cb(); items.delete(it); }
    });
  };
  const onScroll = () => {
    const now = Date.now();
    if (now - last < 60) return;
    last = now;
    check();
  };
  if (typeof window !== "undefined") {
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", check);
    window.addEventListener("load", check);
    // Safety net: if scroll/rAF are throttled (e.g. offscreen iframe), make sure
    // nothing stays permanently hidden.
    setTimeout(check, 400);
    setTimeout(() => { items.forEach((it) => it.cb()); items.clear(); }, 2600);
  }
  return {
    add(el, cb) { const it = { el, cb }; items.add(it); setTimeout(check, 0); return () => items.delete(it); },
  };
})();

function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    return revealManager.add(el, () => el.classList.add("in"));
  }, []);
  return ref;
}

function Reveal({ children, delay, as = "div", className = "", ...rest }) {
  const ref = useReveal();
  const Tag = as;
  const d = delay ? ` d${delay}` : "";
  return <Tag ref={ref} className={`reveal${d} ${className}`} {...rest}>{children}</Tag>;
}

/* ---------------- Cinematic placeholder ---------------- */
/* A styled "footage" frame: atmospheric gradient scene + grain + vignette + drop label.
   Swap for real <img>/<video> later by replacing the .shot__scene. */
function Shot({ scene = "scene-ocean", label = "drop footage", code, ratio, className = "", style = {}, children, dim = false, src, video, poster, pos = "center" }) {
  const s = { ...style };
  if (ratio) s.aspectRatio = ratio;
  const media = video
    ? <video className="shot__img" src={video} poster={poster} autoPlay muted loop playsInline
        ref={(el) => { if (el) el.play().catch(() => {}); }}
        style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", objectPosition: pos, zIndex: 0 }} />
    : src
      ? <img className="shot__img" src={src} alt={label} style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", objectPosition: pos, zIndex: 0 }} />
      : <div className={`shot__scene ${scene}`}></div>;
  return (
    <div className={`shot ${className}`} style={s}>
      {media}
      {dim && <div style={{ position: "absolute", inset: 0, zIndex: 1, background: "rgba(0,0,0,0.32)" }}></div>}
      <div className="shot__grain"></div>
      <div className="shot__vignette"></div>
      {code && <div className="shot__corner">{code}</div>}
      {label && <div className="shot__label">{label}</div>}
      {children && <div style={{ position: "relative", zIndex: 5, height: "100%" }}>{children}</div>}
    </div>
  );
}

/* ---------------- Animated counter ---------------- */
function Stat({ value, prefix = "", suffix = "", duration = 1600 }) {
  const [n, setN] = useState(0);
  const ref = useRef(null);
  const done = useRef(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const run = () => {
      if (done.current) return;
      done.current = true;
      const start = performance.now();
      const tick = (now) => {
        const p = Math.min(1, (now - start) / duration);
        const eased = 1 - Math.pow(1 - p, 3);
        setN(value * eased);
        if (p < 1) requestAnimationFrame(tick);
      };
      requestAnimationFrame(tick);
      setTimeout(() => setN(value), duration + 80);
    };
    return revealManager.add(el, run);
  }, [value, duration]);
  const display = Number.isInteger(value) ? Math.round(n).toLocaleString() : n.toFixed(1);
  return <span ref={ref}>{prefix}{display}{suffix}</span>;
}

/* ---------------- Navigation ---------------- */
const NAV_LINKS = [
  ["The Difference", "difference"],
  ["Configure", "build"],
  ["Gallery", "gallery"],
  ["Specs", "specs"],
  ["Custom Builds", "custom"],
  ["Contact", "contact"],
];

function Nav() {
  const [scrolled, setScrolled] = useState(false);
  const [open, setOpen] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  const go = (id) => (e) => {
    e.preventDefault();
    setOpen(false);
    document.getElementById(id)?.scrollIntoView({ behavior: "smooth", block: "start" });
  };
  return (
    <header className={`nav ${scrolled ? "nav--solid" : ""}`}>
      <div className="nav__inner wrap">
        <a href="#top" className="brand" onClick={go("top")}>
          <img className="brand__mark" src="assets/bmd-logo.png" alt="Bromley Marine Designs" />
        </a>
        <nav className={`nav__links ${open ? "open" : ""}`}>
          {NAV_LINKS.map(([label, id]) => (
            <a key={id} href={`#${id}`} onClick={go(id)}>{label}</a>
          ))}
        </nav>
        <div className="nav__actions">
          <a href="#build" onClick={go("build")} className="btn btn-primary nav__cta">Configure<span className="arr">→</span></a>
          <button className={`nav__burger ${open ? "open" : ""}`} onClick={() => setOpen((o) => !o)} aria-label="Menu">
            <span></span><span></span>
          </button>
        </div>
      </div>
    </header>
  );
}

Object.assign(window, { Reveal, Shot, Stat, Nav, useReveal });
