/* GarageWiz — Admin: Suppliers, Parts, Users, Activity */
(function () {
  const e = React.createElement;
  const { useState, useEffect } = React;
  const Icon = window.Icon, Btn = window.Btn, Badge = window.Badge, Toggle = window.Toggle, Input = window.Input,
        Field = window.Field, SectionTitle = window.SectionTitle, Modal = window.Modal;

  /* ===================== SUPPLIERS ===================== */
  function AdminSuppliers() {
    const app = window.useApp();
    return e('div', null,
      e(SectionTitle, { eyebrow: 'Admin', title: 'Suppliers', sub: 'Door models are linked to a supplier. Disabling one hides its models.',
        right: e(Btn, { variant: 'primary', icon: 'plus', onClick: () => { GW.suppliers.push({ id: 's' + Date.now(), name: 'New supplier', enabled: true, models: [] }); app.bump(); } }, 'Add supplier') }),
      e('div', { className: 'mfr-grid', style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(320px,1fr))', gap: 18 } },
        GW.suppliers.map(sup => e('div', { key: sup.id, className: 'card', style: { padding: 22, opacity: sup.enabled ? 1 : .6 } },
          e('div', { style: { display: 'flex', alignItems: 'center', gap: 14, marginBottom: 14 } },
            e('div', { style: { width: 48, height: 48, borderRadius: 13, background: 'var(--field)', color: 'var(--teal)', display: 'grid', placeItems: 'center', flexShrink: 0 } }, e(Icon, { name: 'truck', size: 24 })),
            e('div', { className: 'grow' },
              e('input', { value: sup.name, onChange: ev => { sup.name = ev.target.value; app.bump(); }, style: { border: 'none', background: 'transparent', fontFamily: 'var(--display)', fontWeight: 600, fontSize: 18, width: '100%', outline: 'none', color: 'var(--ink)' } }),
              e('div', { className: 'muted', style: { fontSize: 13 } }, 'Models: ' + (sup.models.join(', ') || '—')),
            ),
            e(Toggle, { on: sup.enabled, onChange: v => { sup.enabled = v; app.bump(); }, label: sup.name }),
          ),
          e('div', { style: { display: 'flex', gap: 8, flexWrap: 'wrap' } },
            GW.models.map(m => e('span', { key: m.code, className: 'badge ' + (sup.models.includes(m.code) ? 'badge-good' : 'badge-start') }, m.name)),
          ),
        )),
      ),
    );
  }
  window.AdminSuppliers = AdminSuppliers;

  /* ===================== PARTS ===================== */
  function AdminParts() {
    const app = window.useApp();
    const save = () => { GW.saveParts(); app.bump(); };
    return e('div', null,
      e(SectionTitle, { eyebrow: 'Admin', title: 'Parts', sub: 'Add or edit parts any time. Set the cost, then a pricing rule per part — a profit margin %, or a × cost multiplier to sell for more. Customer price updates live and saves instantly.',
        right: e(Btn, { variant: 'primary', icon: 'plus', onClick: () => { GW.parts.push({ id: 'p' + Date.now(), cat: 'Hardware', name: 'New part', desc: '', cost: 0, override: GW.defaultOverride(), enabled: true }); save(); } }, 'Add part') }),
      e('div', { className: 'card', style: { overflow: 'hidden' } },
        e('div', { className: 'table-head-parts' },
          ['Part', 'Category', 'Cost', 'Pricing rule', 'Upsell', 'Customer price'].map((h, i) => e('div', { key: i, style: { textAlign: i === 2 || i === 5 ? 'right' : i === 4 ? 'center' : 'left' } }, h)),
        ),
        GW.parts.map((p, i) => {
          const priced = GW.partPrice(p, app.settings);
          return e('div', { key: p.id, className: 'table-row-parts', style: { opacity: p.enabled ? 1 : .5 } },
          e('div', null,
            e('input', { value: p.name, onChange: ev => { p.name = ev.target.value; save(); }, style: { border: 'none', background: 'transparent', fontWeight: 700, fontSize: 15, width: '100%', outline: 'none', color: 'var(--ink)' } }),
            e('input', { value: p.desc, onChange: ev => { p.desc = ev.target.value; save(); }, placeholder: 'Description', style: { border: 'none', background: 'transparent', fontSize: 13, width: '100%', outline: 'none', color: 'var(--ink-3)' } }),
          ),
          e('div', null, e('input', { value: p.cat, onChange: ev => { p.cat = ev.target.value; save(); }, style: { border: '1px solid var(--line)', borderRadius: 8, padding: '6px 10px', fontSize: 13.5, width: 130, outline: 'none' } })),
          e('div', { style: { textAlign: 'right' } },
            e('div', { style: { position: 'relative', width: 92, marginLeft: 'auto' } },
              e('span', { style: { position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', color: 'var(--ink-3)', fontWeight: 700 } }, '$'),
              e('input', { type: 'number', value: p.cost, onChange: ev => { p.cost = Number(ev.target.value); save(); }, style: { width: '100%', padding: '8px 9px 8px 20px', borderRadius: 8, border: '1.5px solid var(--line-2)', fontWeight: 600, textAlign: 'right', outline: 'none', fontVariantNumeric: 'tabular-nums' } }),
            ),
          ),
          e('div', null,
            e(window.OverrideControl, { value: GW.partOverride(p), settings: app.settings, onChange: ov => { p.override = ov; delete p.margin; save(); } }),
          ),
          e('div', { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 } },
            e(Toggle, { on: !!p.upsell, onChange: v => { p.upsell = v; save(); }, label: 'Upsell ' + p.name }),
            e('div', { style: { fontSize: 10.5, color: 'var(--ink-3)', fontWeight: 600, textAlign: 'center', lineHeight: 1.2 } }, p.upsell ? 'In door flow' : 'Hidden'),
          ),
          e('div', { style: { display: 'flex', alignItems: 'center', gap: 10, justifyContent: 'flex-end' } },
            e('div', { className: 'display num', style: { fontSize: 17, fontWeight: 700, color: 'var(--teal)', fontVariantNumeric: 'tabular-nums' } }, GW.fmt(priced.price)),
            e(Toggle, { on: p.enabled, onChange: v => { p.enabled = v; save(); }, label: p.name }),
            e('button', { onClick: () => { const idx = GW.parts.indexOf(p); GW.parts.splice(idx, 1); save(); }, style: { border: 'none', background: 'var(--danger-bg)', color: 'var(--danger)', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0 } }, e(Icon, { name: 'trash', size: 16 })),
          ),
        );
        }),
      ),
    );
  }
  window.AdminParts = AdminParts;

  /* ===================== BUNDLES ===================== */
  function AdminBundles() {
    const app = window.useApp();
    const save = () => { GW.saveBundles(); app.bump(); };
    const s = app.settings;
    const upd = (patch) => app.setSettings(Object.assign({}, s, patch));
    // all items that can go in a bundle: every add-on + every enabled part
    const addonItems = (GW.addons || []).map(a => ({ id: a.id, name: a.name }));
    const partItems = (GW.parts || []).filter(p => p.enabled !== false).map(p => ({ id: p.id, name: p.name }));
    const allItems = addonItems.concat(partItems);

    const Pill = ({ on, onClick, children }) => e('button', {
      onClick, style: {
        border: '1.5px solid ' + (on ? 'var(--teal)' : 'var(--line-2)'), background: on ? 'var(--teal)' : '#fff',
        color: on ? '#fff' : 'var(--ink-2)', borderRadius: 999, padding: '6px 12px', fontSize: 12.5, fontWeight: 600, cursor: 'pointer',
      },
    }, children);

    return e('div', null,
      e(SectionTitle, { eyebrow: 'Admin', title: 'Bundles & packages', sub: 'Group items into a named package with a discount. When a rep adds the whole set to a quote, the savings apply automatically — a clean way to upsell and raise the average ticket.',
        right: e(Btn, { variant: 'primary', icon: 'plus', onClick: () => { GW.bundles.push({ id: 'b' + Date.now(), name: 'New package', desc: '', items: [], pricing: { mode: 'pctOff', value: 0.10 }, target: 'door', enabled: true }); save(); } }, 'Add bundle') }),

      // ---- automatic rules card ----
      e('div', { className: 'card', style: { padding: 22, marginBottom: 20 } },
        e('div', { style: { fontWeight: 700, fontSize: 15, marginBottom: 4 } }, 'Automatic discount rules'),
        e('div', { className: 'muted', style: { fontSize: 13, marginBottom: 16 } }, 'These apply on top of named packages. Set a value to 0 to turn a rule off.'),
        e('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 16 } },
          e(Field, { label: 'Bundle add-ons threshold', hint: 'Discount kicks in at this many add-ons' },
            e(Input, { type: 'number', value: s.bundleAddonThreshold, onChange: ev => upd({ bundleAddonThreshold: Math.max(0, Number(ev.target.value)) }) })),
          e(Field, { label: '% off bundled add-ons', hint: 'Applied to add-ons over the threshold' },
            e(Input, { type: 'number', value: Math.round((s.bundleAddonPctOff || 0) * 100), onChange: ev => upd({ bundleAddonPctOff: Math.max(0, Number(ev.target.value)) / 100 }) })),
          e(Field, { label: '$ off opener + door', hint: 'Flat discount when an opener is on a door quote' },
            e(Input, { type: 'number', value: s.bundleOpenerOnDoorOff, onChange: ev => upd({ bundleOpenerOnDoorOff: Math.max(0, Number(ev.target.value)) }) })),
        ),
      ),

      // ---- named bundles ----
      e('div', { style: { display: 'flex', flexDirection: 'column', gap: 16 } },
        (GW.bundles || []).map(b => {
          const pv = GW.bundlePreview(b, app.settings);
          const toggleItem = (id) => { const has = b.items.indexOf(id) >= 0; b.items = has ? b.items.filter(x => x !== id) : b.items.concat([id]); save(); };
          return e('div', { key: b.id, className: 'card', style: { padding: 22, opacity: b.enabled === false ? .55 : 1 } },
            e('div', { style: { display: 'flex', gap: 14, alignItems: 'flex-start', marginBottom: 14 } },
              e('div', { className: 'grow' },
                e('input', { value: b.name, onChange: ev => { b.name = ev.target.value; save(); }, style: { border: 'none', background: 'transparent', fontWeight: 700, fontSize: 17, width: '100%', outline: 'none', color: 'var(--ink)', fontFamily: 'var(--display)' } }),
                e('input', { value: b.desc, onChange: ev => { b.desc = ev.target.value; save(); }, placeholder: 'Short sales pitch shown to the customer', style: { border: 'none', background: 'transparent', fontSize: 13, width: '100%', outline: 'none', color: 'var(--ink-3)', marginTop: 2 } }),
              ),
              e(Toggle, { on: b.enabled !== false, onChange: v => { b.enabled = v; save(); }, label: b.name }),
              e('button', { onClick: () => { const i = GW.bundles.indexOf(b); GW.bundles.splice(i, 1); save(); }, style: { border: 'none', background: 'var(--danger-bg)', color: 'var(--danger)', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0 } }, e(Icon, { name: 'trash', size: 16 })),
            ),

            // items
            e('div', { style: { fontSize: 12, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 8 } }, 'Items in this package'),
            e('div', { style: { display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 16 } },
              allItems.map(it => e(Pill, { key: it.id, on: b.items.indexOf(it.id) >= 0, onClick: () => toggleItem(it.id) }, it.name)),
            ),

            // pricing + offered-on + preview
            e('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))', gap: 16, alignItems: 'end' } },
              e(Field, { label: 'Discount type' },
                e(window.Segmented, { value: b.pricing.mode, onChange: m => { b.pricing.mode = m; save(); }, options: [{ value: 'pctOff', label: '% off' }, { value: 'fixed', label: 'Fixed price' }] })),
              e(Field, { label: b.pricing.mode === 'fixed' ? 'Bundle price ($)' : 'Percent off (%)' },
                b.pricing.mode === 'fixed'
                  ? e(Input, { type: 'number', value: b.pricing.value, onChange: ev => { b.pricing.value = Math.max(0, Number(ev.target.value)); save(); } })
                  : e(Input, { type: 'number', value: Math.round((b.pricing.value || 0) * 100), onChange: ev => { b.pricing.value = Math.max(0, Math.min(100, Number(ev.target.value))) / 100; save(); } })),
              e(Field, { label: 'Offered on' },
                e(window.Segmented, { value: b.target, onChange: t => { b.target = t; save(); }, options: [{ value: 'door', label: 'Doors' }, { value: 'opener', label: 'Openers' }, { value: 'parts', label: 'Parts' }, { value: 'any', label: 'Any' }] })),
            ),

            // live preview
            e('div', { style: { display: 'flex', alignItems: 'center', gap: 14, marginTop: 16, padding: '12px 16px', background: 'var(--field)', borderRadius: 12 } },
              e('div', { className: 'grow', style: { fontSize: 13, color: 'var(--ink-2)' } },
                b.items.length ? ('Separately ' + GW.fmt(pv.gross) + ' → bundle ' + GW.fmt(pv.bundlePrice)) : 'Add at least one item to this package.'),
              pv.save > 0 ? e('span', { className: 'badge badge-good', style: { fontSize: 13 } }, 'Customer saves ' + GW.fmt(pv.save)) : null,
            ),
          );
        }),
        (GW.bundles || []).length === 0 ? e('div', { className: 'card', style: { padding: 30, textAlign: 'center', color: 'var(--ink-3)' } }, 'No bundles yet. Add one to start upselling packages.') : null,
      ),
    );
  }
  window.AdminBundles = AdminBundles;

  /* ===================== COUPONS ===================== */
  function AdminCoupons() {
    const app = window.useApp();
    const save = () => { GW.saveCoupons(); app.bump(); };
    return e('div', null,
      e(SectionTitle, { eyebrow: 'Admin', title: 'Coupon codes', sub: 'Create approved discount codes and hand them to reps. A rep types the code on a quote to apply a fixed amount or % off — without the dealer PIN. Every coupon is still capped at the floor, so it can never sell below your minimum.',
        right: e(Btn, { variant: 'primary', icon: 'plus', onClick: () => { GW.coupons.push({ id: 'cp' + Date.now(), code: 'NEWCODE', type: 'amount', value: 50, enabled: true, note: '' }); save(); } }, 'Add coupon') }),
      e('div', { style: { display: 'flex', flexDirection: 'column', gap: 12 } },
        (GW.coupons || []).map(cp => e('div', { key: cp.id, className: 'card', style: { padding: 18, display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap', opacity: cp.enabled ? 1 : .55 } },
          e('div', { style: { width: 46, height: 46, borderRadius: 12, background: 'var(--field)', color: 'var(--teal)', display: 'grid', placeItems: 'center', flexShrink: 0 } }, e(Icon, { name: 'tag', size: 22 })),
          e('div', { style: { minWidth: 150 } },
            e('input', { value: cp.code, onChange: ev => { cp.code = ev.target.value.toUpperCase().replace(/\s+/g, ''); save(); }, style: { border: '1.5px solid var(--line-2)', borderRadius: 8, padding: '8px 10px', fontWeight: 800, letterSpacing: '.05em', fontSize: 15, width: 150, outline: 'none', textTransform: 'uppercase', fontFamily: 'var(--display)' } }),
            e('input', { value: cp.note || '', onChange: ev => { cp.note = ev.target.value; save(); }, placeholder: 'Note (e.g. manager-approved)', style: { border: 'none', background: 'transparent', fontSize: 12, width: 150, outline: 'none', color: 'var(--ink-3)', marginTop: 4 } }),
          ),
          e('div', { style: { minWidth: 180 } },
            e(window.Segmented, { value: cp.type, onChange: v => { cp.type = v; save(); }, options: [{ value: 'amount', label: '$ off' }, { value: 'pct', label: '% off' }] })),
          e('div', { style: { position: 'relative', width: 110 } },
            e('span', { style: { position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', color: 'var(--ink-3)', fontWeight: 700 } }, cp.type === 'pct' ? '%' : '$'),
            e('input', { type: 'number', value: cp.type === 'pct' ? Math.round((cp.value || 0) * 100) : cp.value, onChange: ev => { const n = Math.max(0, Number(ev.target.value)); cp.value = cp.type === 'pct' ? Math.min(100, n) / 100 : n; save(); }, style: { width: '100%', padding: '9px 10px 9px 24px', borderRadius: 8, border: '1.5px solid var(--line-2)', fontWeight: 600, textAlign: 'right', outline: 'none', fontVariantNumeric: 'tabular-nums' } }),
          ),
          e('div', { className: 'grow' }),
          e('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
            e('span', { className: 'muted', style: { fontSize: 12.5 } }, cp.enabled ? 'Active' : 'Off'),
            e(Toggle, { on: cp.enabled, onChange: v => { cp.enabled = v; save(); }, label: cp.code }),
            e('button', { onClick: () => { GW.coupons = GW.coupons.filter(x => x !== cp); save(); }, title: 'Remove', style: { border: 'none', background: 'var(--danger-bg)', color: 'var(--danger)', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0 } }, e(Icon, { name: 'trash', size: 16 })),
          ),
        )),
        (GW.coupons || []).length === 0 ? e('div', { className: 'card', style: { padding: 30, textAlign: 'center', color: 'var(--ink-3)' } }, 'No coupons yet. Add one to let reps apply approved discounts.') : null,
      ),
    );
  }
  window.AdminCoupons = AdminCoupons;

  /* ===================== REVIEW REQUESTS (inbox) ===================== */
  function AdminReviews() {
    const app = window.useApp();
    const list = GW.reviews || [];
    const dismiss = (r) => { GW.reviews = GW.reviews.filter(x => x !== r); GW.saveReviews(); app.bump(); };
    return e('div', null,
      e(SectionTitle, { eyebrow: 'Admin', title: 'Review requests', sub: 'Quotes a rep shared for your review. Open one to see it and use Dealer View to decide what you can do — then call the rep back.' }),
      list.length === 0
        ? e('div', { className: 'card', style: { padding: 40, textAlign: 'center', color: 'var(--ink-3)' } }, e(Icon, { name: 'mail', size: 28, style: { marginBottom: 10 } }), e('div', null, 'No review requests right now.'))
        : e('div', { style: { display: 'flex', flexDirection: 'column', gap: 12 } },
            list.map(r => e('div', { key: r.id, className: 'card', style: { padding: 18, display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap' } },
              e('div', { style: { width: 44, height: 44, borderRadius: 12, background: 'var(--field)', color: 'var(--teal)', display: 'grid', placeItems: 'center', flexShrink: 0 } }, e(Icon, { name: 'door', size: 22 })),
              e('div', { className: 'grow', style: { minWidth: 180 } },
                e('div', { style: { fontWeight: 700, fontSize: 15 } }, (r.customer || 'Customer') + ' · ' + GW.fmt(r.price)),
                e('div', { className: 'muted', style: { fontSize: 12.5 } }, 'From ' + r.rep + ' · ' + new Date(r.ts).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })),
                r.note ? e('div', { style: { fontSize: 13, color: 'var(--ink-2)', marginTop: 4, fontStyle: 'italic' } }, '“' + r.note + '”') : null,
              ),
              e(Btn, { variant: 'primary', size: 'sm', icon: 'arrowR', onClick: () => app.go('#/review/' + r.data) }, 'Open & review'),
              e('button', { onClick: () => dismiss(r), title: 'Dismiss', style: { border: 'none', background: 'var(--field)', color: 'var(--ink-3)', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0 } }, e(Icon, { name: 'close', size: 16 })),
            )),
          ),
    );
  }
  window.AdminReviews = AdminReviews;

  /* ===================== UPGRADES (glass / inserts / add-ons) ===================== */
  function AdminUpgrades() {
    const app = window.useApp();
    const s = app.settings;
    const setIns = (ov) => app.setSettings(Object.assign({}, s, { insertsOverride: ov }));

    const card = (title, sub, children) => e('div', { className: 'card', style: { padding: 22, marginBottom: 18 } },
      e('div', { style: { fontWeight: 700, fontSize: 16, marginBottom: 2 } }, title),
      e('div', { className: 'muted', style: { fontSize: 13, marginBottom: 16 } }, sub),
      children);

    return e('div', null,
      e(SectionTitle, { eyebrow: 'Admin', title: 'Upgrades', sub: 'Set a pricing rule — a margin % or a × cost multiplier — on the optional items a customer can add to a door. Saves instantly.' }),

      // ---- Window glass ----
      card('Window glass', 'Edit your real cost per lite (by panel & door insulation) and set the pricing rule per glass type.',
        e('div', null,
          e('div', { style: { display: 'grid', gridTemplateColumns: '1fr 64px 64px 64px 64px', gap: 8, alignItems: 'center', paddingBottom: 8, fontSize: 11, fontWeight: 800, letterSpacing: '.03em', color: 'var(--ink-3)', textTransform: 'uppercase' } },
            e('div', null, 'Cost / lite'), e('div', { style: { textAlign: 'right' } }, 'Short·Non'), e('div', { style: { textAlign: 'right' } }, 'Short·Ins'), e('div', { style: { textAlign: 'right' } }, 'Long·Non'), e('div', { style: { textAlign: 'right' } }, 'Long·Ins')),
          (GW.glass || []).map(g => {
            g.price = g.price || {};
            const costInp = (cat) => e('div', { style: { position: 'relative' } },
              e('input', { type: 'number', value: g.price[cat] == null ? '' : g.price[cat], onChange: ev => { g.price[cat] = Math.max(0, Number(ev.target.value)); GW.saveGlass(); app.bump(); }, style: { width: '100%', padding: '7px 7px', borderRadius: 7, border: '1.5px solid var(--line-2)', fontWeight: 600, textAlign: 'right', outline: 'none', fontVariantNumeric: 'tabular-nums', fontSize: 13 } }));
            return e('div', { key: g.id, style: { borderTop: '1px solid var(--line)', padding: '12px 0' } },
              e('div', { style: { display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap', marginBottom: 8 } },
                e('div', { className: 'grow', style: { minWidth: 160 } },
                  e('div', { style: { fontWeight: 700, fontSize: 15 } }, g.name),
                  e('div', { className: 'muted', style: { fontSize: 12.5 } }, g.desc),
                ),
                e(window.OverrideControl, { value: g.override || null, settings: s, onChange: ov => { g.override = ov; GW.saveGlass(); app.bump(); } }),
                e('div', { className: 'muted', style: { fontSize: 12 } }, GW.overrideLabel(g.override, s)),
              ),
              e('div', { style: { display: 'grid', gridTemplateColumns: '1fr 64px 64px 64px 64px', gap: 8, alignItems: 'center' } },
                e('div', { className: 'muted', style: { fontSize: 12 } }, 'per lite'),
                costInp('short_unins'), costInp('short_ins'), costInp('long_unins'), costInp('long_ins')),
            );
          }),
        )),

      // ---- Decorative inserts ----
      card('Decorative inserts', 'Set your real cost per door (by width & panel style), and the pricing rule. Inserts only apply when windows are added.',
        e('div', null,
          e('div', { style: { display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap', paddingBottom: 14, borderBottom: '1px solid var(--line)' } },
            e('div', { className: 'grow', style: { minWidth: 180 } }, e('div', { style: { fontWeight: 700, fontSize: 15 } }, 'Pricing rule'), e('div', { className: 'muted', style: { fontSize: 12.5 } }, GW.overrideLabel(s.insertsOverride, s))),
            e(window.OverrideControl, { value: s.insertsOverride || null, settings: s, onChange: setIns })),
          e('div', { style: { fontSize: 12, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--ink-3)', margin: '14px 0 10px' } }, 'Your cost per door'),
          e('div', { style: { display: 'grid', gridTemplateColumns: '70px 1fr 1fr', gap: 10, alignItems: 'center', maxWidth: 420 } },
            e('div', null), e('div', { className: 'muted', style: { fontSize: 12, fontWeight: 700 } }, 'Short panel'), e('div', { className: 'muted', style: { fontSize: 12, fontWeight: 700 } }, 'Long panel'),
            GW.widths.map(w => {
              const row = GW.inserts[w.ft] || (GW.inserts[w.ft] = { short: 0, long: 0 });
              const inp = (grp) => e('div', { style: { position: 'relative' } },
                e('span', { style: { position: 'absolute', left: 9, top: '50%', transform: 'translateY(-50%)', color: 'var(--ink-3)', fontWeight: 700, fontSize: 13 } }, '$'),
                e('input', { type: 'number', value: row[grp] == null ? '' : row[grp], onChange: ev => { row[grp] = Math.max(0, Number(ev.target.value)); GW.saveInserts(); app.bump(); }, style: { width: '100%', padding: '7px 8px 7px 19px', borderRadius: 8, border: '1.5px solid var(--line-2)', fontWeight: 600, textAlign: 'right', outline: 'none', fontVariantNumeric: 'tabular-nums' } }));
              return [
                e('div', { key: 'l' + w.ft, style: { fontWeight: 700, fontSize: 13.5 } }, w.ft + ' ft'),
                e('div', { key: 's' + w.ft }, inp('short')),
                e('div', { key: 'g' + w.ft }, inp('long')),
              ];
            }),
          ),
        )),

      // ---- Add-ons ----
      card('Add-ons & accessories', 'Edit the cost and pricing rule for each add-on. The customer price updates live.',
        (GW.addons || []).map(a => {
          const priced = GW.partPrice({ cost: a.sell, override: a.override }, s);
          return e('div', { key: a.id, style: { display: 'flex', alignItems: 'center', gap: 14, padding: '12px 0', borderTop: '1px solid var(--line)', flexWrap: 'wrap' } },
            e('div', { className: 'grow', style: { minWidth: 160 } },
              e('input', { value: a.name, onChange: ev => { a.name = ev.target.value; GW.saveAddons(); app.bump(); }, style: { border: 'none', background: 'transparent', fontWeight: 700, fontSize: 15, width: '100%', outline: 'none', color: 'var(--ink)' } }),
              e('input', { value: a.desc, onChange: ev => { a.desc = ev.target.value; GW.saveAddons(); app.bump(); }, placeholder: 'Description', style: { border: 'none', background: 'transparent', fontSize: 12.5, width: '100%', outline: 'none', color: 'var(--ink-3)' } }),
            ),
            e('div', { style: { position: 'relative', width: 92 } },
              e('span', { style: { position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', color: 'var(--ink-3)', fontWeight: 700 } }, '$'),
              e('input', { type: 'number', value: a.sell, onChange: ev => { a.sell = Number(ev.target.value); GW.saveAddons(); app.bump(); }, style: { width: '100%', padding: '8px 9px 8px 20px', borderRadius: 8, border: '1.5px solid var(--line-2)', fontWeight: 600, textAlign: 'right', outline: 'none', fontVariantNumeric: 'tabular-nums' } }),
            ),
            e(window.OverrideControl, { value: a.override || null, settings: s, onChange: ov => { a.override = ov; GW.saveAddons(); app.bump(); } }),
            e('div', { className: 'display num', style: { fontSize: 16, fontWeight: 700, color: 'var(--teal)', minWidth: 70, textAlign: 'right' } }, GW.fmt(priced.price)),
          );
        })),
    );
  }
  window.AdminUpgrades = AdminUpgrades;

  /* ===================== USERS ===================== */
  function AdminUsers() {
    const app = window.useApp();
    const [form, setForm] = useState(null); // { id?, name, email, role, isNew, password }
    const [created, setCreated] = useState(null); // { email, password } after add
    const [busy, setBusy] = useState(false);
    const [, force] = useState(0);
    const me = app.user || {};
    const isAdmin = me.role === 'admin';
    const backend = !!(window.GW.db && window.GW.db.configured);

    if (!isAdmin) {
      return e('div', null,
        e(SectionTitle, { eyebrow: 'Admin', title: 'Users' }),
        e('div', { className: 'card', style: { padding: 40, textAlign: 'center', color: 'var(--ink-3)' } },
          e(Icon, { name: 'lock', size: 28, style: { marginBottom: 10 } }),
          e('div', null, 'Only an admin can view or manage users.')));
    }

    const refresh = async () => { if (backend) { try { GW.users = await GW.db.listProfiles(); } catch (e) {} } force(n => n + 1); app.bump(); };

    const saveForm = async () => {
      if (backend) {
        setBusy(true);
        if (form.isNew) {
          if (!form.email || !form.email.trim()) { app.toast('Email is required'); setBusy(false); return; }
          try {
            const res = await GW.db.createUser({ name: form.name, email: form.email.trim(), role: form.role, password: form.password });
            setForm(null); setCreated({ email: res.email, password: res.password, role: res.role }); await refresh();
          } catch (e) { app.toast('Add failed: ' + ((e && e.message) || '')); }
        } else {
          try { await GW.db.updateProfile(form.id, { name: form.name, role: form.role }); app.toast('User updated'); setForm(null); } catch (e) { app.toast('Update failed: ' + ((e && e.message) || '')); }
          await refresh();
        }
        setBusy(false); return;
      }
      if (form.isNew) GW.users.push({ id: 'u' + Date.now(), name: form.name, email: form.email, role: form.role, active: true });
      else { const u = GW.users.find(x => x.id === form.id); if (u) { u.name = form.name; u.email = form.email; u.role = form.role; } }
      GW.saveUsers(); app.bump(); setForm(null);
    };
    const setActive = async (u, val) => {
      if (backend) { try { await GW.db.updateProfile(u.id, { active: val }); } catch (e) { app.toast('Failed'); } await refresh(); }
      else { u.active = val; GW.saveUsers(); app.bump(); }
    };
    const removeUser = (u) => {
      if (backend) { app.toast('Deactivate instead of delete — accounts are managed in Supabase Auth.'); return; }
      if (u.id === me.id) { app.toast("You can't remove your own account."); return; }
      if (!confirm('Remove ' + u.name + '?')) return;
      GW.users = GW.users.filter(x => x !== u); GW.saveUsers(); app.bump();
    };

    return e('div', null,
      e(SectionTitle, { eyebrow: 'System Admin', title: 'Users',
        sub: backend ? 'Add reps directly, or they can sign up on the login screen. Set role and active status here.' : 'Add, edit, or remove reps and admins (local demo data).',
        right: e(Btn, { variant: 'primary', icon: 'plus', onClick: () => setForm({ name: '', email: '', role: 'rep', isNew: true, password: '' }) }, backend ? 'Add rep' : 'Add user') }),
      e('div', { className: 'card', style: { overflow: 'hidden' } },
        e('div', { className: 'table-head-users' }, ['User', 'Role', 'Status', ''].map((h, i) => e('div', { key: i }, h))),
        (GW.users || []).map((u, i) => e('div', { key: u.id, className: 'table-row-users', style: { opacity: u.active ? 1 : .55 } },
          e('div', { style: { display: 'flex', alignItems: 'center', gap: 12 } },
            e('span', { style: { width: 40, height: 40, borderRadius: 999, background: u.role === 'admin' ? 'var(--blue)' : 'var(--teal)', color: '#fff', display: 'grid', placeItems: 'center', fontFamily: 'var(--display)', fontWeight: 600 } }, (u.name || u.email || '?').slice(0, 1).toUpperCase()),
            e('div', null, e('div', { style: { fontWeight: 700, fontSize: 15 } }, u.name || '(no name)', u.id === me.id ? e('span', { className: 'muted', style: { fontSize: 12, fontWeight: 600 } }, '  · you') : null), e('div', { className: 'muted', style: { fontSize: 12.5 } }, u.email)),
          ),
          e('div', null, e('span', { className: 'badge ' + (u.role === 'admin' ? 'badge-prem' : 'badge-start') }, u.role === 'admin' ? 'Admin' : 'Sales Rep')),
          e('div', null, e('span', { className: 'badge ' + (u.active ? 'badge-good' : 'badge-order') }, u.active ? 'Active' : 'Disabled')),
          e('div', { style: { display: 'flex', gap: 6, justifyContent: 'flex-end', alignItems: 'center', flexWrap: 'wrap' } },
            backend ? e(Btn, { variant: 'ghost', size: 'sm', onClick: () => { try { GW.db.client.auth.resetPasswordForEmail(u.email); } catch (e) {} app.toast('Password reset email sent to ' + u.email); } }, 'Reset PW') : e(Btn, { variant: 'ghost', size: 'sm', onClick: () => app.toast('Password reset link sent to ' + u.email) }, 'Reset PW'),
            e(Toggle, { on: !!u.active, onChange: v => setActive(u, v), label: u.name || u.email }),
            e('button', { onClick: () => setForm({ id: u.id, name: u.name || '', email: u.email, role: u.role, isNew: false }), title: 'Edit', style: { border: 'none', background: 'var(--field)', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', color: 'var(--ink-2)', cursor: 'pointer' } }, e(Icon, { name: 'edit', size: 16 })),
            !backend ? e('button', { onClick: () => removeUser(u), title: 'Remove', disabled: u.id === me.id, style: { border: 'none', background: 'var(--danger-bg)', color: 'var(--danger)', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', cursor: u.id === me.id ? 'not-allowed' : 'pointer', opacity: u.id === me.id ? .4 : 1 } }, e(Icon, { name: 'trash', size: 16 })) : null,
          ),
        )),
      ),
      e(Modal, { open: !!form, onClose: () => setForm(null), title: form ? (form.isNew ? (backend ? 'Add rep' : 'Add user') : 'Edit user') : '', width: 440 },
        form ? e('div', { style: { display: 'flex', flexDirection: 'column', gap: 14 } },
          e(Field, { label: 'Full name' }, e(Input, { value: form.name, onChange: ev => setForm(a => ({ ...a, name: ev.target.value })) })),
          e(Field, { label: 'Email' }, e(Input, { value: form.email, disabled: backend && !form.isNew, onChange: ev => setForm(a => ({ ...a, email: ev.target.value })) })),
          e(Field, { label: 'Role' }, e(window.Segmented, { value: form.role, onChange: r => setForm(a => ({ ...a, role: r })), options: [{ value: 'rep', label: 'Sales Rep' }, { value: 'admin', label: 'Admin' }] })),
          (backend && form.isNew) ? e(Field, { label: 'Temporary password', hint: 'Leave blank to auto-generate. The rep can change it later.' }, e(Input, { value: form.password || '', placeholder: 'auto-generate', onChange: ev => setForm(a => ({ ...a, password: ev.target.value })) })) : null,
          e(Btn, { variant: 'primary', block: true, disabled: busy || !form.name || (backend && form.isNew && !form.email), onClick: saveForm }, busy ? 'Saving…' : (form.isNew ? (backend ? 'Create rep' : 'Add user') : 'Save changes')),
        ) : null,
      ),
      // credentials result (after creating a rep)
      e(Modal, { open: !!created, onClose: () => setCreated(null), title: 'Rep account created', width: 440 },
        created ? e('div', { style: { display: 'flex', flexDirection: 'column', gap: 14 } },
          e('p', { className: 'muted', style: { margin: 0, fontSize: 14, lineHeight: 1.5 } }, 'Share these login details with the rep. They can change the password later from the login screen.'),
          e('div', { style: { background: 'var(--field)', borderRadius: 10, padding: 16, display: 'flex', flexDirection: 'column', gap: 8 } },
            e('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 10 } }, e('span', { className: 'muted', style: { fontSize: 13 } }, 'Email'), e('span', { style: { fontWeight: 700, fontSize: 14 } }, created.email)),
            e('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 10 } }, e('span', { className: 'muted', style: { fontSize: 13 } }, 'Password'), e('span', { className: 'num', style: { fontWeight: 800, fontSize: 15, letterSpacing: '.03em' } }, created.password)),
            e('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 10 } }, e('span', { className: 'muted', style: { fontSize: 13 } }, 'Role'), e('span', { className: 'badge ' + (created.role === 'admin' ? 'badge-prem' : 'badge-start') }, created.role === 'admin' ? 'Admin' : 'Sales Rep')),
          ),
          e('div', { style: { display: 'flex', gap: 8 } },
            e(Btn, { variant: 'ghost', block: true, onClick: () => { try { navigator.clipboard && navigator.clipboard.writeText('GarageWiz login\\nURL: ' + location.origin + '\\nEmail: ' + created.email + '\\nPassword: ' + created.password); app.toast('Copied'); } catch (e) {} } }, 'Copy details'),
            e(Btn, { variant: 'primary', block: true, onClick: () => setCreated(null) }, 'Done'),
          ),
        ) : null,
      ),
    );
  }
  window.AdminUsers = AdminUsers;

  /* ===================== PERMISSIONS ===================== */
  function AdminPermissions() {
    const app = window.useApp();
    const me = app.user || {};
    if (me.role !== 'admin') {
      return e('div', null, e(SectionTitle, { eyebrow: 'Admin', title: 'Permissions' }),
        e('div', { className: 'card', style: { padding: 40, textAlign: 'center', color: 'var(--ink-3)' } }, e(Icon, { name: 'lock', size: 28, style: { marginBottom: 10 } }), e('div', null, 'Only an admin can manage permissions.')));
    }
    const tools = (GW.tools || []).filter(t => !t.adminOnly); // admin panel is role-gated, not per-user
    const setPerm = (uid, tid, val) => { GW.permissions[uid] = Object.assign({}, GW.permissions[uid], { [tid]: val }); GW.savePermissions(); app.bump(); };

    return e('div', null,
      e(SectionTitle, { eyebrow: 'Admin', title: 'Tool permissions', sub: 'Grant or revoke each tool per user. Admins always have full access. New tools appear here automatically.' }),
      e('div', { style: { display: 'flex', flexDirection: 'column', gap: 14 } },
        GW.users.map(u => e('div', { key: u.id, className: 'card', style: { padding: 20, opacity: u.active ? 1 : .6 } },
          e('div', { style: { display: 'flex', alignItems: 'center', gap: 12, marginBottom: u.role === 'admin' ? 0 : 14 } },
            e('span', { style: { width: 38, height: 38, borderRadius: 999, background: u.role === 'admin' ? 'var(--blue)' : 'var(--teal)', color: '#fff', display: 'grid', placeItems: 'center', fontFamily: 'var(--display)', fontWeight: 600 } }, u.name.slice(0, 1)),
            e('div', { className: 'grow' },
              e('div', { style: { fontWeight: 700, fontSize: 15.5 } }, u.name),
              e('div', { className: 'muted', style: { fontSize: 12.5 } }, u.email),
            ),
            e('span', { className: 'badge ' + (u.role === 'admin' ? 'badge-prem' : 'badge-start') }, u.role === 'admin' ? 'Admin' : 'Sales Rep'),
          ),
          u.role === 'admin'
            ? e('div', { className: 'muted', style: { fontSize: 13, marginTop: 8 } }, 'Full access to every tool.')
            : e('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 10 } },
                tools.map(t => {
                  const on = GW.hasPermission(u, t.id);
                  return e('div', { key: t.id, style: { display: 'flex', alignItems: 'center', gap: 10, background: 'var(--field)', borderRadius: 10, padding: '10px 12px' } },
                    e('div', { style: { width: 32, height: 32, borderRadius: 9, background: t.accent, color: '#fff', display: 'grid', placeItems: 'center', flexShrink: 0 } }, e(Icon, { name: t.icon, size: 17 })),
                    e('div', { className: 'grow', style: { minWidth: 0 } },
                      e('div', { style: { fontWeight: 700, fontSize: 13.5, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, t.name),
                      e('div', { className: 'muted', style: { fontSize: 11.5 } }, t.status === 'coming_soon' ? 'Coming soon' : (on ? 'Granted' : 'Revoked')),
                    ),
                    e(Toggle, { on, onChange: v => setPerm(u.id, t.id, v), label: t.name }),
                  );
                })),
        )),
      ),
    );
  }
  window.AdminPermissions = AdminPermissions;

  /* ===================== TOOLS (suite registry) ===================== */
  function AdminTools() {
    const app = window.useApp();
    const save = (id) => { GW.saveToolOverride(id); app.bump(); };
    return e('div', null,
      e(SectionTitle, { eyebrow: 'System Admin', title: 'Tools', sub: 'The tool suite shown on the hub. Flip a tool live or hold it as “coming soon”, and choose whether it’s admin-only.' }),
      e('div', { style: { display: 'flex', flexDirection: 'column', gap: 12 } },
        (GW.tools || []).map(t => e('div', { key: t.id, className: 'card', style: { padding: 18, display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap' } },
          e('div', { style: { width: 48, height: 48, borderRadius: 13, background: t.accent, color: '#fff', display: 'grid', placeItems: 'center', flexShrink: 0 } }, e(Icon, { name: t.icon, size: 24 })),
          e('div', { className: 'grow', style: { minWidth: 180 } },
            e('div', { style: { fontWeight: 700, fontSize: 15.5 } }, t.name),
            e('div', { className: 'muted', style: { fontSize: 12.5 } }, t.route),
          ),
          e('div', { style: { minWidth: 200 } },
            e(window.Segmented, { value: t.status, onChange: v => { t.status = v; save(t.id); }, options: [{ value: 'active', label: 'Live' }, { value: 'coming_soon', label: 'Coming soon' }] })),
          e('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
            e('span', { className: 'muted', style: { fontSize: 12.5 } }, 'Admin only'),
            e(Toggle, { on: !!t.adminOnly, onChange: v => { t.adminOnly = v; save(t.id); }, label: t.name + ' admin only' })),
        )),
      ),
    );
  }
  window.AdminTools = AdminTools;

  /* ===================== BACKEND (sync status) ===================== */
  function AdminBackend() {
    const app = window.useApp();
    const connected = !!(window.GW.db && window.GW.db.configured);
    const url = (window.GW_CONFIG && window.GW_CONFIG.supabaseUrl) || '';
    const [busy, setBusy] = useState('');

    const publish = async () => {
      setBusy('publish');
      try { await GW.db.publishCatalog(GW.collectCatalog(), app.settings); app.toast('Catalog published to backend'); }
      catch (e) { app.toast('Publish failed: ' + ((e && e.message) || 'error')); }
      setBusy('');
    };
    const reload = async () => {
      setBusy('reload');
      try { const cat = await GW.db.loadCatalog(); if (cat) GW.applyCatalog(cat); const bs = await GW.db.loadSettings(); if (bs && Object.keys(bs).length) app.setSettings(Object.assign({}, app.settings, bs)); app.bump(); app.toast('Reloaded from backend'); }
      catch (e) { app.toast('Reload failed: ' + ((e && e.message) || 'error')); }
      setBusy('');
    };

    const Row = (label, value, ok) => e('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '11px 0', borderTop: '1px solid var(--line)' } },
      e('span', { className: 'muted', style: { fontSize: 13.5 } }, label),
      e('span', { style: { fontWeight: 700, fontSize: 13.5, color: ok === false ? 'var(--danger)' : ok === true ? 'var(--good)' : 'var(--ink)' } }, value));

    return e('div', null,
      e(SectionTitle, { eyebrow: 'System Admin', title: 'Backend', sub: 'Sync status for the shared cloud database. Admin edits write through automatically; you can also publish or reload manually.' }),
      e('div', { className: 'card', style: { padding: 22, marginBottom: 18, maxWidth: 620 } },
        e('div', { style: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 } },
          e('span', { style: { width: 11, height: 11, borderRadius: 999, background: connected ? 'var(--good)' : 'var(--danger)', boxShadow: connected ? '0 0 8px var(--good)' : 'none' } }),
          e('div', { style: { fontWeight: 800, fontSize: 15 } }, connected ? 'Connected to Supabase' : 'Not connected (running on local storage)'),
        ),
        Row('Project URL', url || '—', connected),
        Row('Signed in as', (app.user && app.user.email) || '—'),
        Row('Catalog write-through', connected ? 'On (auto-syncs admin edits)' : 'Off', connected),
      ),
      connected ? e('div', { className: 'card', style: { padding: 22, maxWidth: 620, display: 'flex', gap: 12, flexWrap: 'wrap' } },
        e(Btn, { variant: 'primary', icon: 'check', disabled: !!busy, onClick: publish }, busy === 'publish' ? 'Publishing…' : 'Publish current catalog'),
        e(Btn, { variant: 'ghost', icon: 'activity', disabled: !!busy, onClick: reload }, busy === 'reload' ? 'Reloading…' : 'Reload from backend'),
      ) : null,
      e('div', { className: 'muted', style: { fontSize: 12.5, marginTop: 14, maxWidth: 620, lineHeight: 1.5 } },
        'Publish pushes this device’s catalog (parts, models, openers, glass, inserts, bundles, coupons, tools, permissions) and business settings up as the shared source of truth. Reps pull it on login. Pricing always runs locally against the cached copy.'),
    );
  }
  window.AdminBackend = AdminBackend;

  /* ===================== ACTIVITY ===================== */
  // ---- sample (offline) version, kept as fallback when no backend ----
  function ActivitySample() {
    const totals = GW.activity.reduce((t, a) => ({ quotes: t.quotes + a.quotes, value: t.value + a.value }), { quotes: 0, value: 0 });
    return e('div', null,
      e(SectionTitle, { eyebrow: 'System Admin', title: 'Activity', sub: 'Sample data (no backend connected). Connect Supabase to see real per-rep numbers.' }),
      e('div', { className: 'stat-strip', style: { display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 16, marginBottom: 20 } },
        [['Total quotes', totals.quotes], ['Quoted value', GW.fmt(totals.value)], ['Avg job', GW.fmt(totals.value / totals.quotes)], ['Active reps', GW.activity.length]].map((s, i) =>
          e('div', { key: i, className: 'card', style: { padding: 20 } }, e('div', { className: 'eyebrow' }, s[0]), e('div', { className: 'display num', style: { fontSize: 30, fontWeight: 700, marginTop: 6, color: 'var(--teal)' } }, s[1]))),
      ),
      e('div', { className: 'card', style: { overflow: 'hidden' } },
        e('div', { className: 'table-head-act' }, ['Rep', 'Quotes', 'Value', 'Avg job', 'Top add-on', 'Discount rate'].map((h, i) => e('div', { key: i, style: { textAlign: i >= 1 && i <= 3 ? 'right' : 'left' } }, h))),
        GW.activity.map((a, i) => e('div', { key: i, className: 'table-row-act' },
          e('div', { style: { fontWeight: 700, fontSize: 15 } }, a.user),
          e('div', { className: 'num', style: { textAlign: 'right' } }, a.quotes),
          e('div', { className: 'num', style: { textAlign: 'right', fontWeight: 600 } }, GW.fmt(a.value)),
          e('div', { className: 'num', style: { textAlign: 'right' } }, GW.fmt(a.avg)),
          e('div', null, e('span', { className: 'badge badge-start' }, a.topAddon)),
          e('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
            e('div', { style: { flex: 1, height: 8, background: 'var(--field)', borderRadius: 999, overflow: 'hidden', minWidth: 60 } }, e('div', { style: { width: (a.discountRate * 100) + '%', height: '100%', background: a.discountRate > 0.45 ? 'var(--warn)' : 'var(--blue)', borderRadius: 999 } })),
            e('span', { className: 'num', style: { fontSize: 13, fontWeight: 600, width: 38, textAlign: 'right' } }, Math.round(a.discountRate * 100) + '%'),
          ),
        )),
      ),
    );
  }

  function AdminActivity() {
    const backend = !!(window.GW.db && window.GW.db.configured);
    const [reps, setReps] = useState(null);
    const [items, setItems] = useState(null);
    const [err, setErr] = useState('');
    useEffect(() => {
      if (!backend) return; let live = true;
      (async () => {
        try { const r = await GW.db.repStats(); const it = await GW.db.itemSales(); if (live) { setReps(r); setItems(it); } }
        catch (e) { if (live) setErr((e && e.message) || 'Could not load activity.'); }
      })(); return () => { live = false; };
    }, []);

    if (!backend) return e(ActivitySample);

    const N = (v) => Number(v) || 0;
    const list = (reps || []).filter(r => N(r.estimates) > 0).sort((a, b) => N(b.quoted_value) - N(a.quoted_value));
    const tot = (reps || []).reduce((t, r) => ({ est: t.est + N(r.estimates), appr: t.appr + N(r.approved), val: t.val + N(r.quoted_value), av: t.av + N(r.approved_value) }), { est: 0, appr: 0, val: 0, av: 0 });
    const apprRate = tot.est ? Math.round(tot.appr / tot.est * 100) : 0;

    // product mix (top items by revenue)
    const mix = {};
    (items || []).forEach(it => { const k = it.label || it.ref_id || it.type; const m = mix[k] || (mix[k] = { label: k, type: it.type, units: 0, revenue: 0 }); m.units += N(it.units); m.revenue += N(it.revenue); });
    const topItems = Object.values(mix).sort((a, b) => b.revenue - a.revenue).slice(0, 8);

    const stat = (label, val) => e('div', { className: 'card', style: { padding: 20 } }, e('div', { className: 'eyebrow' }, label), e('div', { className: 'display num', style: { fontSize: 30, fontWeight: 700, marginTop: 6, color: 'var(--teal)' } }, val));

    return e('div', null,
      e(SectionTitle, { eyebrow: 'System Admin', title: 'Activity', sub: 'Live per-rep performance from the cloud — estimates, value, and approval rate. The source for Reports & Performance Pay.' }),
      err ? e('div', { className: 'card', style: { padding: 16, marginBottom: 16, color: 'var(--danger)', fontWeight: 600 } }, err) : null,
      reps === null ? e('div', { className: 'muted', style: { padding: 30, textAlign: 'center' } }, 'Loading live activity…')
        : e('div', null,
            e('div', { className: 'stat-strip', style: { display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 16, marginBottom: 20 } },
              stat('Estimates', tot.est),
              stat('Quoted value', GW.fmt(tot.val)),
              stat('Approval rate', apprRate + '%'),
              stat('Approved value', GW.fmt(tot.av)),
            ),
            e('div', { className: 'card', style: { overflow: 'hidden', marginBottom: 20 } },
              e('div', { className: 'table-head-act' }, ['Rep', 'Estimates', 'Approved', 'Approval', 'Quoted value', 'Approved value'].map((h, i) => e('div', { key: i, style: { textAlign: i >= 1 ? 'right' : 'left' } }, h))),
              list.length === 0 ? e('div', { style: { padding: 24, textAlign: 'center', color: 'var(--ink-3)' } }, 'No estimates yet — they’ll appear here as reps save them.')
                : list.map((r, i) => {
                    const rate = N(r.estimates) ? Math.round(N(r.approved) / N(r.estimates) * 100) : 0;
                    return e('div', { key: r.user_id || i, className: 'table-row-act' },
                      e('div', { style: { fontWeight: 700, fontSize: 15 } }, r.name || r.email || 'Rep'),
                      e('div', { className: 'num', style: { textAlign: 'right' } }, N(r.estimates)),
                      e('div', { className: 'num', style: { textAlign: 'right' } }, N(r.approved)),
                      e('div', { className: 'num', style: { textAlign: 'right', fontWeight: 600, color: rate >= 50 ? 'var(--good)' : 'var(--ink)' } }, rate + '%'),
                      e('div', { className: 'num', style: { textAlign: 'right', fontWeight: 600 } }, GW.fmt(N(r.quoted_value))),
                      e('div', { className: 'num', style: { textAlign: 'right' } }, GW.fmt(N(r.approved_value))),
                    );
                  }),
            ),
            topItems.length ? e('div', { className: 'card', style: { padding: 22 } },
              e('div', { style: { fontWeight: 700, fontSize: 16, marginBottom: 14 } }, 'Top products by revenue'),
              e('div', { style: { display: 'flex', flexDirection: 'column', gap: 10 } },
                topItems.map((m, i) => e('div', { key: i, style: { display: 'flex', alignItems: 'center', gap: 12 } },
                  e('span', { className: 'badge badge-start', style: { textTransform: 'capitalize', minWidth: 60, textAlign: 'center' } }, m.type),
                  e('div', { className: 'grow', style: { fontWeight: 600, fontSize: 14 } }, m.label),
                  e('div', { className: 'muted', style: { fontSize: 13, minWidth: 60, textAlign: 'right' } }, m.units + ' sold'),
                  e('div', { className: 'display num', style: { fontWeight: 700, color: 'var(--teal)', minWidth: 90, textAlign: 'right' } }, GW.fmt(m.revenue)),
                )),
              ),
            ) : null,
          ),
    );
  }
  window.AdminActivity = AdminActivity;
})();
