/* global React, ReactDOM, Loader, Nav, Roadster, FooterCTA, ProductHero, Specs, Customize, PairsWith, useTweaks, TweaksPanel, TweakSection, TweakColor */
const { useState, useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": ["#FBD22E", "#3FBDC9", "#E94926", "#F4E5C5", "#1A1A1A"]
}/*EDITMODE-END*/;

const PALETTE_OPTIONS = [
  ["#FBD22E", "#3FBDC9", "#E94926", "#F4E5C5", "#1A1A1A"],
  ["#9FD2DE", "#1F4A52", "#E97A38", "#E8DECB", "#1A1A1A"],
  ["#F6CCD2", "#1F4A52", "#C9384A", "#FCF3DC", "#1A1A1A"],
  ["#0F1B2D", "#FF6B35", "#F7C548", "#F4F1DE", "#F8F1E5"],
  ["#E8E2D5", "#2C5F4F", "#D5573B", "#F4ECDB", "#1F1B16"],
  ["#FFE6A7", "#118AB2", "#EF476F", "#FFFCF2", "#073B4C"],
  ["#F4A300", "#A23E48", "#2E2A26", "#F0D78C", "#FBF1D6"],
  ["#101010", "#FFD23F", "#EE4266", "#F8F1E5", "#F8F1E5"],
];

function hexToRgb(hex) {
  const h = hex.replace("#", "");
  const n = parseInt(h.length === 3 ? h.split("").map(c => c + c).join("") : h, 16);
  return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
}
function rgbToHex({ r, g, b }) {
  const c = (v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, "0");
  return `#${c(r)}${c(g)}${c(b)}`;
}
function lighten(hex, amt) { const { r, g, b } = hexToRgb(hex); return rgbToHex({ r: r + (255 - r) * amt, g: g + (255 - g) * amt, b: b + (255 - b) * amt }); }
function darken(hex, amt) { const { r, g, b } = hexToRgb(hex); return rgbToHex({ r: r * (1 - amt), g: g * (1 - amt), b: b * (1 - amt) }); }
function applyPalette(arr) {
  const root = document.documentElement;
  const [bg, cyan, red, cream, ink] = arr;
  root.style.setProperty("--yellow", bg);
  root.style.setProperty("--yellow-soft", lighten(bg, 0.18));
  root.style.setProperty("--yellow-deep", darken(bg, 0.18));
  root.style.setProperty("--cyan", cyan);
  root.style.setProperty("--cyan-soft", lighten(cyan, 0.18));
  root.style.setProperty("--cyan-deep", darken(cyan, 0.22));
  root.style.setProperty("--red", red);
  root.style.setProperty("--red-deep", darken(red, 0.18));
  root.style.setProperty("--red-soft", lighten(red, 0.18));
  root.style.setProperty("--cream", cream);
  root.style.setProperty("--cream-warm", darken(cream, 0.08));
  root.style.setProperty("--paper", lighten(cream, 0.08));
  root.style.setProperty("--ink", ink);
  root.style.setProperty("--ink-soft", lighten(ink, 0.1));
}

// Default product — the Diner Cup, shown when product.html is opened with no params.
const BASE_PRODUCT = {
  sku: "WC-DC-12",
  name: "The Diner Cup",
  tag: "12 oz · Double-Wall · Custom Print",
  craft: true, // paper cup — Special Craft finishes apply
  desc: "Our flagship cup — a 12oz double-walled paper number, classic smooth sidewall, seamed on the forming press. Holds soda, coffee, milkshakes, and the occasional malted. Beautiful enough you'll want to keep one for the cupboard.",
  photo: "assets/products/the-diner-cup-1.jpg",
  gallery: ["assets/products/the-diner-cup-1.jpg", "assets/products/the-diner-cup-2.jpg", "assets/products/the-diner-cup-3.jpg", "assets/products/the-diner-cup-4.jpg"],
  colors: [
    { name: "Cherry Red",  swatch: ["#E94926", "#F4E5C5"] },
    { name: "Soda Cyan",   swatch: ["#3FBDC9", "#1A1A1A"] },
    { name: "Cream Float", swatch: ["#F4E5C5", "#E94926"] },
    { name: "Diner Black", swatch: ["#1A1A1A", "#FBD22E"] },
  ],
  // Options modeled on Vistaprint food-packaging product pages:
  // print coverage, size, material/wall, and quantity tiers.
  sizes: ["8 oz", "12 oz", "16 oz", "20 oz"],
  materials: ["Single-wall", "Double-wall", "Ripple wall"],
  prints: ["Plain", "Logo only", "Full-print"],
  quantities: ["25", "50", "100", "250", "500", "1,000"],
  specs: [
    { name: "Capacity",      value: "12 fluid ounces (355 ml)" },
    { name: "Construction",  value: "Double-wall insulated board, 320 gsm" },
    { name: "Inks",          value: "Soy-based, FDA-grade contact safe" },
    { name: "Stock",         value: "Recycled-content board, virgin food-contact ply" },
    { name: "Heat range",    value: "Cold ice through 180°F brew" },
    { name: "Lid match",     value: "Snap-on dome, sippy slot, kraft sleeve" },
    { name: "Turnaround",    value: "Quoted with your order" },
    { name: "MOQ",           value: "25 units — our smallest run" },
  ],
};

// Brand-generic spec sheet for any catalog item we don't have bespoke copy for.
const GENERIC_SPECS = [
  { name: "Material",   value: "Food-grade board & paper" },
  { name: "Printing",   value: "Up to 4 colors, Pantone-matched" },
  { name: "Inks",       value: "Soy-based, FDA contact-safe" },
  { name: "Stock",      value: "Recycled-content board, virgin food-contact ply" },
  { name: "Finishes",   value: "Silk-screen, spot UV, foil, emboss" },
  { name: "Turnaround", value: "Quoted with your order" },
  { name: "MOQ",        value: "25 units — our smallest run" },
  { name: "Custom",     value: "Any shape, any design — we can do it" },
];

function slugifyName(name) {
  return name.trim().toUpperCase().replace(/[^A-Z0-9]+/g, "-").replace(/^-+|-+$/g, "");
}

// Resolve which product to show from the URL. A menu item links with
// ?p=<name>; with no params we show the flagship Diner Cup. Every catalog item
// has bespoke copy/options/specs in src/catalog.jsx; unknown names fall back
// to a generic template.
function resolveProduct() {
  // static SEO pages (products/<slug>.html) carry the product name on <body>
  const staticName = document.body && document.body.dataset.product;
  if (staticName && window.WC_CATALOG_GET) {
    const staticHit = window.WC_CATALOG_GET(staticName);
    if (staticHit) return { ...staticHit, sku: `WC-${slugifyName(staticHit.name).slice(0, 14)}` };
  }

  let params;
  try { params = new URLSearchParams(window.location.search); } catch (e) { params = null; }
  const name = params && params.get("p");
  if (!name) return BASE_PRODUCT;

  const hit = window.WC_CATALOG_GET && window.WC_CATALOG_GET(name);
  if (hit) {
    return { ...hit, sku: `WC-${slugifyName(hit.name).slice(0, 14)}` };
  }

  const tag = params.get("t") || "Custom Print · Made in the Shop";
  const img = params.get("img");
  return {
    ...BASE_PRODUCT,
    name,
    tag,
    sku: `WC-${slugifyName(name).slice(0, 14)}`,
    desc: `${name} — custom-printed and finished in our shop. Pantone-matched inks, food-safe stock. Tell us your run size and your art, and we'll send back a mock-up with your quote.`,
    photo: img || BASE_PRODUCT.photo,
    gallery: img ? [img, ...BASE_PRODUCT.gallery.filter((g) => g !== img)].slice(0, 4) : BASE_PRODUCT.gallery,
    // Generic items: neutral size + board-stock materials; prints + quantities inherited.
    sizes: ["Small", "Medium", "Large"],
    materials: ["Kraft", "White", "Recycled"],
    specs: GENERIC_SPECS,
  };
}

const PRODUCT = resolveProduct();

// Show the brand intro loader only on the visitor's first landing this session.
// Internal navigation (e.g. Shop ⇄ Home) skips it.
function hasSeenIntro() {
  try { return sessionStorage.getItem("wc-seen-intro") === "1"; } catch (e) { return false; }
}
function markIntroSeen() {
  try { sessionStorage.setItem("wc-seen-intro", "1"); } catch (e) {}
}
function prefersReducedMotion() {
  try { return window.matchMedia("(prefers-reduced-motion: reduce)").matches; } catch (e) { return false; }
}

function App() {
  const [loaded, setLoaded] = useState(() => hasSeenIntro() || prefersReducedMotion());
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [variant, setVariant] = useState({
    size: PRODUCT.sizes[0] || "",
    material: PRODUCT.materials[0] || "",
    print: PRODUCT.prints[0] || "",
    quantity: PRODUCT.quantities[2] || PRODUCT.quantities[0] || "",
  });

  useEffect(() => { applyPalette(t.palette); }, [t.palette]);

  useEffect(() => {
    if (!loaded) return;
    const gsap = window.gsap;
    const ScrollTrigger = window.ScrollTrigger;
    gsap.registerPlugin(ScrollTrigger);

    const reduced = prefersReducedMotion();
    let lenis = null;
    if (!reduced) {
      lenis = new window.Lenis({
        duration: 1.2, smoothWheel: true, smoothTouch: false,
        easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
      });
      lenis.on("scroll", ScrollTrigger.update);
      gsap.ticker.add((time) => lenis.raf(time * 1000));
      gsap.ticker.lagSmoothing(0);
    }

    const onClick = (e) => {
      const a = e.target.closest('a[href^="#"]');
      if (!a) return;
      const id = a.getAttribute("href");
      if (id.length < 2) return;
      const el = document.querySelector(id);
      if (!el) return;
      e.preventDefault();
      if (lenis) lenis.scrollTo(el, { offset: -10, duration: 1.2 });
      else el.scrollIntoView({ behavior: "auto", block: "start" });
    };
    document.addEventListener("click", onClick);
    requestAnimationFrame(() => ScrollTrigger.refresh());

    return () => {
      document.removeEventListener("click", onClick);
      if (lenis) lenis.destroy();
    };
  }, [loaded]);

  return (
    <>
      <a className="skip-link" href="#main">Skip to content</a>
      {!loaded && <Loader onDone={() => { markIntroSeen(); setLoaded(true); }} />}
      <div className="entry-swipe" aria-hidden="true" />
      <div id="main" tabIndex={-1} className={loaded ? "" : "is-prep"}>
        <Nav />
        <Roadster />
        <ProductHero product={PRODUCT} variant={variant} setVariant={setVariant} />
        <Specs product={PRODUCT} />
        <Customize product={PRODUCT} />
        <PairsWith />
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Color Palette" />
        <TweakColor label="Preset" value={t.palette} options={PALETTE_OPTIONS}
          onChange={(v) => setTweak("palette", v)} />
        <TweakSection label="Individual Colors" />
        <TweakColor label="Background"  value={t.palette[0]} onChange={(v) => setTweak("palette", [v, t.palette[1], t.palette[2], t.palette[3], t.palette[4]])} />
        <TweakColor label="Cyan Shapes" value={t.palette[1]} onChange={(v) => setTweak("palette", [t.palette[0], v, t.palette[2], t.palette[3], t.palette[4]])} />
        <TweakColor label="Red Accents" value={t.palette[2]} onChange={(v) => setTweak("palette", [t.palette[0], t.palette[1], v, t.palette[3], t.palette[4]])} />
        <TweakColor label="Cream"       value={t.palette[3]} onChange={(v) => setTweak("palette", [t.palette[0], t.palette[1], t.palette[2], v, t.palette[4]])} />
        <TweakColor label="Ink (Text)"  value={t.palette[4]} onChange={(v) => setTweak("palette", [t.palette[0], t.palette[1], t.palette[2], t.palette[3], v])} />
      </TweaksPanel>
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
