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

/* ============== Utility hooks ============== */

function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    // If IntersectionObserver isn't available, reveal immediately so content
    // is never stuck invisible.
    if (typeof IntersectionObserver === "undefined") {
      el.classList.add("in");
      return;
    }
    const io = new IntersectionObserver(
      (entries) =>
        entries.forEach((e) => {
          if (e.isIntersecting || e.intersectionRatio > 0) {
            e.target.classList.add("in");
            io.unobserve(e.target);
          }
        }),
      // threshold 0 + generous rootMargin so sections taller than the mobile
      // viewport (where 12% may never be visible at once) still reveal as
      // soon as any pixel enters — or even slightly before.
      { threshold: 0, rootMargin: "200px 0px" }
    );
    io.observe(el);
    // Safety net: if for any reason the observer never fires (iOS Safari
    // sometimes skips initial callbacks until the next paint/orientation
    // change), force-reveal after a short delay.
    const fallback = setTimeout(() => {
      if (el && !el.classList.contains("in")) el.classList.add("in");
    }, 1200);
    return () => {
      io.disconnect();
      clearTimeout(fallback);
    };
  }, []);
  return ref;
}

function useScrollY() {
  const [y, setY] = useState(0);
  useEffect(() => {
    const onScroll = () => setY(window.scrollY);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return y;
}

/* Mobile breakpoint: ≤720px = phones, ≤1024px = tablet (single column). */
function useIsMobile(breakpoint = 720) {
  const [m, setM] = useState(() =>
    typeof window !== "undefined" ? window.innerWidth <= breakpoint : false
  );
  useEffect(() => {
    const onResize = () => setM(window.innerWidth <= breakpoint);
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, [breakpoint]);
  return m;
}
window.useIsMobile = useIsMobile;

/* ============== Painting placeholder ============== */

function Painting({ p, aspect = "4/5", framed = false, tag = true, className = "", style = {}, imageIndex = 0, fit = "cover" }) {
  const img = p.images && p.images[imageIndex];

  // fit modes:
  //   "cover"   → background-image with cover crop, fixed `aspect` box (tiles, grids)
  //   "contain" → fixed `aspect` box, image letterboxed inside on paper bg
  //   "natural" → no forced aspect; the image controls the rendered shape
  // For uploaded images we honour the requested fit. The "natural" mode is
  // what the artwork detail page uses so a landscape painting stays
  // landscape, a portrait stays portrait, etc.
  if (img && fit !== "cover") {
    if (fit === "natural") {
      if (framed) {
        return (
          <div className={`painting framed ${className}`} style={{ ...style }}>
            <div className="canvas" style={{ position: "relative", height: "auto" }}>
              <img loading="lazy" decoding="async" src={img} alt={p.title} style={{ display: "block", width: "100%", height: "auto" }} />
              {tag && <div className="ptag">{p.title}</div>}
            </div>
          </div>
        );
      }
      return (
        <div className={`painting ${className}`} style={{ background: "var(--paper)", ...style }}>
          <img loading="lazy" decoding="async" src={img} alt={p.title} style={{ display: "block", width: "100%", height: "auto" }} />
          {tag && <div className="ptag">{p.title}</div>}
        </div>
      );
    }
    if (fit === "contain") {
      if (framed) {
        return (
          <div className={`painting framed ${className}`} style={{ aspectRatio: aspect, ...style }}>
            <div className="canvas" style={{ position: "relative", background: "var(--paper)" }}>
              <img loading="lazy" decoding="async" src={img} alt={p.title} style={{
                display: "block", width: "100%", height: "100%",
                objectFit: "contain", objectPosition: "center",
              }} />
              {tag && <div className="ptag">{p.title}</div>}
            </div>
          </div>
        );
      }
      return (
        <div className={`painting ${className}`} style={{ aspectRatio: aspect, background: "var(--paper)", ...style }}>
          <img src={img} alt={p.title} style={{
            display: "block", width: "100%", height: "100%",
            objectFit: "contain", objectPosition: "center",
          }} />
          {tag && <div className="ptag">{p.title}</div>}
        </div>
      );
    }
  }

  // Default cropped-cover / gradient placeholder behaviour.
  const bgImage = img ? `url("${img}")` : null;
  const bgStyle = bgImage ?
    { backgroundImage: bgImage, backgroundSize: "cover", backgroundPosition: "center", aspectRatio: aspect } :
    { background: p.grad, aspectRatio: aspect };

  if (framed) {
    return (
      <div className={`painting framed ${className}`} style={{ aspectRatio: aspect, ...style }}>
        <div className="canvas" style={bgImage ?
        { backgroundImage: bgImage, backgroundSize: "cover", backgroundPosition: "center" } :
        { background: p.grad }}>
          {tag && <div className="ptag">{p.title}</div>}
        </div>
      </div>);

  }
  return (
    <div className={`painting ${className}`} style={{ ...bgStyle, ...style }}>
      {tag && <div className="ptag">{p.title}</div>}
    </div>);

}

/* ============== Icons (minimal line) ============== */

const Icon = {
  Search: (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>,
  Bag: (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M6 8h12l-1 12H7L6 8Z" /><path d="M9 8a3 3 0 0 1 6 0" /></svg>,
  Menu: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M3 7h18M3 12h18M3 17h18" /></svg>,
  Close: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="m6 6 12 12M18 6 6 18" /></svg>,
  ArrowR: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M5 12h14M13 6l6 6-6 6" /></svg>,
  ArrowL: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M19 12H5M11 6l-6 6 6 6" /></svg>,
  ArrowDown: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M12 5v14M6 13l6 6 6-6" /></svg>,
  Plus: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M12 5v14M5 12h14" /></svg>,
  Minus: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M5 12h14" /></svg>,
  Heart: (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M12 20s-7-4.5-7-10a4 4 0 0 1 7-2.5A4 4 0 0 1 19 10c0 5.5-7 10-7 10Z" /></svg>,
  Check: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="m5 12 5 5L20 7" /></svg>,
  Zoom: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5M8 11h6M11 8v6" /></svg>,
  Star: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" {...p}><path d="m12 3 2.6 5.6 6.1.7-4.6 4.2 1.3 6L12 16.8 6.6 19.5l1.3-6L3.3 9.3l6.1-.7L12 3Z" /></svg>,
  Leaf: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.3" {...p}><path d="M4 20s2-12 16-16c0 0-2 14-16 16Z" /><path d="M4 20c4-6 8-8 12-10" /></svg>,
  Brush: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.3" {...p}><path d="M14 4 4 14a4 4 0 0 0 6 6l10-10-6-6Z" /><path d="m10 8 6 6" /></svg>
};

/* ============== Nav ============== */

function Nav({ route, navigate, cartCount, openCart, openMenu }) {
  const y = useScrollY();
  const scrolled = y > 40;
  const items = [
  ["Home", "home"],
  ["Gallery", "gallery"],
  ["About", "about"],
  ["Collector", "collector"]];

  return (
    <header style={{
      position: "fixed", top: 0, left: 0, right: 0, zIndex: 100,
      background: scrolled ? "rgba(251,245,236,0.92)" : "transparent",
      backdropFilter: scrolled ? "saturate(140%) blur(14px)" : "none",
      WebkitBackdropFilter: scrolled ? "saturate(140%) blur(14px)" : "none",
      borderBottom: scrolled ? "1px solid var(--line-soft)" : "1px solid transparent",
      transition: "all 320ms ease"
    }}>
      <div className="lf-nav-row" style={{
        maxWidth: 1440, margin: "0 auto", padding: "18px 40px",
        display: "grid", gridTemplateColumns: "1fr auto 1fr", alignItems: "center", gap: 24
      }}>
        <nav style={{ display: "flex", gap: 32, alignItems: "center" }}>
          <button onClick={openMenu} style={{ background: "transparent", border: "none", padding: 0, color: "var(--ink)", display: "flex", alignItems: "center", gap: 8 }}>
            <Icon.Menu />
            <span style={{ fontSize: 11, letterSpacing: "0.22em", textTransform: "uppercase", fontWeight: 500 }}>Menu</span>
          </button>
          <span className="lf-nav-inline-links" style={{ display: "flex", gap: 24, fontSize: 12.5, letterSpacing: "0.04em", color: "var(--ink-soft)" }}>
            {items.slice(1, 4).map(([l, r]) =>
            <a key={r} onClick={() => navigate(r)} style={{
              cursor: "pointer",
              borderBottom: route === r ? "1px solid var(--gold)" : "1px solid transparent",
              paddingBottom: 2,
              color: route === r ? "var(--ink)" : "var(--ink-soft)"
            }}>{l}</a>
            )}
          </span>
        </nav>
        <a onClick={() => navigate("home")} style={{ cursor: "pointer", textAlign: "center", display: "block" }}>
          <div style={{ fontFamily: "var(--serif)", fontSize: 26, letterSpacing: "0.18em", fontWeight: 400, color: "var(--ink)", whiteSpace: "nowrap" }}>
            LARISSA
          </div>
          <div style={{ fontSize: 9, letterSpacing: "0.42em", color: "var(--ink-mute)", textTransform: "uppercase", marginTop: -2 }}>
            Fine Art · Ontario
          </div>
        </a>
        <div style={{ display: "flex", justifyContent: "flex-end", alignItems: "center", gap: 22, color: "var(--ink)" }}>
          <a className="lf-nav-search" style={{ cursor: "pointer", fontSize: 12, letterSpacing: "0.16em", textTransform: "uppercase", display: "flex", alignItems: "center", gap: 7 }}>
            <Icon.Search /> Search
          </a>
          <button onClick={openCart} style={{
            cursor: "pointer", background: "transparent", border: "none", color: "var(--ink)",
            display: "flex", alignItems: "center", gap: 7,
            fontSize: 12, letterSpacing: "0.16em", textTransform: "uppercase", fontWeight: 500
          }}>
            <Icon.Bag /> Cart
            {cartCount > 0 &&
            <span style={{
              background: "var(--ink)", color: "var(--warm-white)",
              borderRadius: 999, minWidth: 18, height: 18, padding: "0 5px",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              fontSize: 10, letterSpacing: 0, marginLeft: 2
            }}>{cartCount}</span>
            }
          </button>
        </div>
      </div>
    </header>);

}

function MenuPanel({ onClose, navigate }) {
  const items = [
  ["Home", "home"],
  ["The Gallery", "gallery"],
  ["About Larissa", "about"],
  ["Collector Experience", "collector"]];

  // Lock page scroll while the menu is open so the underlying page can't
  // peek through if a stacking-context quirk renders the panel translucent.
  useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => { document.body.style.overflow = prev; };
  }, []);

  return (
    <div className="lf-menu-overlay" style={{
      position: "fixed", inset: 0, zIndex: 200,
      background: "rgba(46,42,36,0.32)",
      animation: "pageFade 240ms ease both"
    }} onClick={onClose}>
      <aside className="lf-menu-panel" onClick={(e) => e.stopPropagation()} style={{
        position: "absolute", top: 0, left: 0, bottom: 0, width: "min(480px, 90vw)",
        background: "var(--ivory)", padding: "32px 44px",
        display: "flex", flexDirection: "column",
        borderRight: "1px solid var(--line)"
      }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <div className="eyebrow">Menu</div>
          <button onClick={onClose} style={{ background: "transparent", border: "none", color: "var(--ink)" }}>
            <Icon.Close />
          </button>
        </div>
        <nav style={{ marginTop: 40, display: "flex", flexDirection: "column", gap: 6 }}>
          {items.map(([l, r], i) =>
          <a key={r} onClick={() => {navigate(r);onClose();}} className="lf-menu-item" style={{
            cursor: "pointer",
            fontFamily: "var(--serif)",
            fontSize: 42, lineHeight: 1.15,
            color: "var(--ink)",
            padding: "8px 0",
            borderBottom: "1px solid var(--line-soft)",
            display: "flex", alignItems: "baseline", gap: 14
          }}>
              <span style={{ fontFamily: "var(--sans)", fontSize: 10, color: "var(--ink-mute)", letterSpacing: "0.2em" }}>0{i + 1}</span>
              {l}
            </a>
          )}
        </nav>
        <div style={{ marginTop: "auto", paddingTop: 32, color: "var(--ink-soft)", fontSize: 13 }}>
          <div className="eyebrow" style={{ marginBottom: 10 }}>Studio</div>
          Lake of Gooderham · Ontario<br />
          By appointment — hello@larissaart.com
        </div>
      </aside>
    </div>);

}

/* ============== Footer ============== */

function Footer({ navigate }) {
  return (
    <footer style={{ background: "var(--paper)", color: "var(--ink)", marginTop: 120, paddingTop: 100, paddingBottom: 40 }}>
      <div style={{ maxWidth: 1280, margin: "0 auto", padding: "0 40px" }}>
        <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr 1fr", gap: 60, alignItems: "start" }}>
          <div>
            <div style={{ fontFamily: "var(--serif)", fontSize: 30, letterSpacing: "0.16em" }}>LARISSA</div>
            <div style={{ fontSize: 10, letterSpacing: "0.4em", color: "var(--ink-mute)", textTransform: "uppercase", marginTop: 2 }}>Fine Art · Ontario</div>
            <p style={{ marginTop: 24, color: "var(--ink-soft)", maxWidth: 320, fontSize: 14 }}>
              Original oil paintings from a small studio overlooking Gooderham Lake. Every work is hand-signed in oil and shipped worldwide.
            </p>
            <div className="h-script" style={{ fontSize: 26, marginTop: 22, color: "var(--gold-deep)" }}>
              with love, Larissa —
            </div>
          </div>
          <div>
            <div className="eyebrow" style={{ marginBottom: 16 }}>Explore</div>
            <ul style={{ listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 10, fontSize: 14 }}>
              {[["Gallery", "gallery"], ["About", "about"], ["Collector Experience", "collector"]].map(([l, r]) =>
              <li key={r}><a onClick={() => navigate(r)} style={{ cursor: "pointer", color: "var(--ink-soft)" }}>{l}</a></li>
              )}
            </ul>
          </div>
          <div>
            <div className="eyebrow" style={{ marginBottom: 16 }}>Collect</div>
            <ul style={{ listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 10, fontSize: 14, color: "var(--ink-soft)" }}>
              <li>One of one — never reproduced</li>
              <li>Hand-signed in oil</li>
              <li>Worldwide shipping</li>
              <li>Studio visits by appointment</li>
            </ul>
          </div>
          <div>
            <div className="eyebrow" style={{ marginBottom: 16 }}>Studio</div>
            <div style={{ color: "var(--ink-soft)", fontSize: 14, lineHeight: 1.7 }}>
              Gooderham Lake<br />
              Highlands, Ontario<br />
              Canada<br /><br />
              hello@larissaart.com<br />
              By appointment
            </div>
          </div>
        </div>
        <div style={{
          marginTop: 60, paddingTop: 24,
          borderTop: "1px solid var(--line)",
          display: "flex", justifyContent: "space-between", alignItems: "center",
          color: "var(--ink-mute)", fontSize: 12
        }}>
          <div>© Larissa Fine Art Studio, 2026. All works are original and protected by copyright.</div>
          <div style={{ display: "flex", gap: 28, alignItems: "center" }}>
            <a onClick={() => navigate("privacy")} style={{ cursor: "pointer" }}>Privacy</a>
            <a onClick={() => navigate("terms")} style={{ cursor: "pointer" }}>Terms</a>
            <a onClick={() => navigate("admin")} style={{
              cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 6,
              padding: "6px 12px", borderRadius: 999,
              border: "1px solid var(--line)", color: "var(--ink-soft)",
              fontSize: 10.5, letterSpacing: "0.2em", textTransform: "uppercase", fontWeight: 500
            }}>
              <span style={{ width: 5, height: 5, borderRadius: 999, background: "var(--gold)" }} />
              Studio Atelier
            </a>
          </div>
        </div>
      </div>
    </footer>);

}

/* ============== Cart Drawer ============== */

function CartDrawer({ open, onClose, items, removeItem, navigate }) {
  const total = items.reduce((s, i) => s + i.price, 0);
  if (!open) return null;
  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 300, background: "rgba(46,42,36,0.36)", animation: "pageFade 200ms ease both" }}>
      <aside onClick={(e) => e.stopPropagation()} style={{
        position: "absolute", top: 0, right: 0, bottom: 0, width: "min(460px, 92vw)",
        background: "var(--warm-white)", display: "flex", flexDirection: "column",
        borderLeft: "1px solid var(--line)"
      }}>
        <div style={{ padding: "28px 32px", borderBottom: "1px solid var(--line-soft)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <div>
            <div className="eyebrow">Your Selection</div>
            <div style={{ fontFamily: "var(--serif)", fontSize: 26, marginTop: 4 }}>The Studio Cart</div>
          </div>
          <button onClick={onClose} style={{ background: "transparent", border: "none" }}><Icon.Close /></button>
        </div>
        <div style={{ flex: 1, overflowY: "auto", padding: "16px 32px" }}>
          {items.length === 0 ?
          <div style={{ padding: "60px 0", textAlign: "center", color: "var(--ink-soft)" }}>
              <div className="h-script" style={{ fontSize: 38, color: "var(--gold-deep)" }}>Empty for now</div>
              <p style={{ marginTop: 8, fontSize: 14 }}>Begin in the gallery — every piece is one of one.</p>
              <button className="btn btn-ghost" style={{ marginTop: 18 }} onClick={() => {navigate("gallery");onClose();}}>
                Enter the Gallery
              </button>
            </div> :
          items.map((p) =>
          <div key={p.id} style={{ display: "grid", gridTemplateColumns: "92px 1fr auto", gap: 16, padding: "20px 0", borderBottom: "1px solid var(--line-soft)" }}>
              <Painting p={p} aspect="4/5" tag={false} />
              <div>
                <div style={{ fontFamily: "var(--serif)", fontSize: 19, lineHeight: 1.2 }}>{p.title}</div>
                <div style={{ fontSize: 12, color: "var(--ink-mute)", marginTop: 4 }}>{p.dims} · {p.medium}</div>
                <div style={{ fontSize: 13, marginTop: 8 }}>CAD ${p.price.toLocaleString()}</div>
                <button onClick={() => removeItem(p.id)} style={{ marginTop: 8, background: "transparent", border: "none", padding: 0, color: "var(--ink-mute)", fontSize: 11, letterSpacing: "0.18em", textTransform: "uppercase", cursor: "pointer" }}>Remove</button>
              </div>
              <div />
            </div>
          )}
        </div>
        {items.length > 0 &&
        <div style={{ padding: "20px 32px 28px", borderTop: "1px solid var(--line)" }}>
            <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 14, fontSize: 14, color: "var(--ink-soft)" }}>
              <span>Subtotal</span>
              <span style={{ color: "var(--ink)" }}>CAD ${total.toLocaleString()}</span>
            </div>
            <div style={{ fontSize: 11, color: "var(--ink-mute)", marginBottom: 16, lineHeight: 1.6 }}>
              Worldwide shipping & insurance calculated at checkout. Each painting ships unframed in archival crating.
            </div>
            <button className="btn btn-primary" style={{ width: "100%", justifyContent: "center" }} onClick={() => {navigate("checkout");onClose();}}>
              Begin Checkout <Icon.ArrowR />
            </button>
          </div>
        }
      </aside>
    </div>);

}

Object.assign(window, {
  useReveal, useScrollY, Painting, Icon, Nav, Footer, CartDrawer
});