/* eslint-disable */
/* cityform — App shell v2
   Forks app.jsx with v2-specific tweaks:
     · heroMode    — model / photo / plan / triptych
     · sceneMode   — scroll / auto / off (the 4-phase signature scene)
     · motionDensity — confident / subtle / off
     · hideStickers — global override that returns null from CitySticker

   The current tweak state is mirrored to window.__v2 and broadcast via
   the `cf-v2-tweaks` event so page-level components can react without
   prop-drilling. Plus the original v1 tweaks (mode, density, accent
   preview) survive unchanged.
*/

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "mode": "light",
  "density": "standard",
  "cardVariant": "photo",
  "previewAccent": "vermilion",
  "heroMode": "model",
  "sceneMode": "scroll",
  "motionDensity": "confident",
  "hideStickers": false
}/*EDITMODE-END*/;

/* Wrap CitySticker so the hideStickers tweak takes effect everywhere.
   The original symbol is captured ONCE — re-wrapping on hot-reload of
   this script would otherwise infinitely chain wrappers. */
(function () {
  if (window.__cfStickerWrapped) return;
  const original = window.CitySticker;
  window.CitySticker = function CitySticker(props) {
    if (window.__v2 && window.__v2.hideStickers) return null;
    return original ? original(props) : null;
  };
  window.__cfStickerWrapped = true;
})();

function App() {
  const [route, setRoute] = React.useState('home');
  const [productId, setProductId] = React.useState(null);
  const [cart, setCart] = React.useState([]);
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [catalogReady, setCatalogReady] = React.useState(false);
  const [checkoutMsg, setCheckoutMsg] = React.useState(null);

  // Mirror v2 tweaks onto window so non-app components can read them.
  React.useEffect(() => {
    window.__v2 = {
      heroMode: t.heroMode,
      sceneMode: t.sceneMode,
      motionDensity: t.motionDensity,
      hideStickers: t.hideStickers,
    };
    window.dispatchEvent(new CustomEvent('cf-v2-tweaks', { detail: window.__v2 }));
    // Motion density — flip a class on <html> that disables transitions
    // when set to 'off', or boosts them when set to 'confident'.
    const root = document.documentElement;
    root.removeAttribute('data-motion');
    if (t.motionDensity && t.motionDensity !== 'subtle') {
      root.setAttribute('data-motion', t.motionDensity);
    }
  }, [t.heroMode, t.sceneMode, t.motionDensity, t.hideStickers]);

  // Live admin catalogue, with fallback to bundled data.js (same as v1).
  React.useEffect(() => {
    let cancelled = false;
    fetch('/api/storefront/catalog')
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(live => {
        if (cancelled) return;
        if (Array.isArray(live) && live.length > 0) {
          // Merge, don't replace: live D1 entries are authoritative & buyable;
          // the bundled designed collection (incl. the Sheffield hero + its
          // curated GLB) persists for the look but is marked non-buyable
          // (stock 0) since it isn't in the D1 source of truth.
          const bundled = Array.isArray(window.CATALOG) ? window.CATALOG : [];
          const liveIds = new Set(live.map(x => x.id));
          const keptBundled = bundled
            .filter(b => !liveIds.has(b.id))
            .map(b => ({ ...b, stock: 0 }));
          window.CATALOG = [...live, ...keptBundled];
          // Re-apply v2 photo/GLB augmentation over the merged catalogue.
          if (typeof window.__applyV2Catalog === 'function') window.__applyV2Catalog();
        }
        setCatalogReady(true);
      })
      .catch(() => { if (!cancelled) setCatalogReady(true); });
    return () => { cancelled = true; };
  }, []);

  React.useEffect(() => {
    document.documentElement.setAttribute('data-mode', t.mode || 'light');
    document.documentElement.setAttribute('data-density', t.density || 'standard');
  }, [t.mode, t.density]);

  React.useEffect(() => { window.scrollTo({ top:0 }); }, [route, productId]);

  if (!catalogReady) {
    return (
      <div style={{ minHeight:'100vh', background:'var(--bg)', display:'flex', alignItems:'center', justifyContent:'center' }}>
        <div className="eyebrow" style={{ color:'var(--stone)' }}>LOADING CATALOGUE…</div>
      </div>
    );
  }

  // Commission ("atelier") is out of scope for v1 — fold it back to home.
  const go = (r, id) => {
    if (r === 'atelier') r = 'home';
    setRoute(r);
    if (id) setProductId(id);
  };

  const addToCart = (item) => setCart(c => [...c, item]);
  const removeFromCart = (i) => setCart(c => c.filter((_, idx) => idx !== i));

  // Cart -> Stripe Checkout. D1 is the price/stock authority; we send only
  // slug + qty. Browser is redirected to Stripe's hosted payment page.
  const checkout = async () => {
    if (checkoutMsg === 'loading') return;
    setCheckoutMsg('loading');
    const byId = new Map();
    cart.forEach((i) => byId.set(i.id, (byId.get(i.id) || 0) + (i.qty || 1)));
    const items = [...byId].map(([slug, qty]) => ({ slug, qty }));
    try {
      const res = await fetch('/api/checkout', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ items }),
      });
      const data = await res.json().catch(() => ({}));
      if (res.status === 409 && Array.isArray(data.sold)) {
        setCheckoutMsg('No longer available: ' + data.sold.join(', '));
        return;
      }
      if (!res.ok || !data.url) {
        setCheckoutMsg('Could not start checkout. Please try again.');
        return;
      }
      window.location = data.url;
    } catch (e) {
      setCheckoutMsg('Could not start checkout. Please try again.');
    }
  };

  return (
    <div style={{ minHeight:'100vh', background:'var(--bg)' }}>
      <TopNav route={route} go={go} cartCount={cart.length}/>
      {route === 'home'    && <HomePage go={go} t={t}/>}
      {route === 'atlas'   && <AtlasPage go={go} t={t}/>}
      {route === 'product' && <ProductPage go={go} id={productId || 'sheffield'} t={t} addToCart={addToCart}/>}
      {route === 'atelier' && <MakeYoursPage go={go} t={t} addToCart={addToCart}/>}
      {route === 'cart'    && <CartPage go={go} cart={cart} removeFromCart={removeFromCart} checkout={checkout} checkoutMsg={checkoutMsg} t={t}/>}
      {route === 'order'   && <CartPage go={go} cart={cart} removeFromCart={removeFromCart} checkout={checkout} checkoutMsg={checkoutMsg} t={t}/>}
      {route === 'journal' && <StubPage go={go} title="Journal" subtitle="Process notes from the Sheffield studio." />}
      {route === 'about'   && <StubPage go={go} title="Studio" subtitle="Cityform is one designer, one printer, twelve cities." />}

      <TweaksPanel>
        <TweakSection label="v2 home" />
        <TweakSelect label="Hero treatment" value={t.heroMode}
          options={[
            { value:'model',    label:'3D model · rotating' },
            { value:'photo',    label:'Photo gallery' },
            { value:'plan',     label:'Plan view' },
            { value:'triptych', label:'Triptych · object + plan + detail' },
          ]}
          onChange={(v) => setTweak('heroMode', v)} />
        <TweakRadio label="Process scene" value={t.sceneMode}
          options={[
            { value:'scroll', label:'Scroll' },
            { value:'auto',   label:'Auto' },
            { value:'off',    label:'Off' },
          ]}
          onChange={(v) => setTweak('sceneMode', v)} />
        <TweakRadio label="Motion" value={t.motionDensity}
          options={[
            { value:'confident', label:'Confident' },
            { value:'subtle',    label:'Subtle' },
            { value:'off',       label:'Off' },
          ]}
          onChange={(v) => setTweak('motionDensity', v)} />
        <TweakToggle label="Hide signature stickers" value={!!t.hideStickers}
          onChange={(v) => setTweak('hideStickers', v)} />

        <TweakSection label="Display" />
        <TweakRadio label="Mode" value={t.mode}
          options={['light', 'dark']}
          onChange={(v) => setTweak('mode', v)} />
        <TweakRadio label="Card density" value={t.density}
          options={['cozy', 'standard', 'dense']}
          onChange={(v) => setTweak('density', v)} />

        <TweakSection label="Quick nav" />
        <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
          {[
            ['home',    'Home'],
            ['atlas',   'Collection'],
            ['product', 'Product'],
            ['atelier', 'Commission'],
            ['cart',    'Bag'],
            ['order',   'Order'],
          ].map(([r, l]) => (
            <button key={r} onClick={() => go(r, r === 'product' ? 'sheffield' : null)}
              style={{
                fontSize:11, padding:'6px 10px',
                border:`1px solid ${route === r ? '#fff' : 'rgba(255,255,255,0.25)'}`,
                background: route === r ? '#fff' : 'transparent',
                color: route === r ? '#000' : 'inherit',
                cursor:'pointer', fontFamily:'Inter, sans-serif',
              }}>
              {l}
            </button>
          ))}
        </div>
      </TweaksPanel>
    </div>
  );
}

function StubPage({ go, title, subtitle }) {
  return (
    <div style={{ background:'var(--mist)', minHeight:'60vh', display:'flex', alignItems:'center', justifyContent:'center', flexDirection:'column' }}>
      <div className="eyebrow">IN DEVELOPMENT</div>
      <h1 className="display-section" style={{ fontSize:84, marginTop:14, marginBottom:14 }}>{title}</h1>
      <p className="body" style={{ fontSize:17, color:'var(--stone)', maxWidth:520, textAlign:'center' }}>{subtitle}</p>
      <button className="btn-v2 btn-v2-ghost" style={{ marginTop:32 }} onClick={() => go('home')}>← Back home</button>
    </div>
  );
}

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