// MerchShop.jsx — full merch catalog with terminal-style filters
const MerchShop = ({ onOpen, onAdd, initialLine, user }) => {
  const [products, setProducts] = React.useState([]);

  React.useEffect(() => {
    if (window.OBC_API && window.OBC_API.getMerchProducts) {
      window.OBC_API.getMerchProducts().then(setProducts);
    } else {
      setProducts(window.OBC_PRODUCTS_MERCH || []);
    }
  }, []);

  const lines = React.useMemo(() => {
    if (window.OBC_GET_MERCH_LINES) return window.OBC_GET_MERCH_LINES(products);
    const seen = new Map();
    products.forEach((p) => {
      if (!seen.has(p.line)) seen.set(p.line, { id: p.line, label: p.line.toUpperCase(), color: p.accent || '#00FF41', sub: p.line });
    });
    return Array.from(seen.values());
  }, [products]);

  const allTypes = React.useMemo(() => {
    const s = new Set();
    products.forEach((p) => { if (p.type) s.add(p.type); });
    return Array.from(s);
  }, [products]);

  const [filterLines, setFilterLines] = React.useState(() => initialLine ? new Set([initialLine]) : new Set());
  const [filterTypes, setFilterTypes] = React.useState(new Set());
  const [sort, setSort] = React.useState('default');
  const [query, setQuery] = React.useState('');
  const [showLockedOnly, setShowLockedOnly] = React.useState(false);

  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;
  };

  const spend = (user && user.tierData && user.tierData.lifetime_spend) || 0;
  const helpers = window.OBC_TIER_HELPERS || {};

  const filtered = React.useMemo(() => {
    let out = products.filter((p) => {
      if (filterLines.size > 0 && !filterLines.has(p.line)) return false;
      if (filterTypes.size > 0 && !filterTypes.has(p.type)) return false;
      if (showLockedOnly) {
        const isLocked = p.minTier != null && helpers.canPurchaseMerch && !helpers.canPurchaseMerch(spend, p.minTier);
        if (isLocked) return false;
      }
      if (query) {
        const q = query.toLowerCase();
        const hay = [p.name, p.type, p.material, (p.features || []).join(' ')].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 === 'name') out = [...out].sort((a, b) => a.name.localeCompare(b.name));
    return out;
  }, [products, filterLines, filterTypes, sort, query, showLockedOnly, spend]);

  const clearAll = () => { setFilterLines(new Set()); setFilterTypes(new Set()); setSort('default'); setQuery(''); setShowLockedOnly(false); };
  const activeCount = filterLines.size + filterTypes.size + (query ? 1 : 0) + (showLockedOnly ? 1 : 0);

  const lineFlag = filterLines.size > 0 ? `--line={${Array.from(filterLines).join(',')}}` : null;
  const typeFlag = filterTypes.size > 0 ? `--type={${Array.from(filterTypes).join(',')}}` : null;
  const cmd = ['./merch',
    lineFlag,
    typeFlag,
    query ? `--grep="${query}"` : null,
    sort !== 'default' ? `--sort=${sort}` : null,
    showLockedOnly ? '--unlocked-only' : 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 }}>{'>'} merch</h2>
          <span style={{ fontSize: 13, color: '#BFBFBF', letterSpacing: '0.2em' }}>
            {filtered.length} / {products.length} ITEMS · {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' }}>
          <MerchFilterGroup label="// SEARCH">
            <div style={{ position: 'relative' }}>
              <span style={{ position: 'absolute', left: 10, top: 10, color: '#00FF41', fontSize: 15 }}>{'>'}</span>
              <input
                value={query}
                onChange={(e) => setQuery(e.target.value)}
                placeholder="grep name, material..."
                style={{
                  width: '100%', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.28)',
                  color: '#FFF', fontFamily: 'inherit', fontSize: 15, padding: '10px 12px 10px 28px', 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>
          </MerchFilterGroup>

          <MerchFilterGroup label="// LINE — multi-select">
            <MerchChip label="ALL" active={filterLines.size === 0} onClick={() => setFilterLines(new Set())} count={products.length} />
            {lines.map((l) => (
              <MerchChip 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} />
            ))}
          </MerchFilterGroup>

          <MerchFilterGroup label="// TYPE — multi-select">
            <MerchChip label="ALL TYPES" active={filterTypes.size === 0} onClick={() => setFilterTypes(new Set())} />
            {allTypes.map((t) => (
              <MerchChip key={t} label={t} active={filterTypes.has(t)} onClick={() => setFilterTypes(toggle(filterTypes, t))} count={products.filter((p) => p.type === t).length} />
            ))}
          </MerchFilterGroup>

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

          <MerchFilterGroup label="// TIER ACCESS">
            <MerchChip label="SHOW ALL" active={!showLockedOnly} onClick={() => setShowLockedOnly(false)} />
            <MerchChip label="SHOW UNLOCKED ONLY" active={showLockedOnly} onClick={() => setShowLockedOnly(true)} />
          </MerchFilterGroup>
        </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) => (<MerchCard key={p.id} p={p} onOpen={onOpen} onAdd={onAdd} user={user} />))}
                  </div>
                </div>
              );
            })
          ) : (
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(310px, 1fr))', gap: 16 }}>
              {filtered.map((p) => (<MerchCard key={p.id} p={p} onOpen={onOpen} onAdd={onAdd} user={user} />))}
            </div>
          )}
        </div>
      </div>
    </section>
  );
};

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

const MerchChip = ({ 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: 13, 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.MerchShop = MerchShop;
