// Shared components: Header, Footer, ProductCard, etc.
const { useEffect: useEffectC, useRef: useRefC, useState: useStateC, useContext: useContextC, createContext: createContextC } = React;

// Cart context
const CartContext = createContextC(null);

function CartProvider({ children }) {
  const [items, setItems] = useStateC(() => {
    try { return JSON.parse(localStorage.getItem("cc_cart") || "[]"); } catch { return []; }
  });
  useEffectC(() => {
    localStorage.setItem("cc_cart", JSON.stringify(items));
  }, [items]);

  const add = (productId, qty = 1, v = 0) => {
    setItems(prev => {
      const existing = prev.find(i => i.id === productId && (i.v || 0) === v);
      if (existing) return prev.map(i => (i.id === productId && (i.v || 0) === v) ? { ...i, qty: i.qty + qty } : i);
      return [...prev, { id: productId, v, qty }];
    });
  };
  const remove = (id, v = 0) => setItems(prev => prev.filter(i => !(i.id === id && (i.v || 0) === v)));
  const setQty = (id, v, qty) => setItems(prev => prev.map(i => (i.id === id && (i.v || 0) === v) ? { ...i, qty: Math.max(1, qty) } : i));
  const clear = () => setItems([]);
  const count = items.reduce((s, i) => s + i.qty, 0);
  const subtotal = items.reduce((s, i) => {
    const p = window.PRODUCTS.find(p => p.id === i.id);
    const variant = p && p.variants[i.v || 0];
    return s + (variant ? variant.p * i.qty : 0);
  }, 0);

  return <CartContext.Provider value={{ items, add, remove, setQty, clear, count, subtotal }}>{children}</CartContext.Provider>;
}

function useCart() { return useContextC(CartContext); }

// Router (real URLs via History API). Every route is a real prerendered
// page on disk, so a cold load at /product/bpc-157 serves real HTML and
// only then hands off to React — crawlers never depend on JS running.
function useRoute() {
  const [route, setRoute] = useStateC(() => parseRoute(location.pathname));
  useEffectC(() => {
    const onPop = () => setRoute(parseRoute(location.pathname));
    window.addEventListener("popstate", onPop);
    window.addEventListener("ccr:navigate", onPop);
    return () => {
      window.removeEventListener("popstate", onPop);
      window.removeEventListener("ccr:navigate", onPop);
    };
  }, []);
  const first = useRefC(true);
  useEffectC(() => {
    // Don't scroll on the initial mount — a deep link should land where the
    // browser put it (and prerendered content is already in place).
    if (first.current) { first.current = false; return; }
    window.scrollTo(0, 0);
  }, [route.path, route.id]);
  return route;
}

// "/shop/weight-loss" -> { path: "shop", id: "weight-loss" }
function parseRoute(pathname) {
  const clean = (pathname || "/").replace(/^\/+|\/+$/g, "");
  if (!clean) return { path: "home", id: null };
  const [path, ...rest] = clean.split("/");
  return { path, id: rest[0] ? decodeURIComponent(rest[0]) : null };
}

// Build an href for a logical route. Single source of truth so links and
// the prerenderer can never drift apart.
function hrefFor(path, id) {
  if (path === "home") return "/";
  if (path === "shop" && id) return `/shop/${window.CAT_SLUG(id)}`;
  return id ? `/${path}/${id}` : `/${path}`;
}

function navigate(path) {
  const url = path.startsWith("/") ? path : "/" + path;
  if (url === location.pathname) return;
  history.pushState({}, "", url);
  window.dispatchEvent(new Event("ccr:navigate"));
}

// Intercept same-origin link clicks once, globally, so every plain <a href>
// in the markup does a client-side transition. Links stay real anchors —
// crawlable, middle-clickable, and copyable — with no per-link onClick.
if (typeof document !== "undefined" && !window.__ccrLinkHandler) {
  window.__ccrLinkHandler = true;
  document.addEventListener("click", (e) => {
    if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
    const a = e.target.closest && e.target.closest("a");
    if (!a) return;
    const href = a.getAttribute("href");
    if (!href || !href.startsWith("/")) return;          // external, mailto, or #
    if (a.target && a.target !== "_self") return;
    if (a.hasAttribute("download")) return;
    e.preventDefault();
    navigate(href);
  });
}

// Promo ticker
function Ticker({ items }) {
  const text = items.join("      •      ");
  return (
    <div className="ticker">
      <div className="ticker-track">
        <span>{text}</span><span>{text}</span><span>{text}</span>
      </div>
    </div>
  );
}

function Header() {
  const { count } = useCart();
  const route = useRoute();
  return (
    <header className="site-header-wrap">
      <div className="utility-bar">
        <div className="utility-inner">
          <span><strong>Research use only.</strong> Not for human consumption.</span>
          <span className="utility-links">
            <a href="/newsletter">Newsletter</a>
            <a href={`mailto:${window.ORDER_INFO.email}`}>Contact</a>
          </span>
        </div>
      </div>
      <div className="site-header">
        <div className="header-inner">
          <a className="brand" href="/">
            <img className="brand-badge" src={(window.__resources && window.__resources.ccrBadge) || "/assets/ccr-badge.png"} alt="Clown Catcher Research emblem" />
            <span className="brand-text">
              <span className="brand-mark">Clown <span className="accent">Catcher</span></span>
              <span className="brand-llc">RESEARCH</span>
            </span>
          </a>
          <nav className="nav">
            <a href="/" className={route.path === "home" ? "active" : ""}>Home</a>
            <a href="/shop" className={route.path === "shop" || route.path === "product" ? "active" : ""}>Shop All</a>
            <div className="nav-drop">
              <a href="/shop" className="nav-drop-trigger" onClick={(e) => e.preventDefault()}>Categories <span className="caret">▾</span></a>
              <div className="nav-drop-menu">
                {window.CATEGORIES.filter(c => c !== "All").map(c => (
                  <a key={c} href={`/shop/${window.CAT_SLUG(c)}`}>{c}</a>
                ))}
              </div>
            </div>
            <a href="/newsletter" className={route.path === "newsletter" ? "active" : ""}>Newsletter</a>
          </nav>
          <div className="header-right">
            <span className="status-dot"></span><span className="status-text">Shipping daily</span>
            <a href="/cart" className="cart-btn">
              <span>Cart</span>
              <span className="cart-count">{count}</span>
            </a>
          </div>
        </div>
      </div>
      <Ticker items={[
        "Free shipping on orders over $300",
        "$20 flat-rate shipping",
        "Order by cart — payment options sent by email",
        "Fast, discreet shipping",
        "Join the weekly newsletter for updates",
        "Price list updated " + window.ORDER_INFO.updated,
      ]} />
    </header>
  );
}

function Footer() {
  return (
    <footer className="site-footer">
      <div className="foot-grid">
        <div className="foot-brand">
          <div className="foot-mark-row">
            <img className="foot-badge" src={(window.__resources && window.__resources.ccrBadge) || "/assets/ccr-badge.png"} alt="Clown Catcher Research emblem" />
            <div className="foot-mark">Clown<span className="accent">Catcher</span></div>
          </div>
          <p className="foot-tag">Premium research peptides for the scientific community.</p>
          <div className="foot-disclaimer">
            <strong>For laboratory research use only.</strong> Products on this site are sold for in-vitro and laboratory research purposes only. Not intended for human or animal consumption. By purchasing, you certify you are a qualified research professional.
          </div>
        </div>
        <div>
          <h4>Shop</h4>
          <a href="/shop">All Peptides</a>
          <a href="/shop">Recovery</a>
          <a href="/shop">GH Class</a>
          <a href="/shop">Performance</a>
          <a href="/shop">Cognitive</a>
        </div>
        <div>
          <h4>Newsletter</h4>
          <a href="/newsletter">Subscribe for weekly updates</a>
        </div>
        <div>
          <h4>Ordering</h4>
          <a href={`mailto:${window.ORDER_INFO.email}`}>{window.ORDER_INFO.email}</a>
          <a href="/shop">Shipping: $20 · free over $300</a>
          <a href="/shop">Payment options sent by email</a>
        </div>
      </div>
      <div className="foot-base">
        <span>© {new Date().getFullYear()} Clown Catcher Research. All rights reserved.</span>
        <span>All products are for research use only. Not for human consumption.</span>
      </div>
    </footer>
  );
}

// Fly-to-cart animation: clones the product's vial and arcs it into the
// header cart button, then bounces the button. sourceEl is any element
// containing (or being) a .photo-vial; falls back to a plain bump.
function flyToCart(sourceEl) {
  const cartBtn = document.querySelector(".cart-btn");
  if (!cartBtn) return;
  const bump = () => {
    cartBtn.classList.remove("cart-bump");
    void cartBtn.offsetWidth; // restart the animation on rapid re-adds
    cartBtn.classList.add("cart-bump");
  };
  const vial = sourceEl && (sourceEl.classList && sourceEl.classList.contains("photo-vial")
    ? sourceEl
    : sourceEl.querySelector && sourceEl.querySelector(".photo-vial"));
  const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  if (!vial || reduced || typeof vial.animate !== "function") { bump(); return; }

  const from = vial.getBoundingClientRect();
  const to = cartBtn.getBoundingClientRect();
  const holder = document.createElement("div");
  const arc = document.createElement("div");
  holder.className = "fly-to-cart";
  holder.style.left = from.left + "px";
  holder.style.top = from.top + "px";
  holder.style.width = from.width + "px";
  holder.style.height = from.height + "px";
  arc.appendChild(vial.cloneNode(true));
  holder.appendChild(arc);
  document.body.appendChild(holder);

  const dx = (to.left + to.width / 2) - (from.left + from.width / 2);
  const dy = (to.top + to.height / 2) - (from.top + from.height / 2);
  const dur = 650;
  // X starts slow and accelerates, Y shoots up and settles — together they
  // trace an arc from the card up into the cart.
  holder.animate(
    [{ transform: "translateX(0)" }, { transform: `translateX(${dx}px)` }],
    { duration: dur, easing: "cubic-bezier(0.55, 0, 0.85, 0.5)", fill: "forwards" }
  );
  const flight = arc.animate(
    [
      { transform: "translateY(0) scale(1) rotate(0deg)", opacity: 1 },
      { transform: `translateY(${dy}px) scale(0.08) rotate(14deg)`, opacity: 0.85 },
    ],
    { duration: dur, easing: "cubic-bezier(0.2, 0.9, 0.3, 1)", fill: "forwards" }
  );
  flight.onfinish = () => { holder.remove(); bump(); };
  // Safety net: never leave a ghost behind if onfinish doesn't fire.
  setTimeout(() => { if (holder.parentNode) { holder.remove(); bump(); } }, dur + 200);
}

// Product card — clinical light style
function ProductCard({ p, large = false }) {
  const { add } = useCart();
  return (
    <article className={`product-card ${large ? "large" : ""}`}>
      <div className="card-photo">
        <PhotoVial name={p.name} mass={p.dose} width={large ? 118 : 96} />
        <div className="card-tag">{p.category}</div>
        <div className="card-purity">{p.form}</div>
      </div>
      <div className="card-info">
        {/* Real anchor, stretched over the whole card via CSS — crawlable and
            middle-clickable, where the old onClick handler was neither. */}
        <a className="card-name card-link" href={`/product/${p.id}`}>{p.name}</a>
        <div className="card-sub">{p.subtitle} · {p.mass}</div>
      </div>
      <div className="card-foot">
        <div className="card-price">{p.variants.length > 1 && <span className="from-note">from </span>}<span className="dollar">$</span>{p.price}<span className="unit-note"> / {window.UNIT_WORD(p.form)}</span></div>
        <button className="add-btn" onClick={(e) => { e.preventDefault(); e.stopPropagation(); add(p.id); flyToCart(e.currentTarget.closest(".product-card")); }}>
          <span>Add to Cart</span>
        </button>
      </div>
    </article>
  );
}

// Reveal-on-scroll wrapper
function Reveal({ children, delay = 0, className = "" }) {
  const ref = useRefC(null);
  const [vis, setVis] = useStateC(false);
  useEffectC(() => {
    // Show by default; observer just upgrades to animated reveal when entering view.
    const el = ref.current;
    if (!el) { setVis(true); return; }
    // If already on screen at mount, show immediately.
    const rect = el.getBoundingClientRect();
    if (rect.top < window.innerHeight && rect.bottom > 0) {
      requestAnimationFrame(() => setVis(true));
    }
    const obs = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) setVis(true); });
    }, { threshold: 0, rootMargin: "0px 0px -10% 0px" });
    obs.observe(el);
    // Safety fallback — if observer never fires (e.g. fixed-overlay quirks), reveal after a beat.
    const fallback = setTimeout(() => setVis(true), 1200);
    return () => { obs.disconnect(); clearTimeout(fallback); };
  }, []);
  return <div ref={ref} className={`reveal ${vis ? "in" : ""} ${className}`} style={{ transitionDelay: `${delay}ms` }}>{children}</div>;
}

// Age gate — 21+ compliance modal. Persists acknowledgment in localStorage.
function AgeGate() {
  const [state, setState] = useStateC(() => {
    try { return localStorage.getItem("cc_age_verified") === "1" ? "passed" : "ask"; } catch { return "ask"; }
  });
  if (state === "passed") return null;
  const confirm = () => {
    try { localStorage.setItem("cc_age_verified", "1"); } catch {}
    setState("passed");
  };
  return (
    <div className="age-gate" data-screen-label="Age verification">
      <div className="age-card">
        <img className="age-logo" src={(window.__resources && window.__resources.ccrLogoFull) || "/assets/ccr-logo-full.jpg"} alt="Clown Catcher Research" />
        {state === "ask" ? (
          <>
            <h2>Are you 21 or older?</h2>
            <p>This site sells research compounds intended strictly for laboratory use. You must be at least 21 years of age and a qualified research professional to enter.</p>
            <div className="age-actions">
              <button className="btn btn-primary age-yes" onClick={confirm}>I am 21 or older — Enter</button>
              <button className="btn btn-ghost age-no" onClick={() => setState("blocked")}>I am under 21</button>
            </div>
            <div className="age-fine">By entering, you certify you are 21+ and agree that all products are for research use only — not for human or animal consumption.</div>
          </>
        ) : (
          <>
            <h2>Access restricted</h2>
            <p>You must be 21 or older to access this site. We are unable to sell to anyone under the age of 21.</p>
            <div className="age-actions">
              <button className="btn btn-ghost" onClick={() => setState("ask")}>Go back</button>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { CartProvider, useCart, useRoute, navigate, Header, Footer, ProductCard, Ticker, Reveal, AgeGate, flyToCart });
