/* global React */
// Mereke landing — shared hooks & small helpers
const { useState, useEffect, useRef, useCallback } = React;

/* ---- Reliable scroll-position reveal engine ----------------------
   IntersectionObserver is unreliable inside some preview iframes, so
   we use a single rAF-throttled scroll/resize checker reading
   getBoundingClientRect (which always works). Elements register a
   callback fired once when their top crosses ~88% of the viewport. */
const __revealSet = new Set();
let __revealQueued = false;
function __checkReveals() {
  __revealQueued = false;
  const vh = window.innerHeight || document.documentElement.clientHeight;
  __revealSet.forEach((entry) => {
    const r = entry.el.getBoundingClientRect();
    if (r.top < vh * 0.9 && r.bottom > 0) {
      entry.cb();
      __revealSet.delete(entry);
    }
  });
}
function __queueReveal() {
  if (__revealQueued) return;
  __revealQueued = true;
  setTimeout(__checkReveals, 40);
}
function __registerReveal(el, cb) {
  const entry = { el, cb };
  __revealSet.add(entry);
  __queueReveal();
  return () => __revealSet.delete(entry);
}
if (typeof window !== "undefined" && !window.__revealBound) {
  window.__revealBound = true;
  window.addEventListener("scroll", __queueReveal, { passive: true });
  window.addEventListener("resize", __queueReveal);
  window.addEventListener("load", __queueReveal);
  // safety sweep in case scroll events are coalesced
  setInterval(__checkReveals, 350);
}

/* Scroll-reveal: adds .in when element enters viewport, then locks to
   the final state so content is guaranteed visible even if the iframe's
   transition timeline is throttled (background tabs / preview frames). */
function Reveal({ children, className = "", delay = 0, tag = "div", style = {}, ...rest }) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  const [locked, setLocked] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    return __registerReveal(el, () => setSeen(true));
  }, []);
  useEffect(() => {
    if (!seen) return;
    const t = setTimeout(() => setLocked(true), 1150);
    return () => clearTimeout(t);
  }, [seen]);
  const Tag = tag;
  const dcls = delay ? ` d${delay}` : "";
  const lockStyle = locked ? { opacity: 1, transform: "none", transition: "none" } : null;
  return React.createElement(Tag, { ref, className: `reveal${dcls} ${seen ? "in" : ""} ${className}`,
    style: lockStyle ? { ...style, ...lockStyle } : style, ...rest }, children);
}

/* Count-up trigger that fires when scrolled into view */
function useInView() {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    return __registerReveal(el, () => setInView(true));
  }, []);
  return [ref, inView];
}

function CountUp({ to, duration = 1800, prefix = "", suffix = "", sep = " " }) {
  const [ref, inView] = useInView();
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!inView) return;
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce) { setVal(to); return; }
    const ease = (t) => 1 - Math.pow(1 - t, 3);
    const start = Date.now();
    const id = setInterval(() => {
      const p = Math.min((Date.now() - start) / duration, 1);
      setVal(Math.round(ease(p) * to));
      if (p >= 1) clearInterval(id);
    }, 33);
    return () => clearInterval(id);
  }, [inView, to, duration]);
  const fmt = (n) => n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, sep);
  return React.createElement("span", { ref }, prefix + fmt(val) + suffix);
}

/* Parallax: translateY a ref based on scroll position (timer-throttled) */
function useParallax(strength = 0.18) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce) return;
    let queued = false;
    const update = () => {
      queued = false;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight;
      const center = r.top + r.height / 2;
      const off = (center - vh / 2) / vh;
      el.style.transform = `translate3d(0, ${(-off * strength * 100).toFixed(2)}px, 0)`;
    };
    const onScroll = () => { if (!queued) { queued = true; setTimeout(update, 16); } };
    update();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => { window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); };
  }, [strength]);
  return ref;
}

const Spark = ({ className = "", style = {} }) =>
  React.createElement("span", { className: `mk-spark ${className}`, "aria-hidden": "true", style });

const Eyebrow = ({ children, onRed = false }) =>
  React.createElement("span", { className: `lp-eyebrow ${onRed ? "on-red" : ""}` },
    React.createElement(Spark), children);

const A = "assets"; // asset base

/* ---- Event bus for modals ---------------------------------------- */
function openLead() { window.dispatchEvent(new CustomEvent("mereke:lead")); }
function openProduct(p) { window.dispatchEvent(new CustomEvent("mereke:product", { detail: p })); }
function useBus(name, handler) {
  useEffect(() => {
    const fn = (e) => handler(e.detail);
    window.addEventListener(name, fn);
    return () => window.removeEventListener(name, fn);
  }, [name, handler]);
}

/* ---- Premium CTA button ------------------------------------------ */
function CTA({ children, variant = "amber", size = "", onClick, href, lead = false, style = {} }) {
  const cls = `lp-btn lp-btn-${variant}${size ? " lp-btn-" + size : ""}`;
  const handle = (e) => { if (lead) { e.preventDefault(); openLead(); } if (onClick) onClick(e); };
  if (href && !lead) return React.createElement("a", { href, className: cls, style, onClick: handle }, children);
  return React.createElement(href ? "a" : "button", { href: href || undefined, className: cls, style, onClick: handle, type: href ? undefined : "button" }, children);
}

/* ---- Ethnic texture layer (recolorable, optional parallax) -------- */
function Ethno({ color = "var(--ink-900)", variant = "", parallax = 0, style = {} }) {
  const ref = useRef(null);
  useEffect(() => {
    if (!parallax) return;
    const el = ref.current; if (!el) return;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    let queued = false;
    const update = () => { queued = false; const r = el.parentElement.getBoundingClientRect(); const vh = window.innerHeight;
      const off = (r.top + r.height / 2 - vh / 2) / vh; el.style.transform = `translate3d(0, ${(-off * parallax * 100).toFixed(1)}px, 0)`; };
    const onS = () => { if (!queued) { queued = true; setTimeout(update, 16); } };
    update(); window.addEventListener("scroll", onS, { passive: true }); window.addEventListener("resize", onS);
    return () => { window.removeEventListener("scroll", onS); window.removeEventListener("resize", onS); };
  }, [parallax]);
  return React.createElement("div", { ref, "aria-hidden": "true", className: `lp-ethno ${variant}`, style: { color, ...style } });
}

/* ---- Ethnic divider ---------------------------------------------- */
const DividerMark = ({ style = {} }) => React.createElement("div", { className: "lp-divider-mark", style },
  React.createElement("span", { className: "ln" }),
  React.createElement("span", { className: "curl flip" }),
  React.createElement(Spark, { style: { width: 15, height: 15 } }),
  React.createElement("span", { className: "curl" }),
  React.createElement("span", { className: "ln" }));

/* ---- Countdown to a date ----------------------------------------- */
function daysUntil(dateStr) {
  const t = new Date(dateStr).getTime();
  const now = Date.now();
  const d = Math.max(0, Math.ceil((t - now) / 86400000));
  return d;
}

Object.assign(window, { Reveal, useInView, CountUp, useParallax, Spark, Eyebrow, A, openLead, openProduct, useBus, CTA, Ethno, DividerMark, daysUntil });
