/* global React */
// Rayu — cart + checkout, modelled on a default Shopify storefront:
//   add-to-cart → slide-out drawer → /cart page → checkout → thank-you.
//
// FRONT-END MOCK. No payment provider is wired up (see rayu-knowledge.md §8):
// "Pay now" validates the form, then routes to the confirmation screen. No money
// moves, no card data leaves the page, nothing is sent anywhere.
//
// Cart state lives in localStorage and is exposed on window.RayuCart so the
// plain <a href="Order.html"> CTAs already scattered through hero.jsx and
// sections.jsx keep working — see the delegated click handler at the bottom.

const { useState, useEffect, useCallback, useRef: useCartRef } = React;

const CART_KEY = "rayu.cart.v1";

/* The one thing Rayu sells: a single membership, no variants. Swap the image
   for the real product shot when it lands (see PRODUCT_IMAGE). */
const PRODUCT_IMAGE = "assets/band-product.png"; // real product photo (drop it in at this path)
const MEMBERSHIP = {
  id: "rayu-membership-12",
  title: "Rayu Membership",
  subtitle: "12 months · band included",
  price: 24900, // cents
  image: PRODUCT_IMAGE,
};

const SHIPPING = [
  { id: "standard", label: "Standard", detail: "3–5 business days", price: 0 },
  { id: "express", label: "Express", detail: "1–2 business days", price: 1500 },
];

/* Discount codes the mock knows about. RAYU15 is the one the top banner sells,
   and the banner CTA pre-applies it so the 15% promise holds at checkout. */
const DISCOUNTS = {
  RAYU15: { label: "RAYU15", rate: 0.15 },
  WELCOME10: { label: "WELCOME10", rate: 0.1 },
};
const PROMO_KEY = "rayu.promo.v1";
const BANNER_KEY = "rayu.banner.dismissed.v1";

const setPromo = (code) => { try { localStorage.setItem(PROMO_KEY, code); } catch (e) {} };
const getPromo = () => { try { return localStorage.getItem(PROMO_KEY); } catch (e) { return null; } };

const money = (cents) =>
  cents === 0 ? "Free" : "$" + (cents / 100).toFixed(2);

/* ── Store ───────────────────────────────────────────────────────────────
   Tiny pub/sub over localStorage. React state alone won't do: the CTAs that
   add to cart live outside the React tree that renders the drawer.          */
function createCart() {
  let items = [];
  try {
    const raw = localStorage.getItem(CART_KEY);
    if (raw) items = JSON.parse(raw) || [];
  } catch (e) {
    items = [];
  }
  const subs = new Set();
  const emit = () => {
    try { localStorage.setItem(CART_KEY, JSON.stringify(items)); } catch (e) {}
    subs.forEach((fn) => fn(items));
  };
  return {
    get: () => items,
    subscribe(fn) { subs.add(fn); return () => subs.delete(fn); },
    add() {
      // Membership is a subscription: one per cart, never stacked.
      if (!items.find((i) => i.id === MEMBERSHIP.id)) {
        items.push({ ...MEMBERSHIP, qty: 1 });
        emit();
      }
    },
    remove(id) { items = items.filter((i) => i.id !== id); emit(); },
    clear() { items = []; emit(); },
    count: () => items.reduce((n, i) => n + i.qty, 0),
    subtotal: () => items.reduce((n, i) => n + i.price * i.qty, 0),
  };
}

const cart = createCart();

function useCart() {
  const [items, setItems] = useState(cart.get());
  useEffect(() => cart.subscribe((next) => setItems([...next])), []);
  return {
    items,
    count: items.reduce((n, i) => n + i.qty, 0),
    subtotal: items.reduce((n, i) => n + i.price * i.qty, 0),
  };
}

/* ── Router ──────────────────────────────────────────────────────────────
   Hash routes so the whole thing stays a single static index.html.         */
function useRoute() {
  const [route, setRoute] = useState(() => window.location.hash || "#/");
  useEffect(() => {
    const onHash = () => {
      setRoute(window.location.hash || "#/");
      window.scrollTo(0, 0);
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);
  return route;
}

const go = (hash) => { window.location.hash = hash; };

/* ── Announcement bar ────────────────────────────────────────────────────
   Fixed above the nav; .nav / .ck-header are offset by --bar-h. The offset is
   driven by data-bar on <html> so dismissing it collapses the space too.     */
function AnnouncementBar({ onOrder }) {
  const [gone, setGone] = useState(() => {
    try { return sessionStorage.getItem(BANNER_KEY) === "1"; } catch (e) { return false; }
  });

  useEffect(() => {
    document.documentElement.dataset.bar = gone ? "off" : "on";
  }, [gone]);

  if (gone) return null;

  return (
    <div className="ck-bar">
      <p className="ck-bar-copy">
        <strong>15% off</strong> with 12 month access today
      </p>
      <button
        className="ck-bar-cta"
        onClick={() => { setPromo("RAYU15"); onOrder(); }}
      >
        Get started now
      </button>
      <button
        className="ck-bar-x"
        aria-label="Dismiss"
        onClick={() => {
          try { sessionStorage.setItem(BANNER_KEY, "1"); } catch (e) {}
          setGone(true);
        }}
      >
        ×
      </button>
    </div>
  );
}

function ShopHeader() {
  const { count } = useCart();
  return (
    <header className="ck-header">
      <div className="ck-header-in">
        <a href="#/" className="ck-logo"><img src="assets/logo-white.png" alt="rayu.ai" /></a>
        <button className="ck-header-cart" onClick={() => go("#/cart")}>
          Cart <span>{count}</span>
        </button>
      </div>
    </header>
  );
}

function LineItem({ item, onRemove, compact }) {
  return (
    <div className={compact ? "ck-line compact" : "ck-line"}>
      <div className="ck-line-media">
        <img src={item.image} alt={item.title} />
        <span className="ck-line-qty">{item.qty}</span>
      </div>
      <div className="ck-line-body">
        <div className="ck-line-top">
          <div>
            <h3 className="ck-line-title">{item.title}</h3>
            <p className="ck-line-sub">{item.subtitle}</p>
          </div>
          <div className="ck-line-price">{money(item.price * item.qty)}</div>
        </div>
        {!compact && onRemove && (
          <div className="ck-line-actions">
            <button className="ck-link" onClick={onRemove}>Remove</button>
          </div>
        )}
      </div>
    </div>
  );
}

function EmptyCart() {
  return (
    <div className="ck-empty">
      <h2 className="display">Your cart is empty.</h2>
      <p>Rayu is with you from the day the band lands.</p>
      <button className="btn" onClick={() => { cart.add(); go("#/cart"); }}>
        Add the membership — $249/year
      </button>
      <a className="ck-link" href="#/">Continue shopping</a>
    </div>
  );
}

/* ── Cart drawer ─────────────────────────────────────────────────────── */
function CartDrawer({ open, onClose }) {
  const { items, subtotal } = useCart();
  const panelRef = useCartRef(null);

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    const first = panelRef.current && panelRef.current.querySelector("button");
    if (first) first.focus();
    return () => {
      document.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [open, onClose]);

  return (
    <div className={open ? "ck-drawer-root open" : "ck-drawer-root"} aria-hidden={!open}>
      <div className="ck-scrim" onClick={onClose} />
      <aside
        ref={panelRef}
        className="ck-drawer"
        role="dialog"
        aria-modal="true"
        aria-label="Cart"
      >
        <div className="ck-drawer-head">
          <h2>Your cart</h2>
          <button className="ck-close" onClick={onClose} aria-label="Close cart">×</button>
        </div>

        {items.length === 0 ? (
          <div className="ck-drawer-empty">
            <p>Your cart is empty.</p>
            <button className="btn" onClick={() => cart.add()}>Add the membership</button>
          </div>
        ) : (
          <>
            <div className="ck-drawer-body">
              {items.map((item) => (
                <LineItem
                  key={item.id}
                  item={item}
                  onRemove={() => cart.remove(item.id)}
                />
              ))}
            </div>
            <div className="ck-drawer-foot">
              <div className="ck-row">
                <span>Subtotal</span>
                <strong>{money(subtotal)}</strong>
              </div>
              <p className="ck-note">
                Shipping and taxes calculated at checkout. Free shipping · 60-day money-back guarantee.
              </p>
              <button className="btn ck-full" onClick={() => { onClose(); go("#/checkout"); }}>
                Checkout
              </button>
              <button className="ck-link ck-full" onClick={() => { onClose(); go("#/cart"); }}>
                View cart
              </button>
            </div>
          </>
        )}
      </aside>
    </div>
  );
}

/* ── Cart page ───────────────────────────────────────────────────────── */
function CartPage() {
  const { items, subtotal } = useCart();

  return (
    <>
      <ShopHeader />
      <main className="ck-page">
        <div className="shell">
          {items.length === 0 ? <EmptyCart /> : (
            <>
              <div className="ck-page-head">
                <h1 className="display ck-h1">Your cart</h1>
                <a className="ck-link" href="#/">Continue shopping</a>
              </div>

              <div className="ck-cart-grid">
                <div className="ck-cart-lines">
                  {items.map((item) => (
                    <LineItem
                      key={item.id}
                      item={item}
                      onColor={(c) => cart.setColor(c)}
                      onRemove={() => cart.remove(item.id)}
                    />
                  ))}
                </div>

                <aside className="ck-summary">
                  <h2 className="ck-summary-h">Order summary</h2>
                  <div className="ck-row"><span>Subtotal</span><span>{money(subtotal)}</span></div>
                  <div className="ck-row"><span>Shipping</span><span>Free</span></div>
                  <div className="ck-row ck-total">
                    <span>Total</span>
                    <strong>{money(subtotal)}</strong>
                  </div>
                  <p className="ck-note">Taxes included. 60-day money-back guarantee.</p>
                  <button className="btn ck-full" onClick={() => go("#/checkout")}>
                    Checkout
                  </button>
                </aside>
              </div>
            </>
          )}
        </div>
      </main>
    </>
  );
}

/* ── Checkout ────────────────────────────────────────────────────────── */
const REQUIRED = ["email", "first", "last", "address", "city", "postcode", "card", "expiry", "cvc", "cardName"];

const LABELS = {
  email: "Email", first: "First name", last: "Last name", address: "Address",
  city: "City", postcode: "Eircode / Postcode", card: "Card number",
  expiry: "Expiry (MM/YY)", cvc: "CVC", cardName: "Name on card",
};

function validate(form) {
  const errs = {};
  REQUIRED.forEach((k) => { if (!String(form[k] || "").trim()) errs[k] = `${LABELS[k]} is required`; });
  if (form.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) errs.email = "Enter a valid email";
  const digits = String(form.card || "").replace(/\s/g, "");
  if (digits && !/^\d{13,19}$/.test(digits)) errs.card = "Enter a valid card number";
  if (form.expiry && !/^(0[1-9]|1[0-2])\s?\/\s?\d{2}$/.test(form.expiry)) errs.expiry = "Use MM/YY";
  if (form.cvc && !/^\d{3,4}$/.test(form.cvc)) errs.cvc = "3–4 digits";
  return errs;
}

function Field({ name, form, errs, onChange, type = "text", placeholder, autoComplete, span }) {
  const bad = errs[name];
  return (
    <label className={span ? "ck-field ck-span" : "ck-field"}>
      <span className="ck-label">{LABELS[name]}</span>
      <input
        className={bad ? "ck-input bad" : "ck-input"}
        type={type}
        value={form[name] || ""}
        placeholder={placeholder}
        autoComplete={autoComplete}
        aria-invalid={!!bad}
        onChange={(e) => onChange(name, e.target.value)}
      />
      {bad && <span className="ck-err">{bad}</span>}
    </label>
  );
}

function CheckoutPage() {
  const { items, subtotal } = useCart();
  const [form, setForm] = useState({ country: "Ireland" });
  const [errs, setErrs] = useState({});
  const [ship, setShip] = useState("standard");
  // Banner CTA stashes RAYU15 — carry it into checkout so the 15% actually lands.
  const [code, setCode] = useState(() => getPromo() || "");
  const [applied, setApplied] = useState(() => DISCOUNTS[getPromo()] || null);
  const [codeErr, setCodeErr] = useState("");

  const set = useCallback((k, v) => {
    setForm((f) => ({ ...f, [k]: v }));
    setErrs((e) => (e[k] ? { ...e, [k]: undefined } : e));
  }, []);

  if (items.length === 0) {
    return (<><ShopHeader /><main className="ck-page"><div className="shell"><EmptyCart /></div></main></>);
  }

  const shipping = SHIPPING.find((s) => s.id === ship);
  const discount = applied ? Math.round(subtotal * applied.rate) : 0;
  const total = subtotal - discount + shipping.price;

  const applyCode = () => {
    const hit = DISCOUNTS[code.trim().toUpperCase()];
    if (hit) { setApplied(hit); setCodeErr(""); }
    else { setApplied(null); setCodeErr("That code isn't valid."); }
  };

  const submit = (e) => {
    e.preventDefault();
    const found = validate(form);
    setErrs(found);
    if (Object.keys(found).length) {
      const first = document.querySelector(".ck-input.bad");
      if (first) first.focus();
      return;
    }
    // Mock: no payment provider is wired up. Stash the order and confirm.
    try {
      sessionStorage.setItem("rayu.order.v1", JSON.stringify({
        email: form.email, total,
      }));
    } catch (err) {}
    cart.clear();
    go("#/order-confirmed");
  };

  return (
    <>
      <ShopHeader />
      <main className="ck-checkout">
        <form className="ck-checkout-main" onSubmit={submit} noValidate>
          <div className="ck-checkout-inner">
            <h1 className="ck-h2">Contact</h1>
            <div className="ck-fields">
              <Field name="email" form={form} errs={errs} onChange={set} type="email"
                placeholder="you@example.com" autoComplete="email" span />
            </div>

            <h2 className="ck-h2">Delivery</h2>
            <div className="ck-fields">
              <label className="ck-field ck-span">
                <span className="ck-label">Country / region</span>
                <select className="ck-input" value={form.country}
                  onChange={(e) => set("country", e.target.value)}>
                  {["Ireland", "United Kingdom", "United States", "Germany", "France"].map((c) =>
                    <option key={c}>{c}</option>)}
                </select>
              </label>
              <Field name="first" form={form} errs={errs} onChange={set} autoComplete="given-name" />
              <Field name="last" form={form} errs={errs} onChange={set} autoComplete="family-name" />
              <Field name="address" form={form} errs={errs} onChange={set} autoComplete="street-address" span />
              <Field name="city" form={form} errs={errs} onChange={set} autoComplete="address-level2" />
              <Field name="postcode" form={form} errs={errs} onChange={set} autoComplete="postal-code" />
            </div>

            <h2 className="ck-h2">Shipping method</h2>
            <div className="ck-choices">
              {SHIPPING.map((s) => (
                <label key={s.id} className={ship === s.id ? "ck-choice on" : "ck-choice"}>
                  <input type="radio" name="ship" checked={ship === s.id}
                    onChange={() => setShip(s.id)} />
                  <span className="ck-choice-body">
                    <span className="ck-choice-label">{s.label}</span>
                    <span className="ck-choice-detail">{s.detail}</span>
                  </span>
                  <span className="ck-choice-price">{money(s.price)}</span>
                </label>
              ))}
            </div>

            <h2 className="ck-h2">Payment</h2>
            <p className="ck-secure">All transactions are secure and encrypted.</p>
            <div className="ck-fields ck-card">
              <Field name="card" form={form} errs={errs} onChange={set}
                placeholder="1234 5678 9012 3456" autoComplete="cc-number" span />
              <Field name="expiry" form={form} errs={errs} onChange={set}
                placeholder="MM/YY" autoComplete="cc-exp" />
              <Field name="cvc" form={form} errs={errs} onChange={set}
                placeholder="123" autoComplete="cc-csc" />
              <Field name="cardName" form={form} errs={errs} onChange={set}
                autoComplete="cc-name" span />
            </div>

            <p className="ck-mock">
              Demo checkout — no payment provider is connected. Nothing is charged and no card
              details leave this page.
            </p>

            <button type="submit" className="btn ck-full ck-pay">Pay now · {money(total)}</button>
            <a className="ck-link ck-back" href="#/cart">← Return to cart</a>
          </div>
        </form>

        <aside className="ck-checkout-aside">
          <div className="ck-checkout-aside-in">
            {items.map((item) => <LineItem key={item.id} item={item} compact />)}

            <div className="ck-code">
              <input
                className="ck-input"
                placeholder="Discount code"
                value={code}
                onChange={(e) => { setCode(e.target.value); setCodeErr(""); }}
              />
              <button type="button" className="ck-code-btn" onClick={applyCode}>Apply</button>
            </div>
            {codeErr && <span className="ck-err">{codeErr}</span>}
            {applied && (
              <div className="ck-tag">{applied.label} — {Math.round(applied.rate * 100)}% off</div>
            )}

            <div className="ck-rows">
              <div className="ck-row"><span>Subtotal</span><span>{money(subtotal)}</span></div>
              {discount > 0 && (
                <div className="ck-row ck-row-cut"><span>Discount</span><span>−{money(discount)}</span></div>
              )}
              <div className="ck-row"><span>Shipping</span><span>{money(shipping.price)}</span></div>
              <div className="ck-row ck-total"><span>Total</span><strong>{money(total)}</strong></div>
            </div>
            <p className="ck-note">Taxes included · 60-day money-back guarantee</p>
          </div>
        </aside>
      </main>
    </>
  );
}

/* ── Thank you ───────────────────────────────────────────────────────── */
function OrderConfirmed() {
  let order = {};
  try { order = JSON.parse(sessionStorage.getItem("rayu.order.v1")) || {}; } catch (e) {}

  return (
    <>
      <ShopHeader />
      <main className="ck-page">
        <div className="shell">
          <div className="ck-done">
            <div className="ck-done-mark">✓</div>
            <p className="eyebrow">Order confirmed</p>
            <h1 className="display ck-h1">Rayu is on her way.</h1>
            <p className="ck-done-body">
              {order.email
                ? <>We've sent a confirmation to <strong>{order.email}</strong>. Your band ships within 2 business days — Rayu starts the day you unbox it.</>
                : <>Your band ships within 2 business days — Rayu starts the day you unbox it.</>}
            </p>
            <p className="ck-mock">
              Demo order — nothing was charged and no email was sent.
            </p>
            <a className="btn" href="#/">Back to rayu.ai</a>
          </div>
        </div>
      </main>
    </>
  );
}

/* ── CTA delegation ──────────────────────────────────────────────────────
   The homepage CTAs are plain <a href="Order.html…"> / "Checkout.html…" links
   (several sit inside the hero block, which is off-limits to edit). Catch them
   here instead: Order → add to cart + open the drawer, Checkout → checkout.   */
function useCtaInterceptor(openDrawer) {
  useEffect(() => {
    const onClick = (e) => {
      const a = e.target.closest && e.target.closest("a[href]");
      if (!a) return;
      const href = a.getAttribute("href") || "";
      if (/^Order\.html/i.test(href)) {
        e.preventDefault();
        cart.add();
        openDrawer();
      } else if (/^Checkout\.html/i.test(href)) {
        e.preventDefault();
        cart.add();
        go("#/checkout");
      }
    };
    document.addEventListener("click", onClick);
    return () => document.removeEventListener("click", onClick);
  }, [openDrawer]);
}

Object.assign(window, {
  RayuCart: cart, useCart, useRoute, useCtaInterceptor,
  CartDrawer, CartPage, CheckoutPage, OrderConfirmed, AnnouncementBar,
});
