// Shop.jsx — full catalog with terminal-style filters
const Shop = ({ onOpen, initialLine }) => {
  const [products, setProducts] = React.useState([]);
  const lines = window.OBC_LINES || [];

  React.useEffect(() => { window.OBC_API.getAllProducts().then(setProducts); }, []);

  const [filterLines, setFilterLines] = React.useState(() => initialLine ? new Set([initialLine]) : new Set());
  const [filterRoasts, setFilterRoasts] = React.useState(new Set());
  const [minStrength, setMinStrength] = React.useState(0);
  const [sort, setSort] = React.useState('default');
  const [query, setQuery] = React.useState('');

  // When the user clicks a footer "shop by line" link while on /shop, the route doesn't change
  // but the initialLine prop does — sync the filter set when it changes.
  React.useEffect(() => {
    if (initialLine) setFilterLines(new Set([initialLine]));
  }, [initialLine]);

  const toggle = (set, val) => {
    const next = new Set(set);
    if (next.has(val)) next.delete(val); else next.add(val);
    return next;
  };

  // Build roast filter options dynamically from data
  const allRoasts = React.useMemo(() => {
    const buckets = new Set();
    products.forEach((p) => {
      const r = p.roast.toLowerCase();
      if (r.includes('decaf')) buckets.add('decaf');
      else if (r.includes('extra dark') || r.includes('ultra dark')) buckets.add('extra-dark');
      else if (r.includes('dark') || r.includes('espresso')) buckets.add('dark');
      else if (r.includes('medium-dark')) buckets.add('medium-dark');
      else if (r.includes('light')) buckets.add('light');
      else if (r.includes('medium')) buckets.add('medium');
      else buckets.add('blend');
    });
    return Array.from(buckets);
  }, [products]);

  const roastLabel = (id) => ({
    'all': 'ALL ROASTS', 'light': 'LIGHT', 'medium': 'MEDIUM', 'medium-dark': 'MEDIUM-DARK',
    'dark': 'DARK', 'extra-dark': 'EXTRA DARK', 'decaf': 'DECAF', 'blend': 'BLEND',
  }[id] || id.toUpperCase());

  const matchesRoast = (p) => {
    if (filterRoasts.size === 0) return true;
    const r = p.roast.toLowerCase();
    const tags = new Set();
    if (r.includes('decaf')) tags.add('decaf');
    if (r.includes('extra dark') || r.includes('ultra dark')) tags.add('extra-dark');
    else if (r.includes('medium-dark')) tags.add('medium-dark');
    else if ((r.includes('dark') || r.includes('espresso')) && !r.includes('medium')) tags.add('dark');
    if (r.includes('light')) tags.add('light');
    if (r.includes('medium') && !r.includes('medium-dark')) tags.add('medium');
    if (r.includes('blend') || r.includes('sampler') || r.includes('subscription') || r.includes('limited release') || r.includes('mystery')) tags.add('blend');
    for (const f of filterRoasts) if (tags.has(f)) return true;
    return false;
  };

  const filtered = React.useMemo(() => {
    let out = products.filter((p) => {
      if (filterLines.size > 0 && !filterLines.has(p.line)) return false;
      if (!matchesRoast(p)) return false;
      if (p.strength < minStrength) return false;
      if (query) {
        const q = query.toLowerCase();
        const hay = [p.name, p.origin, p.notes.join(' '), p.roast].join(' ').toLowerCase();
        if (!hay.includes(q)) return false;
      }
      return true;
    });
    if (sort === 'price-asc') out = [...out].sort((a,b) => a.price - b.price);
    else if (sort === 'price-desc') out = [...out].sort((a,b) => b.price - a.price);
    else if (sort === 'strength-desc') out = [...out].sort((a,b) => b.strength - a.strength);
    else if (sort === 'name') out = [...out].sort((a,b) => a.name.localeCompare(b.name));
    return out;
  }, [products, filterLines, filterRoasts, minStrength, sort, query]);

  const clearAll = () => { setFilterLines(new Set()); setFilterRoasts(new Set()); setMinStrength(0); setSort('default'); setQuery(''); };
  const activeCount = filterLines.size + filterRoasts.size + (minStrength > 0 ? 1 : 0) + (query ? 1 : 0);

  // Build the active filter command line for show
  const lineFlag  = filterLines.size > 0  ? `--line={${Array.from(filterLines).join(',')}}` : null;
  const roastFlag = filterRoasts.size > 0 ? `--roast={${Array.from(filterRoasts).join(',')}}` : null;
  const cmd = ['./shop',
    lineFlag,
    roastFlag,
    minStrength > 0 ? `--strength>=${minStrength}` : null,
    query ? `--grep="${query}"` : null,
    sort !== 'default' ? `--sort=${sort}` : null,
  ].filter(Boolean).join(' ');

  return (
    <section style={{ padding: '40px 24px 80px', maxWidth: 1480, margin: '0 auto' }}>
      <div style={{ marginBottom: 18 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, flexWrap: 'wrap' }}>
          <h2 style={{ fontSize: 36, letterSpacing: '0.04em', textTransform: 'uppercase', fontWeight: 800, color: '#FFF', margin: 0 }}>{'>'} shop</h2>
          <span style={{ fontSize: 13, color: '#BFBFBF', letterSpacing: '0.2em' }}>
            {filtered.length} / {products.length} SKUs · {activeCount} FILTERS
          </span>
          {activeCount > 0 && (
            <button onClick={clearAll} style={{ marginLeft: 'auto', background: 'transparent', border: '1px solid #FF3344', color: '#FF3344', padding: '6px 12px', fontFamily: 'inherit', fontSize: 11, letterSpacing: '0.15em', cursor: 'pointer', borderRadius: 2 }}>
              [ X ] CLEAR FILTERS
            </button>
          )}
        </div>
        <div style={{ marginTop: 12, padding: '12px 16px', background: 'rgba(0,255,65,0.05)', border: '1px solid rgba(0,255,65,0.25)', color: '#00FF41', fontSize: 13, letterSpacing: '0.04em' }}>
          $ {cmd}
          <span style={{ background: '#00FF41', color: '#000', marginLeft: 6, padding: '0 4px' }}>_</span>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '240px 1fr', gap: 28, marginTop: 28 }}>
        {/* ============================== SIDEBAR FILTERS ============================== */}
        <aside style={{ position: 'sticky', top: 120, alignSelf: 'start', maxHeight: 'calc(100vh - 140px)', overflow: 'auto' }}>
          <FilterGroup label="// SEARCH">
            <div style={{ position: 'relative' }}>
              <span style={{ position: 'absolute', left: 10, top: 10, color: '#00FF41', fontSize: 13 }}>{'>'}</span>
              <input
                value={query}
                onChange={(e) => setQuery(e.target.value)}
                placeholder="grep notes, origin..."
                style={{
                  width: '100%', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.28)',
                  color: '#FFF', fontFamily: 'inherit', fontSize: 13, padding: '8px 10px 8px 26px', borderRadius: 2,
                }}
                onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
                onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
              />
            </div>
          </FilterGroup>

          <FilterGroup label="// LINE — multi-select">
            <Chip label="ALL" active={filterLines.size === 0} onClick={() => setFilterLines(new Set())} count={products.length} />
            {lines.map((l) => (
              <Chip key={l.id} label={l.label} accent={l.color} active={filterLines.has(l.id)} onClick={() => setFilterLines(toggle(filterLines, l.id))} count={products.filter((p) => p.line === l.id).length} />
            ))}
          </FilterGroup>

          <FilterGroup label="// ROAST — multi-select">
            <Chip label="ALL ROASTS" active={filterRoasts.size === 0} onClick={() => setFilterRoasts(new Set())} />
            {['light','medium','medium-dark','dark','extra-dark','blend','decaf'].filter((r) => allRoasts.includes(r)).map((r) => (
              <Chip key={r} label={roastLabel(r)} active={filterRoasts.has(r)} onClick={() => setFilterRoasts(toggle(filterRoasts, r))} />
            ))}
          </FilterGroup>

          <FilterGroup label="// STRENGTH ⚡ MIN">
            <div style={{ display: 'flex', gap: 4 }}>
              {[0,1,2,3,4,5].map((n) => (
                <button key={n} onClick={() => setMinStrength(n)} style={{
                  flex: 1, padding: '8px 0', background: minStrength === n ? '#00FF41' : 'transparent',
                  color: minStrength === n ? '#000' : '#E0E0E0', border: `1px solid ${minStrength === n ? '#00FF41' : 'rgba(255,255,255,0.28)'}`,
                  fontFamily: 'inherit', fontSize: 12, fontWeight: 700, cursor: 'pointer', borderRadius: 2,
                }}>{n === 0 ? 'ANY' : `≥${n}`}</button>
              ))}
            </div>
          </FilterGroup>

          <FilterGroup label="// SORT">
            {[
              { id:'default', label:'DEFAULT (BY LINE)' },
              { id:'name', label:'A → Z' },
              { id:'price-asc', label:'PRICE ↑' },
              { id:'price-desc', label:'PRICE ↓' },
              { id:'strength-desc', label:'STRENGTH ↓' },
            ].map((s) => (
              <Chip key={s.id} label={s.label} active={sort === s.id} onClick={() => setSort(s.id)} />
            ))}
          </FilterGroup>
        </aside>

        {/* ============================== RESULTS ============================== */}
        <div>
          {filtered.length === 0 ? (
            <div style={{ padding: '64px 24px', border: '1px dashed rgba(255,255,255,0.32)', textAlign: 'center', color: '#BFBFBF', fontSize: 14, lineHeight: 1.8 }}>
              <div style={{ color: '#FF3344', fontSize: 18, letterSpacing: '0.2em', marginBottom: 14 }}>{'>'} no results</div>
              <div>$ grep "{query || '*'}" returned 0 matches.</div>
              <div>// loosen filters or <span style={{ color: '#00FF41', cursor: 'pointer' }} onClick={clearAll}>./reset</span>.</div>
            </div>
          ) : sort === 'default' ? (
            lines.map((line) => {
              const items = filtered.filter((p) => p.line === line.id);
              if (items.length === 0) return null;
              return (
                <div key={line.id} style={{ marginBottom: 48 }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16, paddingBottom: 10, borderBottom: `1px solid ${line.color}` }}>
                    <span style={{ fontSize: 13, fontWeight: 800, letterSpacing: '0.18em', color: line.color, textTransform: 'uppercase' }}>{line.label}</span>
                    <span style={{ fontSize: 10, letterSpacing: '0.25em', color: '#9A9A9A' }}>// {line.sub}</span>
                    <span style={{ marginLeft: 'auto', fontSize: 11, color: '#BFBFBF', letterSpacing: '0.15em' }}>{items.length} ITEMS</span>
                  </div>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(310px, 1fr))', gap: 16 }}>
                    {items.map((p) => (<window.ProductCard key={p.id} p={p} onOpen={onOpen} />))}
                  </div>
                </div>
              );
            })
          ) : (
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(310px, 1fr))', gap: 16 }}>
              {filtered.map((p) => (<window.ProductCard key={p.id} p={p} onOpen={onOpen} />))}
            </div>
          )}
        </div>
      </div>
    </section>
  );
};

const FilterGroup = ({ label, children }) => (
  <div style={{ marginBottom: 24 }}>
    <div style={{ fontSize: 11, letterSpacing: '0.22em', color: '#E0E0E0', fontWeight: 700, marginBottom: 10 }}>{label}</div>
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>{children}</div>
  </div>
);

const Chip = ({ label, accent, active, onClick, count }) => (
  <button onClick={onClick} style={{
    display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px',
    background: active ? (accent || '#00FF41') : 'transparent',
    color: active ? '#000' : (accent || '#E0E0E0'),
    border: `1px solid ${active ? (accent || '#00FF41') : 'rgba(255,255,255,0.22)'}`,
    fontFamily: 'inherit', fontSize: 11, fontWeight: 700, letterSpacing: '0.12em',
    cursor: 'pointer', borderRadius: 2, textAlign: 'left',
  }}>
    <span style={{ flex: 1 }}>{active ? '[*] ' : '[ ] '}{label}</span>
    {typeof count === 'number' && <span style={{ opacity: 0.7, fontSize: 10 }}>{String(count).padStart(2,'0')}</span>}
  </button>
);

window.Shop = Shop;
