// app.jsx — main App, view router, Tweaks
const { useState, useEffect, useMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "background": "balanced",
  "menuLayout": "sidebar",
  "rowExpand": "drawer",
  "density": "comfy",
  "grain": true,
  "watermark": true,
  "accent": "#c8201f"
} /*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [view, setView] = useState('landing'); // landing | menu
  const [stateCode, setStateCode] = useState(null);
  const [selected, setSelected] = useState(null); // product or null
  const [unlockedToken, setUnlockedToken] = useState(
    VALID_TOKENS.has((localStorage.getItem('tswToken') || '').toUpperCase()) ? localStorage.getItem('tswToken') : null
  );
  const unlocked = !!unlockedToken;

  // Filters
  const [q, setQ] = useState('');
  const [catFilter, setCatFilter] = useState('all');
  const [statusFilter, setStatusFilter] = useState('all');
  const [strainFilter, setStrainFilter] = useState('all');
  const [thcRange, setThcRange] = useState(0);

  // Live data: pulse a random row periodically to simulate inventory updates
  const [pulseId, setPulseId] = useState(null);
  // Initial ticker pings — placeholder copy. Scrubbed 2026-05-14 so
  // nobody sees a fake "real" product name in the live feed. The
  // periodic restock-pulse picks names from PRODUCTS (also scrubbed),
  // so within ~9s the feed fills with Placeholder NN entries naturally.
  const [tickerLog, setTickerLog] = useState([
  { at: '2m', msg: 'Placeholder 02 · restocked' },
  { at: '7m', msg: 'Placeholder 08 · restocked' },
  { at: '14m', msg: 'Placeholder 03 · marked low' }]
  );

  useEffect(() => {
    if (view !== 'menu') return;
    const interval = setInterval(() => {
      const live = PRODUCTS.filter((p) => p.status !== 'soon' && p.state === stateCode);
      if (!live.length) return;
      const pick = live[Math.floor(Math.random() * live.length)];
      setPulseId(pick.id);
      setTickerLog((prev) => [{ at: 'now', msg: `${pick.name} · inventory ping` }, ...prev].slice(0, 6));
      setTimeout(() => setPulseId(null), 2400);
    }, 9000);
    return () => clearInterval(interval);
  }, [view, stateCode]);

  // Persisted state
  useEffect(() => {
    const s = localStorage.getItem('tswStateCode');
    if (s && STATES.find((x) => x.code === s && x.status === 'live')) {
      setStateCode(s);
      setView('menu');
    }
  }, []);

  function pickState(s) {
    if (s.status !== 'live') {
      alert(`${s.name} — request-access form goes here.`);
      return;
    }
    setStateCode(s.code);
    setView('menu');
    setSelected(null);
    setCatFilter('all');setStatusFilter('all');setStrainFilter('all');setThcRange(0);setQ('');
    localStorage.setItem('tswStateCode', s.code);
    window.scrollTo({ top: 0, behavior: 'instant' });
  }

  function goLanding() {
    setView('landing');
    setStateCode(null);
    setSelected(null);
    localStorage.removeItem('tswStateCode');
    window.scrollTo({ top: 0, behavior: 'instant' });
  }

  function onUnlock(tok) {
    localStorage.setItem('tswToken', tok);
    setUnlockedToken(tok);
  }
  function onLock() {
    localStorage.removeItem('tswToken');
    setUnlockedToken(null);
  }

  // Filtered products for current state
  const stateProducts = useMemo(
    () => PRODUCTS.filter((p) => p.state === stateCode),
    [stateCode]
  );
  const filtered = useMemo(() => {
    return stateProducts.filter((p) => {
      if (catFilter !== 'all' && p.cat !== catFilter) return false;
      if (statusFilter !== 'all' && p.status !== statusFilter) return false;
      if (strainFilter !== 'all' && p.strain !== strainFilter) return false;
      const thc = typeof p.thc === 'number' ? p.thc : 0;
      if (thcRange > 0 && thc < thcRange) return false;
      if (q) {
        const t = (p.name + ' ' + p.notes + ' ' + p.format + ' ' + p.strain).toLowerCase();
        if (!t.includes(q.toLowerCase())) return false;
      }
      return true;
    });
  }, [stateProducts, catFilter, statusFilter, strainFilter, thcRange, q]);

  // Augment products with live pulse
  const filteredLive = useMemo(() => {
    return filtered.map((p) => p.id === pulseId ? { ...p, flag: 'restocked' } : p);
  }, [filtered, pulseId]);

  // Open product (inline vs drawer vs modal)
  function onOpen(p) {setSelected(p);}
  function onClose() {setSelected(null);}

  // Apply background class to body
  useEffect(() => {
    document.body.dataset.bg = t.background;
    document.body.dataset.grain = t.grain ? 'on' : 'off';
    document.body.dataset.watermark = t.watermark ? 'on' : 'off';
    document.body.dataset.density = t.density;
    document.documentElement.style.setProperty('--accent', t.accent);
  }, [t.background, t.grain, t.watermark, t.density, t.accent]);

  const inlineSelected = t.rowExpand === 'inline' ? selected : null;
  const drawerSelected = t.rowExpand === 'drawer' ? selected : null;
  const modalSelected = t.rowExpand === 'modal' ? selected : null;

  return (
    <div className="app">
      <NavBar
        onBrand={goLanding}
        onLanding={goLanding}
        view={view}
        stateCode={stateCode}
        unlocked={unlocked}
        onLock={onLock} />
      

      <main className="main">
        {view === 'landing' &&
        <Landing onPick={pickState} unlocked={unlocked} onUnlock={onUnlock} onLock={onLock} />
        }

        {view === 'menu' && stateCode &&
        <MenuView
          stateCode={stateCode}
          products={filteredLive}
          allProducts={stateProducts}
          unlocked={unlocked}
          q={q} setQ={setQ}
          catFilter={catFilter} setCatFilter={setCatFilter}
          statusFilter={statusFilter} setStatusFilter={setStatusFilter}
          strainFilter={strainFilter} setStrainFilter={setStrainFilter}
          thcRange={thcRange} setThcRange={setThcRange}
          layout={t.menuLayout}
          tickerLog={tickerLog}
          onOpen={onOpen}
          onUnlock={onUnlock}
          inlineSelected={inlineSelected}
          onCloseInline={onClose} />

        }
      </main>

      {drawerSelected && <DrawerDetail p={drawerSelected} unlocked={unlocked} onClose={onClose} />}
      {modalSelected && <ModalDetail p={modalSelected} unlocked={unlocked} onClose={onClose} />}

      <TweaksPanel>
        <TweakSection label="Background" />
        <TweakRadio label="Mood" value={t.background}
        options={[
        { value: 'conservative', label: 'Clean' },
        { value: 'balanced', label: 'Editorial' },
        { value: 'bold', label: 'Bold' }]
        }
        onChange={(v) => setTweak('background', v)} />
        <TweakToggle label="Film grain" value={t.grain} onChange={(v) => setTweak('grain', v)} />
        <TweakToggle label="Watermark" value={t.watermark} onChange={(v) => setTweak('watermark', v)} />
        <TweakColor label="Accent red" value={t.accent}
        options={['#c8201f', '#ff3a3a', '#a13a2a', '#e85a3a']}
        onChange={(v) => setTweak('accent', v)} />

        <TweakSection label="Menu layout" />
        <TweakRadio label="Inside a state" value={t.menuLayout}
        options={[
        { value: 'sidebar', label: 'Sidebar' },
        { value: 'hybrid', label: 'Cards' },
        { value: 'magazine', label: 'Editorial' }]
        }
        onChange={(v) => setTweak('menuLayout', v)} />

        <TweakSection label="Row click" />
        <TweakRadio label="Opens in" value={t.rowExpand}
        options={[
        { value: 'inline', label: 'Inline' },
        { value: 'drawer', label: 'Drawer' },
        { value: 'modal', label: 'Modal' }]
        }
        onChange={(v) => setTweak('rowExpand', v)} />

        <TweakSection label="Density" />
        <TweakRadio label="Spacing" value={t.density}
        options={[
        { value: 'compact', label: 'Compact' },
        { value: 'comfy', label: 'Comfy' }]
        }
        onChange={(v) => setTweak('density', v)} />
      </TweaksPanel>
    </div>);

}

function NavBar({ onBrand, view, stateCode, unlocked, onLock }) {
  const st = stateCode ? STATES.find((s) => s.code === stateCode) : null;
  return (
    <header className="navbar">
      <button className="brand" onClick={onBrand}>
        <span className="brand-seal">
          <img src="assets/tsw-logo.svg" alt="Top Secret Workshops" className="brand-seal-img" />
        </span>
        <div className="brand-text">
          <span className="brand-eyebrow">Wholesale Menu</span>
          <strong>Top Secret Workshops</strong>
        </div>
      </button>
      <div className="nav-right">
        <div className="nav-status">
          <span className={`nav-dot ${unlocked ? 'on' : 'off'}`}></span>
          <span className="t-mono">
            {view === 'landing' ?
            'Public catalog' :
            `${st?.name || ''} · ${unlocked ? 'prices unlocked' : 'prices locked'}`}
          </span>
        </div>
        {view === 'menu' &&
        <button className="btn-ghost btn-sm" onClick={onBrand}>← Markets</button>
        }
        {unlocked && <button className="btn-ghost btn-sm" onClick={onLock}>Lock prices</button>}
      </div>
    </header>);

}

function MenuView({
  stateCode, products, allProducts, unlocked, q, setQ,
  catFilter, setCatFilter, statusFilter, setStatusFilter,
  strainFilter, setStrainFilter, thcRange, setThcRange,
  layout, tickerLog, onOpen, onUnlock,
  inlineSelected, onCloseInline
}) {
  const st = STATES.find((s) => s.code === stateCode);
  const avail = allProducts.filter((p) => p.status === 'available').length;
  const low = allProducts.filter((p) => p.status === 'low').length;
  const soon = allProducts.filter((p) => p.status === 'soon').length;
  const out = allProducts.filter((p) => p.status === 'out').length;

  return (
    <div className="menu-view">
      <section className="menu-hero">
        <div className="menu-hero-l">
          <div className="menu-hero-crumbs">
            <span className="num">§01</span>
            <span>Market</span>
            <span className="slash">/</span>
            <span className="accent">{st.name}</span>
          </div>
          <h1 className="display display-red">
            <span className="display-line">{st.name}</span>
          </h1>
          <p className="lede">
            Public specs, private pricing. {avail} SKUs in stock, {low} running low, {soon} on deck.
            Live from the inventory tracker — restocks pulse in real time.
          </p>
          <div className="hero-stats">
            <div><b>{allProducts.length}</b><small>state SKUs</small></div>
            <div><b style={{ color: STATUS_META.available.tone }}>{avail}</b><small>in stock</small></div>
            <div><b style={{ color: STATUS_META.low.tone }}>{low}</b><small>low</small></div>
            <div><b style={{ color: STATUS_META.soon.tone }}>{soon}</b><small>coming</small></div>
            <div><b style={{ color: STATUS_META.out.tone }}>{out}</b><small>out</small></div>
          </div>
        </div>
        <div className="menu-hero-r">
          <div className="ticker">
            <div className="ticker-head">
              <span className="ticker-led"></span>
              <span className="t-mono">Live · Inventory feed</span>
            </div>
            <ul>
              {tickerLog.map((t, i) =>
              <li key={i}>
                  <span className="ticker-at t-mono">{t.at}</span>
                  <span>{t.msg}</span>
                </li>
              )}
            </ul>
          </div>
        </div>
      </section>

      <FilterBar
        q={q} setQ={setQ}
        catFilter={catFilter} setCatFilter={setCatFilter}
        statusFilter={statusFilter} setStatusFilter={setStatusFilter}
        unlocked={unlocked} />
      

      {layout === 'sidebar' &&
      <SidebarLayout products={products} catFilter={catFilter} setCatFilter={setCatFilter}
      unlocked={unlocked} onOpen={onOpen} />
      }
      {layout === 'hybrid' &&
      <HybridLayout products={products} catFilter={catFilter} setCatFilter={setCatFilter}
      unlocked={unlocked} onOpen={onOpen} />
      }
      {layout === 'magazine' &&
      <MagazineLayout products={products} catFilter={catFilter} setCatFilter={setCatFilter}
      unlocked={unlocked} onOpen={onOpen} />
      }

      {inlineSelected && <InlineDetail p={inlineSelected} unlocked={unlocked} onClose={onCloseInline} />}
    </div>);

}

Object.assign(window, { App, NavBar, MenuView });

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