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

/* =================================================
   Smooth scroll via Lenis (loaded from CDN)
================================================= */
function useLenis(enabled = true) {
  useEffect(() => {
    if (!enabled) return;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    if (!window.Lenis) return;
    const lenis = new window.Lenis({
      duration: 1.2,
      easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
      smoothWheel: true,
      wheelMultiplier: 1.0,
    });
    let raf;
    function loop(t) {
      lenis.raf(t);
      raf = requestAnimationFrame(loop);
    }
    raf = requestAnimationFrame(loop);
    window.__lenis = lenis;
    return () => {
      cancelAnimationFrame(raf);
      lenis.destroy();
      window.__lenis = null;
    };
  }, [enabled]);
}

/* =================================================
   Custom cursor with hover-label
================================================= */
function Cursor() {
  const ref = useRef(null);
  const labelRef = useRef(null);
  const [label, setLabel] = useState("");
  const pos = useRef({ x: -100, y: -100, tx: -100, ty: -100 });

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onMove = (e) => {
      pos.current.tx = e.clientX;
      pos.current.ty = e.clientY;
    };
    const onOver = (e) => {
      const t = e.target.closest("[data-cursor]");
      if (t) {
        setLabel(t.getAttribute("data-cursor"));
        el.classList.add("is-hover");
      } else {
        setLabel("");
        el.classList.remove("is-hover");
      }
    };
    let raf;
    const tick = () => {
      pos.current.x += (pos.current.tx - pos.current.x) * 0.22;
      pos.current.y += (pos.current.ty - pos.current.y) * 0.22;
      el.style.transform = `translate(${pos.current.x}px, ${pos.current.y}px) translate(-50%, -50%)`;
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseover", onOver);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseover", onOver);
    };
  }, []);

  return (
    <div ref={ref} className="cursor" aria-hidden="true">
      <div className="cursor-dot"></div>
      <div className="cursor-label" ref={labelRef}>{label}</div>
    </div>
  );
}

/* =================================================
   Magnetic button — pulls toward cursor in ~80px radius
================================================= */
function MagneticButton({ children, className = "", radius = 80, strength = 0.32, ...rest }) {
  const ref = useRef(null);
  const innerRef = useRef(null);

  useEffect(() => {
    const wrap = ref.current;
    const inner = innerRef.current;
    if (!wrap || !inner) return;
    if (window.matchMedia("(hover: none)").matches) return;

    const onMove = (e) => {
      const r = wrap.getBoundingClientRect();
      const cx = r.left + r.width / 2;
      const cy = r.top + r.height / 2;
      const dx = e.clientX - cx;
      const dy = e.clientY - cy;
      const dist = Math.hypot(dx, dy);
      if (dist < radius + Math.max(r.width, r.height) / 2) {
        inner.style.transform = `translate(${dx * strength}px, ${dy * strength}px)`;
      } else {
        inner.style.transform = "translate(0,0)";
      }
    };
    const onLeave = () => {
      inner.style.transition = "transform 600ms cubic-bezier(0.16, 1, 0.3, 1)";
      inner.style.transform = "translate(0,0)";
      setTimeout(() => { if (inner) inner.style.transition = ""; }, 620);
    };
    const onEnter = () => {
      inner.style.transition = "";
    };

    window.addEventListener("mousemove", onMove);
    wrap.addEventListener("mouseenter", onEnter);
    wrap.addEventListener("mouseleave", onLeave);
    return () => {
      window.removeEventListener("mousemove", onMove);
      wrap.removeEventListener("mouseenter", onEnter);
      wrap.removeEventListener("mouseleave", onLeave);
    };
  }, [radius, strength]);

  return (
    <button ref={ref} className={`magnetic ${className}`} {...rest}>
      <span ref={innerRef} className="magnetic-inner">{children}</span>
    </button>
  );
}

/* =================================================
   Reveal on scroll
   Variants: "fade" (default), "line" (text rises), "img" (scale-from-1.06)
================================================= */
function Reveal({ children, variant = "fade", delay = 0, threshold = 0.18, className = "", as: As = "div", style: extraStyle, ...rest }) {
  const ref = useRef(null);
  // 'hidden' = pre-reveal, 'animate' = transitioning in, 'instant' = no transition (already in viewport at mount, or reduced motion)
  const [mode, setMode] = useState("hidden");

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
      setMode("instant");
      return;
    }

    // If already in viewport at mount, snap to revealed without ever creating
    // a transition — iframe / throttled-rAF environments can freeze in-flight
    // transitions at 0% progress, hiding the element forever.
    const r = el.getBoundingClientRect();
    const vh = window.innerHeight || document.documentElement.clientHeight;
    if (r.top < vh * 0.92 && r.bottom > 0) {
      setMode("instant");
      return;
    }

    const trigger = () => setTimeout(() => setMode("animate"), delay);

    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            trigger();
            io.unobserve(el);
          }
        });
      },
      { threshold, rootMargin: "0px 0px -8% 0px" }
    );
    io.observe(el);

    // Safety: anything still hidden after 1.6s gets instantly revealed
    const safety = setTimeout(() => {
      setMode((m) => (m === "hidden" ? "instant" : m));
    }, 1600);

    return () => {
      io.disconnect();
      clearTimeout(safety);
    };
  }, [delay, threshold]);

  const visible = mode !== "hidden";
  const useTransition = mode === "animate";

  /* variant=line: inline-style transform on inner span. Skips creating a
     transition for elements that were already in-viewport at mount. */
  if (variant === "line") {
    return (
      <As
        ref={ref}
        className={`reveal-line ${className} ${visible ? "is-visible" : ""}`}
        style={{ display: "block", overflow: "hidden", ...extraStyle }}
        {...rest}
      >
        <span
          style={{
            display: "block",
            transform: visible ? "translateY(0)" : "translateY(110%)",
            transition: useTransition ? "transform 800ms cubic-bezier(0.16, 1, 0.3, 1)" : "none",
            transitionDelay: useTransition ? `${delay}ms` : "0ms",
            willChange: "transform",
          }}
        >
          {children}
        </span>
      </As>
    );
  }

  /* variant=fade & img: same protection. Apply opacity/transform inline,
     skipping transitions for above-the-fold elements. */
  if (variant === "img") {
    return (
      <As
        ref={ref}
        className={`reveal-img ${className} ${visible ? "is-visible" : ""}`}
        style={{ overflow: "hidden", ...extraStyle }}
        {...rest}
      >
        <span
          style={{
            display: "block",
            transform: visible ? "scale(1)" : "scale(1.06)",
            opacity: visible ? 1 : 0,
            transition: useTransition ? "transform 900ms cubic-bezier(0.16, 1, 0.3, 1), opacity 900ms cubic-bezier(0.16, 1, 0.3, 1)" : "none",
            transitionDelay: useTransition ? `${delay}ms` : "0ms",
            willChange: "transform, opacity",
          }}
        >
          {children}
        </span>
      </As>
    );
  }

  // variant=fade
  return (
    <As
      ref={ref}
      className={`reveal ${className} ${visible ? "is-visible" : ""}`}
      style={{
        opacity: visible ? 1 : 0,
        transform: visible ? "translateY(0)" : "translateY(40px)",
        transition: useTransition ? "opacity 700ms cubic-bezier(0.16, 1, 0.3, 1), transform 700ms cubic-bezier(0.16, 1, 0.3, 1)" : "none",
        transitionDelay: useTransition ? `${delay}ms` : "0ms",
        willChange: "opacity, transform",
        ...extraStyle,
      }}
      {...rest}
    >
      {children}
    </As>
  );
}

/* Stagger children with a sequential delay */
function RevealGroup({ children, gap = 80, variant = "fade", from = 0, ...rest }) {
  const items = React.Children.toArray(children);
  return (
    <React.Fragment>
      {items.map((c, i) => (
        <Reveal key={i} variant={variant} delay={from + i * gap} {...rest}>{c}</Reveal>
      ))}
    </React.Fragment>
  );
}

/* Multi-line reveal: split a heading into lines, each rising */
function RevealLines({ lines, gap = 80, delay = 0 }) {
  return (
    <span>
      {lines.map((l, i) => (
        <Reveal key={i} variant="line" delay={delay + i * gap} as="span" className="reveal-line">
          {l}
        </Reveal>
      ))}
    </span>
  );
}

/* =================================================
   Header — sticky, knows current route + scrolled state
================================================= */
function Header({ route, onNavigate, dark = false }) {
  const [scrolled, setScrolled] = useState(false);
  const cart = (typeof useStore !== "undefined") ? useStore((s) => s.cart) : [];
  const cartCount = cart.reduce((n, l) => n + l.qty, 0);

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 12);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  const nav = [
    { label: "Shop", route: "plp" },
    { label: "Custom", route: "custom" },
    { label: "Journal", route: "journal" },
    { label: "Atelier", route: "atelier" },
    { label: "Showrooms", route: "showrooms" },
    { label: "Trade", route: "trade" },
  ];

  return (
    <header className={`site-header ${scrolled ? "is-scrolled" : ""} ${dark ? "on-dark" : ""}`}>
      <nav className="nav">
        {nav.map((n) => (
          <a
            key={n.label}
            href="#"
            data-cursor="View"
            className={n.route === route ? "is-active" : ""}
            onClick={(e) => { e.preventDefault(); onNavigate(n.route); }}
          >
            {n.label}
          </a>
        ))}
      </nav>
      <a
        className="brand"
        href="#home"
        data-cursor="Home"
        onClick={(e) => { e.preventDefault(); onNavigate("home"); }}
      >
        Delina Living
      </a>
      <div className="meta">
        <a
          href="#"
          data-cursor="Search"
          onClick={(e) => { e.preventDefault(); Store.setUI({ searchOpen: true }); }}
        >Search</a>
        <a
          href="#"
          data-cursor="Account"
          onClick={(e) => { e.preventDefault(); onNavigate("account"); }}
        >Account</a>
        <a
          href="#"
          data-cursor="Open"
          className="cart-pill"
          onClick={(e) => { e.preventDefault(); Store.setUI({ cartOpen: true }); }}
        >Cart<span className="num">({cartCount})</span></a>
      </div>
    </header>
  );
}

/* =================================================
   Footer
================================================= */
function Footer({ onNavigate }) {
  const go = (r) => (e) => { e.preventDefault(); onNavigate(r); };
  return (
    <footer className="site-footer">
      <div className="footer-top">
        <div>
          <h4>Delina Living · Los Angeles + Vietnam</h4>
          <p className="t-body" style={{ color: "rgba(242,235,224,0.75)", maxWidth: "32ch" }}>
            Investment furniture made the slow way. Designed in Los Angeles, built to order at our atelier in Vietnam. Fifty-year frame warranty, single designer, no exceptions.
          </p>
        </div>
        <div>
          <h4>Shop</h4>
          <ul>
            <li><a data-cursor="View" onClick={go("plp")} href="#">Seating</a></li>
            <li><a data-cursor="View" onClick={go("plp")} href="#">Dining</a></li>
            <li><a data-cursor="View" onClick={go("plp")} href="#">Casegoods</a></li>
            <li><a data-cursor="View" onClick={go("plp")} href="#">Lighting</a></li>
            <li><a data-cursor="View" onClick={go("plp")} href="#">Accessories</a></li>
          </ul>
        </div>
        <div>
          <h4>House</h4>
          <ul>
            <li><a data-cursor="Read" onClick={go("atelier")} href="#">Our Atelier</a></li>
            <li><a data-cursor="Read" onClick={go("atelier")} href="#">The Designer</a></li>
            <li><a data-cursor="View" onClick={go("custom")} href="#">Custom Commissions</a></li>
            <li><a data-cursor="Read" onClick={go("sustainability")} href="#">Materials</a></li>
            <li><a data-cursor="View" onClick={go("trade")} href="#">Trade Program</a></li>
            <li><a data-cursor="View" onClick={go("showrooms")} href="#">Showrooms</a></li>
            <li><a data-cursor="Read" onClick={go("journal")} href="#">Journal</a></li>
          </ul>
        </div>
        <div>
          <h4>Service</h4>
          <ul>
            <li><a data-cursor="Read" onClick={go("help")} href="#">Made-to-Order</a></li>
            <li><a data-cursor="Read" onClick={go("help")} href="#">White-Glove Delivery</a></li>
            <li><a data-cursor="Read" onClick={go("help")} href="#">50-Year Warranty</a></li>
            <li><a data-cursor="Read" onClick={go("help")} href="#">Care &amp; Repair</a></li>
            <li><a data-cursor="Write" onClick={go("contact")} href="#">Contact</a></li>
            <li><a data-cursor="Read" onClick={go("sustainability")} href="#">Sustainability</a></li>
          </ul>
        </div>
      </div>

      <div className="footer-wordmark">Delina Living</div>

      <div className="footer-bottom">
        <div>© 2026 Delina Group, LLC — Los Angeles + Vietnam</div>
        <div style={{ display: "flex", gap: 24 }}>
          <a href="#">Instagram</a>
          <a href="#">Pinterest</a>
          <a href="#">Substack</a>
        </div>
        <div>
          <a onClick={go("help")} href="#">Privacy</a> · <a onClick={go("help")} href="#">Terms</a> · <a onClick={go("help")} href="#">Accessibility</a>
        </div>
      </div>
    </footer>
  );
}

/* =================================================
   Cart Drawer — slides in from right
================================================= */
function CartDrawer({ onCheckout }) {
  const open = useStore((s) => s.ui.cartOpen);
  const cart = useStore((s) => s.cart);
  const subtotal = cart.reduce((n, l) => n + l.price * l.qty, 0);
  const close = () => Store.setUI({ cartOpen: false });

  /* Lock body scroll when open */
  useEffect(() => {
    if (open) document.body.style.overflow = "hidden";
    else document.body.style.overflow = "";
    return () => { document.body.style.overflow = ""; };
  }, [open]);

  /* Esc closes */
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") close(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open]);

  return (
    <React.Fragment>
      <div className={`scrim ${open ? "is-open" : ""}`} onClick={close}></div>
      <aside className={`cart-drawer ${open ? "is-open" : ""}`} aria-hidden={!open}>
        <div className="cart-drawer-head">
          <h3>Your <em>atelier</em> order</h3>
          <button className="close" data-cursor="Close" onClick={close}>Close ×</button>
        </div>

        <div className="cart-drawer-body">
          {cart.length === 0 ? (
            <div className="cart-empty">
              <h4>Empty, for now.</h4>
              <p className="t-body">Browse the catalog — every piece is made to order at our atelier in Vietnam.</p>
              <div style={{ marginTop: 24 }}>
                <button
                  className="btn btn--solid"
                  data-cursor="View"
                  onClick={() => { close(); window.location.hash = "plp"; }}
                >
                  <span>The catalog</span><span className="arrow">→</span>
                </button>
              </div>
            </div>
          ) : (
            cart.map((l, i) => (
              <div className="cart-line" key={i}>
                <div className="thumb" style={{ backgroundImage: `url(${l.img})` }}></div>
                <div>
                  <div className="name">{l.name}</div>
                  <div className="sub">{l.sub}</div>
                  <div className="variant">
                    <span className="dot" style={{ background: l.upholsteryColor || "#A8997E" }}></span>
                    <span>{l.upholstery || "Bone Linen"} · {l.leg || "White Oak"}</span>
                  </div>
                  <div className="price-row">
                    <div className="qty">
                      <button data-cursor="-" onClick={() => Store.updateQty(i, l.qty - 1)}>−</button>
                      <span className="val">{l.qty}</span>
                      <button data-cursor="+" onClick={() => Store.updateQty(i, l.qty + 1)}>+</button>
                    </div>
                    <div className="price">{formatPrice(l.price * l.qty)}</div>
                  </div>
                  <button className="remove" data-cursor="Remove" onClick={() => Store.removeFromCart(i)}>Remove</button>
                </div>
              </div>
            ))
          )}
        </div>

        {cart.length > 0 && (
          <div className="cart-drawer-foot">
            <div className="summary-row"><span className="l">Subtotal</span><span>{formatPrice(subtotal)}</span></div>
            <div className="summary-row"><span className="l">White-glove delivery</span><span>Included</span></div>
            <div className="summary-row total"><span>Total</span><span className="v">{formatPrice(subtotal)}</span></div>
            <button className="btn btn--solid" data-cursor="Checkout" onClick={() => { close(); onCheckout(); }} style={{ justifyContent: "center", marginTop: 8 }}>
              <span>Continue to checkout</span><span className="arrow">→</span>
            </button>
            <p className="t-small" style={{ textAlign: "center", marginTop: 6 }}>
              Eight-week lead time. No charges until your piece enters the workshop.
            </p>
          </div>
        )}
      </aside>
    </React.Fragment>
  );
}

/* =================================================
   Search overlay — full screen, slides down
================================================= */
const SEARCH_INDEX = [
  { name: "Sognefjord", sub: "Three-Seat Sofa", price: 4820, img: "assets/sognefjord-bone.jpg", route: "pdp" },
  { name: "Lysefjord", sub: "Lounge Chair", price: 2640, img: "assets/lysefjord-lounge.jpg", route: "pdp" },
  { name: "Geirangerfjord", sub: "Dining Table", price: 3980, img: "assets/geirangerfjord-table.jpg", route: "pdp" },
  { name: "Hardanger", sub: "Sideboard", price: 5420, img: "assets/hardanger-sideboard.jpg", route: "pdp" },
  { name: "Trollfjord", sub: "Reading Chair", price: 2280, img: "assets/trollfjord-reading.jpg", route: "pdp" },
  { name: "Aurland", sub: "Pendant Lamp", price: 880, img: "assets/aurland-pendant.jpg", route: "pdp" },
];

function SearchOverlay({ onNavigate }) {
  const open = useStore((s) => s.ui.searchOpen);
  const [q, setQ] = useState("");
  const inputRef = useRef(null);
  const close = () => { Store.setUI({ searchOpen: false }); setQ(""); };

  useEffect(() => {
    if (open) document.body.style.overflow = "hidden";
    else document.body.style.overflow = "";
    return () => { document.body.style.overflow = ""; };
  }, [open]);

  useEffect(() => {
    if (open) setTimeout(() => inputRef.current && inputRef.current.focus(), 400);
    const onKey = (e) => { if (e.key === "Escape" && open) close(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open]);

  const lower = q.trim().toLowerCase();
  const results = lower
    ? SEARCH_INDEX.filter((p) => (p.name + " " + p.sub).toLowerCase().includes(lower))
    : SEARCH_INDEX.slice(0, 6);

  const navTo = (route) => { close(); onNavigate(route); };

  return (
    <div className={`search-overlay ${open ? "is-open" : ""}`} aria-hidden={!open}>
      <div className="search-head">
        <div className="t-eyebrow" style={{ color: "var(--ink-mute)" }}>— Search Delina Living</div>
        <button className="close" data-cursor="Close" onClick={close}
                style={{ fontFamily: '"DM Mono", monospace', fontSize: 11, letterSpacing: "0.16em", textTransform: "uppercase" }}>
          Close (esc) ×
        </button>
      </div>
      <div className="search-input-wrap">
        <input
          ref={inputRef}
          type="text"
          placeholder="What are you looking for?"
          value={q}
          onChange={(e) => setQ(e.target.value)}
          data-cursor="Type"
        />
      </div>
      <div className="search-body">
        <div className="search-suggest">
          <h5>{lower ? "Try also" : "Popular categories"}</h5>
          <ul>
            {["Sofas", "Dining tables", "Lounge chairs", "Casegoods", "Lighting", "Made to order"].map((c) => (
              <li key={c}><a href="#" data-cursor="Search" onClick={(e) => { e.preventDefault(); setQ(c); }}>{c}</a></li>
            ))}
          </ul>
        </div>
        <div>
          <h5 style={{ fontFamily: '"DM Mono", monospace', fontSize: 11, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--ink-mute)", marginBottom: 16 }}>
            {lower ? `${results.length} match${results.length === 1 ? "" : "es"}` : "From the catalog"}
          </h5>
          <div className="search-results">
            {results.map((p) => (
              <div key={p.name} className="search-result-card" onClick={() => navTo(p.route)} data-cursor="View" style={{ cursor: "none" }}>
                <div className="img" style={{ backgroundImage: `url(${p.img})` }}></div>
                <div className="name">{p.name}</div>
                <div className="sub">{p.sub} · {formatPrice(p.price)}</div>
              </div>
            ))}
            {results.length === 0 && (
              <p className="t-body" style={{ gridColumn: "1 / -1", color: "var(--ink-mute)", fontStyle: "italic", fontSize: 22, fontFamily: '"GT Sectra","Instrument Serif",serif' }}>
                Nothing in the catalog matches that — try a category, or write to us.
              </p>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

/* Expose to other Babel scripts */
Object.assign(window, {
  useLenis, Cursor, MagneticButton, Reveal, RevealGroup, RevealLines, Header, Footer,
  CartDrawer, SearchOverlay,
});
