// ============================================================
// Saraya Events — Admin Dashboard
//
// Phase 1 scope:
//   • Platform stats overview
//   • Vendor approval queue (approve / reject / suspend)
//   • Subscription management (view, give free access, downgrade)
//   • Payout management (approve / hold / release)
//   • Complaint queue
//   • Subscription tier editor (names, prices, limits)
//   • User list
// ============================================================

const {
  useState: useStateAD,
  useEffect: useEffectAD,
  useCallback: useCallbackAD,
  useRef: useRefAD,
} = React;

/* ---------- Stat card ---------- */
function AdminStat({ icon, label, value, tone }) {
  const colors = {
    gold:    { bg: 'var(--cream)',  fg: 'var(--gold-deep)' },
    success: { bg: '#F0FDF4',      fg: '#16A34A' },
    warning: { bg: '#FFFBEB',      fg: '#D97706' },
    danger:  { bg: '#FEF2F2',      fg: '#B91C1C' },
  };
  const c = colors[tone] || colors.gold;
  return (
    <div style={{ background: 'var(--white)', borderRadius: 14, border: '1px solid var(--line)', padding: '18px 20px' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
        <span style={{ display: 'inline-flex', width: 36, height: 36, borderRadius: 10, background: c.bg, alignItems: 'center', justifyContent: 'center' }}>
          <Icon name={icon} size={18} style={{ color: c.fg }} />
        </span>
        <span style={{ fontSize: 12, color: 'var(--fg-secondary)', fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase' }}>{label}</span>
      </div>
      <p style={{ fontSize: 30, fontWeight: 700, fontFamily: 'var(--font-display)', margin: 0 }}>{value ?? '—'}</p>
    </div>
  );
}

const COMPLAINT_TYPE_LABELS = {
  booking_issue: 'Booking issue',
  rental_issue: 'Rental issue',
  service_issue: 'Service issue',
  vendor_issue: 'Vendor issue',
  payment_issue: 'Payment issue',
  delivery_issue: 'Delivery issue',
  order_issue: 'Order issue',
  quality_issue: 'Quality issue',
  vendor_conduct: 'Vendor conduct',
  billing_dispute: 'Billing dispute',
  other: 'Other',
};

/* ---------- Status badge ---------- */
function StatusBadge({ status }) {
  const MAP = {
    active:               { bg: '#DCFCE7', fg: '#16A34A' },
    approved:             { bg: '#DCFCE7', fg: '#16A34A' },
    pending_approval:     { bg: '#FEF3C7', fg: '#D97706' },
    payment_pending:      { bg: '#DBEAFE', fg: '#1D4ED8' },
    package_pending:      { bg: '#F3E8FF', fg: '#7C3AED' },
    registered:           { bg: '#F3F4F6', fg: '#6B7280' },
    suspended:            { bg: '#FEE2E2', fg: '#B91C1C' },
    deactivated:          { bg: '#F3F4F6', fg: '#9CA3AF' },
    // legacy statuses (kept for backward compatibility)
    agreement_accepted:   { bg: '#D1FAE5', fg: '#059669' },
    under_review:         { bg: '#FEF3C7', fg: '#D97706' },
    documents_submitted:  { bg: '#DBEAFE', fg: '#1D4ED8' },
    pending:              { bg: '#FEF3C7', fg: '#D97706' },
    approved_payout:      { bg: '#D1FAE5', fg: '#059669' },
    on_hold:              { bg: '#FEE2E2', fg: '#B91C1C' },
    paid:                 { bg: '#DCFCE7', fg: '#16A34A' },
    open:                 { bg: '#DBEAFE', fg: '#1D4ED8' },
    resolved:             { bg: '#DCFCE7', fg: '#16A34A' },
  };
  const s = MAP[status] || { bg: '#F3F4F6', fg: '#6B7280' };
  return (
    <span style={{ padding: '3px 10px', borderRadius: 20, background: s.bg, color: s.fg, fontSize: 12, fontWeight: 600, textTransform: 'capitalize' }}>
      {(status || '').replace(/_/g, ' ')}
    </span>
  );
}

/* ---------- Section wrapper ---------- */
function AdminSection({ title, desc, children, action }) {
  return (
    <div style={{ background: 'var(--white)', borderRadius: 16, border: '1px solid var(--line)', overflow: 'hidden' }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '18px 22px', borderBottom: '1px solid var(--line)' }}>
        <div>
          <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 20, fontWeight: 500, margin: 0 }}>{title}</h2>
          {desc && <p style={{ fontSize: 13, color: 'var(--fg-secondary)', margin: '3px 0 0' }}>{desc}</p>}
        </div>
        {action}
      </div>
      <div style={{ padding: '0' }}>{children}</div>
    </div>
  );
}

/* ---------- Table ---------- */
function AdminTable({ cols, rows, emptyMsg }) {
  if (!rows || rows.length === 0) {
    return (
      <div style={{ padding: '32px 22px', textAlign: 'center', color: 'var(--fg-muted)', fontSize: 14 }}>
        {emptyMsg || 'No records'}
      </div>
    );
  }
  return (
    <div style={{ overflowX: 'auto' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13.5 }}>
        <thead>
          <tr style={{ background: 'var(--bg-tint)' }}>
            {cols.map((c) => (
              <th key={c.key} style={{ padding: '10px 16px', textAlign: 'start', fontWeight: 600, fontSize: 12, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--fg-secondary)', borderBottom: '1px solid var(--line)', whiteSpace: 'nowrap' }}>
                {c.label}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row, i) => (
            <tr key={row.id || i} style={{ borderBottom: '1px solid var(--line)', transition: 'background 120ms' }}
              onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--bg-tint)'; }}
              onMouseLeave={(e) => { e.currentTarget.style.background = ''; }}>
              {cols.map((c) => (
                <td key={c.key} style={{ padding: '12px 16px', verticalAlign: 'middle', whiteSpace: c.wrap ? 'normal' : 'nowrap' }}>
                  {c.render ? c.render(row) : (row[c.key] ?? '—')}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

/* ---------- Confirm dialog ---------- */
function ConfirmDialog({ msg, onOk, onCancel, dangerous }) {
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 500, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(42,31,26,0.5)', padding: 16 }}>
      <div style={{ background: 'var(--white)', borderRadius: 16, padding: '28px', maxWidth: 380, width: '100%', boxShadow: 'var(--shadow-deep)' }}>
        <p style={{ fontSize: 15, lineHeight: 1.6, color: 'var(--fg-primary)', marginBottom: 20 }}>{msg}</p>
        <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
          <Button variant="ghost" onClick={onCancel}>Cancel</Button>
          <Button variant={dangerous ? 'danger' : 'primary'} onClick={onOk}>Confirm</Button>
        </div>
      </div>
    </div>
  );
}

/* ---- Placeholder panel for sections not yet backed by live data ---- */
function AdminPlaceholder({ title, desc, items, note }) {
  return (
    <div style={{ display: 'grid', gap: 16 }}>
      <div style={{ padding: '16px 20px', borderRadius: 12, background: '#FFFBEB', border: '1.5px solid #FCD34D', display: 'flex', gap: 12, alignItems: 'flex-start' }}>
        <Icon name="construction" size={18} style={{ color: '#D97706', flexShrink: 0, marginTop: 2 }} />
        <div>
          <div style={{ fontWeight: 600, fontSize: 14, marginBottom: 4 }}>Backend Required</div>
          <div style={{ fontSize: 13, color: 'var(--fg-secondary)', lineHeight: 1.6 }}>{note || 'This section requires Supabase tables and RLS policies to be configured. The UI is ready — connect the data source to activate.'}</div>
        </div>
      </div>
      {items && (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(220px,1fr))', gap: 12 }}>
          {items.map((item, i) => (
            <div key={i} style={{ padding: '18px 20px', borderRadius: 12, background: 'var(--white)', border: '1px solid var(--line)' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
                <span style={{ display: 'inline-flex', width: 32, height: 32, borderRadius: 8, background: 'var(--cream)', alignItems: 'center', justifyContent: 'center' }}>
                  <Icon name={item.icon} size={16} style={{ color: 'var(--gold-deep)' }} />
                </span>
                <span style={{ fontWeight: 600, fontSize: 13.5 }}>{item.label}</span>
              </div>
              <p style={{ fontSize: 12.5, color: 'var(--fg-secondary)', lineHeight: 1.5, margin: 0 }}>{item.desc}</p>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}



/* ============================================================
   ADMIN MARKETPLACE LISTINGS APPROVAL
   ============================================================ */
function AdminListingsApproval() {
  const db = window.SarayaDB;
  const [listType, setListType] = window.React.useState('products');
  const [items, setItems]       = window.React.useState([]);
  const [limit, setLimit]       = window.React.useState(100);
  const [loading, setLoading]   = window.React.useState(true);
  const [busyId, setBusyId]     = window.React.useState('');
  const [selected, setSelected] = window.React.useState(new Set());
  const [bulkBusy, setBulkBusy] = window.React.useState(false);
  const [editItem, setEditItem]   = window.React.useState(null);
  const [editCats, setEditCats]   = window.React.useState([]);
  const [editOpening, setEditOpening] = window.React.useState(false);
  const openDetailsWindow = (it) => {
    const w = window.open('', '_blank', 'width=760,height=840');
    if (!w) return;
    const imgs = (it.images && it.images.length) ? it.images : (it.cover_image_url ? [it.cover_image_url] : []);
    const esc = (s) => (s == null ? '' : String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'));
    const imgsHtml = imgs.map((src) => '<img src="' + esc(src) + '" style="width:140px;height:140px;object-fit:cover;border-radius:8px;border:1px solid #E5E7EB;margin:4px;">').join('');
    const dfile = it.meta && it.meta.digital_file;
    const digitalHtml = it.is_digital ? (
      '<h2 style="font-size:15px;margin:18px 0 4px;">Digital Product</h2>' +
      '<div class="row"><span class="label">Type:</span> ' + esc((it.meta && it.meta.digital_type) || '—') + '</div>' +
      '<div class="row"><span class="label">Delivery:</span> ' + esc((it.meta && it.meta.digital_delivery) || '—') + '</div>' +
      '<div class="row"><span class="label">Timeframe:</span> ' + esc((it.meta && it.meta.digital_timeframe) || '—') + '</div>' +
      '<div class="row"><span class="label">Format:</span> ' + esc((it.meta && it.meta.digital_format) || '—') + '</div>' +
      '<div class="row"><span class="label">Usage:</span> ' + esc((it.meta && it.meta.digital_usage) || '—') + '</div>' +
      '<div class="row"><span class="label">Customization:</span> ' + ((it.meta && it.meta.digital_customization) ? 'Yes' : 'No') + '</div>' +
      '<div class="row"><span class="label">File:</span> ' + (dfile && dfile.path ? esc(dfile.name || 'file') + ' (' + Math.round((dfile.size || 0) / 1024) + ' KB)' : '<span style="color:#B91C1C;font-weight:600;">No downloadable file uploaded yet — approve only if this is delivered manually per order.</span>') + '</div>'
    ) : '';
    const varsArr = (it.meta && Array.isArray(it.meta.variations)) ? it.meta.variations : [];
    const varsHtml = varsArr.length ? ('<h2 style="font-size:15px;margin:18px 0 4px;">Variations (' + varsArr.length + ')</h2>' + varsArr.map(function (g) {
      var opts = (g.options || []).map(function (o) { return esc(o.label || o.value || '?') + (Number(o.price_adjustment) ? ' (+' + o.price_adjustment + ')' : '') + (o.is_available === false ? ' [unavailable]' : ''); }).join(', ');
      var warn = ''; if (!g.name && !g.type) warn += ' [missing name]'; if ((g.options || []).some(function (o) { return !o.label && !o.value; })) warn += ' [option missing label]';
      return '<div class="row"><span class="label">' + esc(g.name || g.type || 'Group') + (g.required ? ' *' : '') + ':</span> ' + opts + (warn ? '<span style="color:#B91C1C;font-weight:600;">' + esc(warn) + '</span>' : '') + '</div>';
    }).join('')) : '';
    const html = '<!doctype html><html><head><meta charset="utf-8"><title>' + esc(it.name_en || it.name_ar || 'Listing Details') +
      '</title><style>body{font-family:-apple-system,Segoe UI,Arial,sans-serif;padding:24px;color:#111827;max-width:720px;margin:0 auto;}' +
      'h1{font-size:20px;margin:0 0 4px;}.ar{color:#6B7280;font-size:14px;margin-bottom:16px;}.row{margin:8px 0;font-size:14px;}' +
      '.label{font-weight:600;display:inline-block;min-width:110px;}.imgs{display:flex;flex-wrap:wrap;margin:16px 0;}' +
      '.meta{color:#9CA3AF;font-size:12px;margin-top:20px;}</style></head><body>' +
      '<h1>' + esc(it.name_en || it.name_ar || 'Listing') + '</h1>' +
      (it.name_ar ? '<div class="ar">' + esc(it.name_ar) + '</div>' : '') +
      '<div class="imgs">' + imgsHtml + '</div>' +
      '<div class="row"><span class="label">Vendor:</span> ' + esc((it.vendor_profiles && it.vendor_profiles.trade_name) || '—') + '</div>' +
      '<div class="row"><span class="label">Category:</span> ' + esc((it.categories && it.categories.name_en) || it.category || '—') + '</div>' +
      '<div class="row"><span class="label">Price:</span> AED ' + esc(it.price != null ? it.price : (it.base_price != null ? it.base_price : (it.price_per_day != null ? it.price_per_day : '—'))) + '</div>' +
      '<div class="row"><span class="label">Status:</span> ' + esc(it.status || '—') + (it.is_active === false ? ' (inactive)' : '') + '</div>' +
      (it.description_en ? '<div class="row"><span class="label">Description:</span> ' + esc(it.description_en) + '</div>' : '') +
      (it.description_ar ? '<div class="row" dir="rtl"><span class="label">الوصف:</span> ' + esc(it.description_ar) + '</div>' : '') +
      digitalHtml +
      varsHtml +
      '<div class="meta">Created: ' + (it.created_at ? new Date(it.created_at).toLocaleString() : '—') + ' · Updated: ' + (it.updated_at ? new Date(it.updated_at).toLocaleString() : '—') + '</div>' +
      '</body></html>';
    w.document.write(html);
    w.document.close();
  };
  const [filterActive, setFilterActive] = window.React.useState('all'); const [filterStatus, setFilterStatus] = window.React.useState('all');
  const [filterDigital, setFilterDigital] = window.React.useState('all');
  const [search, setSearch] = window.React.useState('');

  const TABLE = listType === 'products' ? 'products' : listType === 'rentals' ? 'rentals' : 'services';

  const load = async () => {
    if (!db) return;
    setLoading(true);
    let q = db.from(TABLE).select('*, vendor_profiles(trade_name), categories(name_en, name_ar, slug)').order('created_at', { ascending: false }).limit(limit);
    const { data, error } = await q;
    if (!error && data) setItems(data);
    setLoading(false);
  };

  window.React.useEffect(() => { load(); }, [listType, limit]);
  window.React.useEffect(() => { setSelected(new Set()); }, [listType]);

  const toggle = async (id, field, current) => {
    setBusyId(id + field);
    await db.from(TABLE).update({ [field]: !current }).eq('id', id);
    setItems((prev) => prev.map((it) => it.id === id ? { ...it, [field]: !current } : it));
    setBusyId('');
  };
  const setStatus = async (id, status) => { setBusyId(id + 'status'); await db.from(TABLE).update({ status }).eq('id', id); setItems((prev) => prev.map((it) => it.id === id ? { ...it, status } : it)); setBusyId(''); };

  // Admin edit: open the same full listing editor vendors use, pre-loaded with this listing.
  const openEdit = async (it) => {
    if (!window.ListingFormModal) { window.alert('Editor module not loaded yet — please refresh.'); return; }
    setEditOpening(true);
    try {
      const catType = listType === 'products' ? 'product' : listType === 'rentals' ? 'rental' : 'service';
      const cats = (window.SarayaService && window.SarayaService.categories) ? await window.SarayaService.categories.list(catType) : [];
      setEditCats(cats || []);
    } catch (e) { setEditCats([]); }
    setEditOpening(false);
    setEditItem(it);
  };
  // After an admin edit saves (the shared form marks it pending), approve it and refresh.
  const onEditSaved = async () => {
    const id = editItem && editItem.id;
    setEditItem(null);
    if (id) { await db.from(TABLE).update({ status: 'approved' }).eq('id', id); }
    await load();
  };

  const toggleSelectAll = () => {
    setSelected((prev) => (prev.size === filtered.length ? new Set() : new Set(filtered.map((it) => it.id))));
  };
  const toggleSelectOne = (id) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };
  const handleBulkDelete = async () => {
    if (!selected.size) return;
    if (!window.confirm(`Delete ${selected.size} selected listing(s)? This cannot be undone.`)) return;
    setBulkBusy(true);
    await Promise.all(Array.from(selected).map((id) => db.from(TABLE).delete().eq('id', id)));
    setItems((prev) => prev.filter((it) => !selected.has(it.id)));
    setBulkBusy(false);
    setSelected(new Set());
  };
  const handleBulkVisibility = async (makeActive) => {
    if (!selected.size) return;
    setBulkBusy(true);
    await Promise.all(Array.from(selected).map((id) => db.from(TABLE).update({ is_active: makeActive }).eq('id', id)));
    setItems((prev) => prev.map((it) => selected.has(it.id) ? { ...it, is_active: makeActive } : it));
    setBulkBusy(false);
    setSelected(new Set());
  };

  const searchQ = (search || '').trim().toLowerCase();
  const filtered = items.filter((it) => {
    if (searchQ) {
      const hay = ((it.name_en || '') + ' ' + (it.name_ar || '') + ' ' + ((it.vendor_profiles && it.vendor_profiles.trade_name) || '')).toLowerCase();
      if (hay.indexOf(searchQ) === -1) return false;
    }
    if (listType === 'products' && filterDigital === 'digital' && !it.is_digital) return false;
    if (listType === 'products' && filterDigital === 'digital_nofile' && !(it.is_digital && !(it.meta && it.meta.digital_file && it.meta.digital_file.path))) return false;
    if (filterActive === 'active') return it.is_active !== false;
    if (filterActive === 'inactive') return it.is_active === false;
    if (filterStatus !== 'all' && (it.status || 'approved') !== filterStatus) return false;
    return true;
  });

  const priceCol = listType === 'products' ? 'price' : listType === 'rentals' ? 'price_per_day' : 'base_price';
  const typeColors = { products: '#1B2A4A', rentals: '#2D7D78', services: '#B8965A' };
  const typeLabel  = { products: 'Product', rentals: 'Rental', services: 'Service' };

  return (
    <div style={{ display: 'grid', gap: 16 }}>
      {/* Type tabs */}
      <div style={{ display: 'flex', gap: 0, borderRadius: 10, overflow: 'hidden', border: '1px solid var(--line)', width: 'fit-content' }}>
        {['products','rentals','services'].map((t) => (
          <button key={t} onClick={() => setListType(t)} style={{ padding: '8px 18px', border: 'none', cursor: 'pointer', fontWeight: 600, fontSize: 13, background: listType === t ? 'var(--espresso)' : 'var(--white)', color: listType === t ? 'var(--ivory)' : 'var(--fg-primary)', borderInlineEnd: t !== 'services' ? '1px solid var(--line)' : 'none' }}>
            {t.charAt(0).toUpperCase() + t.slice(1)}
          </button>
        ))}
      </div>
      {/* Search */}
      <div style={{ position: 'relative', maxWidth: 340 }}>
        <Icon name="search" size={15} style={{ position: 'absolute', insetInlineStart: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--fg-muted)', pointerEvents: 'none' }} />
        <input value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Search by name or vendor…" style={{ width: '100%', boxSizing: 'border-box', padding: '8px 32px', borderRadius: 9, border: '1px solid var(--line-strong)', fontFamily: 'var(--font-body)', fontSize: 13, outline: 'none', color: 'var(--fg-primary)', background: 'var(--white)' }} />
        {search && <button onClick={() => setSearch('')} style={{ position: 'absolute', insetInlineEnd: 10, top: '50%', transform: 'translateY(-50%)', border: 'none', background: 'none', cursor: 'pointer', color: 'var(--fg-muted)', fontSize: 16, lineHeight: 1 }}>×</button>}
      </div>
      {/* Status filter */}
      <div style={{ display: 'flex', gap: 8 }}>
        {[['all','All'],['active','Active'],['inactive','Inactive / Draft']].map(([v,l]) => (
          <button key={v} onClick={() => setFilterActive(v)} style={{ padding: '5px 12px', borderRadius: 20, border: '1px solid var(--line)', cursor: 'pointer', fontSize: 12.5, fontWeight: filterActive===v ? 700 : 400, background: filterActive===v ? 'var(--espresso)' : 'var(--white)', color: filterActive===v ? 'var(--ivory)' : 'var(--fg-primary)' }}>
            {l}
          </button>
        ))}
        <span style={{ fontSize: 12, color: 'var(--fg-muted)', alignSelf: 'center' }}>{filtered.length} listing{filtered.length !== 1 ? 's' : ''}</span>
      </div>
      {/* Status filter */}
      <div style={{ display: 'flex', gap: 8 }}>
        {[['all','All'],['pending','Pending Review'],['approved','Approved'],['rejected','Rejected']].map(([v,l]) => (
          <button key={v} onClick={() => setFilterStatus(v)} style={{ padding: '5px 12px', borderRadius: 20, border: '1px solid var(--line)', cursor: 'pointer', fontSize: 12.5, fontWeight: filterStatus===v ? 700 : 400, background: filterStatus===v ? 'var(--espresso)' : 'var(--white)', color: filterStatus===v ? 'var(--ivory)' : 'var(--fg-primary)' }}>
            {l}
          </button>
        ))}
        <span style={{ fontSize: 12, color: 'var(--fg-muted)', alignSelf: 'center' }}>{filtered.length} listing{filtered.length !== 1 ? 's' : ''}</span>
      </div>

      {/* Digital filter (products only) */}
      {listType === 'products' && (
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
          <span style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '.05em' }}>Digital</span>
          {[['all','All types'],['digital','Digital only'],['digital_nofile','Digital · no file']].map(([v,l]) => (
            <button key={v} onClick={() => setFilterDigital(v)} style={{ padding: '5px 12px', borderRadius: 20, border: '1px solid ' + (v === 'digital_nofile' ? '#FCA5A5' : 'var(--line)'), cursor: 'pointer', fontSize: 12.5, fontWeight: filterDigital===v ? 700 : 400, background: filterDigital===v ? (v === 'digital_nofile' ? '#991B1B' : 'var(--espresso)') : 'var(--white)', color: filterDigital===v ? 'var(--ivory)' : (v === 'digital_nofile' ? '#991B1B' : 'var(--fg-primary)') }}>
              {l}
            </button>
          ))}
        </div>
      )}

      {selected.size > 0 && (
        <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 10, padding: '10px 14px', background: '#FFF7ED', border: '1px solid #FED7AA', borderRadius: 10, marginBottom: 12 }}>
          <span style={{ fontSize: 13, fontWeight: 600, color: '#9A3412' }}>{selected.size} selected</span>
          <button disabled={bulkBusy} onClick={() => handleBulkVisibility(false)} style={{ padding: '6px 12px', borderRadius: 8, border: '1px solid #FED7AA', background: '#fff', fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>Hide</button>
          <button disabled={bulkBusy} onClick={() => handleBulkVisibility(true)} style={{ padding: '6px 12px', borderRadius: 8, border: '1px solid #FED7AA', background: '#fff', fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>Unhide</button>
          <button disabled={bulkBusy} onClick={handleBulkDelete} style={{ padding: '6px 12px', borderRadius: 8, border: '1px solid #FCA5A5', background: '#fff', color: '#991B1B', fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>Delete</button>
          <button disabled={bulkBusy} onClick={() => setSelected(new Set())} style={{ padding: '6px 12px', borderRadius: 8, border: '1px solid var(--line)', background: '#fff', fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>Clear</button>
        </div>
      )}

      {loading ? (
        <div style={{ textAlign: 'center', padding: 40, color: 'var(--fg-muted)' }}><Icon name="loader" size={28} style={{ animation: 'sarayaSpin 1s linear infinite' }} /></div>
      ) : filtered.length === 0 ? (
        <div style={{ padding: 32, textAlign: 'center', background: 'var(--white)', borderRadius: 12, border: '1px dashed var(--line)', color: 'var(--fg-muted)', fontSize: 14 }}>
          No {listType} found.
        </div>
      ) : (
        <div style={{ background: 'var(--white)', borderRadius: 14, border: '1px solid var(--line)', overflow: 'hidden' }}>
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13, minWidth: 900 }}>
            <thead>
              <tr style={{ background: 'var(--bg-tint)', borderBottom: '1px solid var(--line)' }}>
                <th style={{ padding: '10px 14px', width: 32 }}>
                  <input type="checkbox" checked={filtered.length > 0 && selected.size === filtered.length} onChange={toggleSelectAll} />
                </th>
                {['Image','Name','Category','Vendor','Price','Status','Active','Popular','Actions'].map((h) => (
                  <th key={h} style={{ padding: '10px 14px', textAlign: 'start', fontWeight: 600, fontSize: 11.5, color: 'var(--fg-secondary)', textTransform: 'uppercase', letterSpacing: '.05em', whiteSpace: 'nowrap' }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {filtered.length === 0 ? (
                <tr><td colSpan={11} style={{ padding: '28px 14px', textAlign: 'center', color: 'var(--fg-muted)', fontSize: 13.5 }}>
                  {listType === 'products' ? 'No product listings found yet.' : listType === 'rentals' ? 'No rental listings found yet.' : 'No vendor service listings found yet.'}
                </td></tr>
              ) : filtered.map((it, idx) => {
                const imgSrc = (it.images && it.images[0]) || it.src || it.cover_image_url || null;
                const price = it[priceCol];
                const isActive = it.is_active !== false;
                const isPopular = it.is_popular || false;
                const vendorName = (it.vendor_profiles && it.vendor_profiles.trade_name) || '—';
                return (
                  <tr key={it.id} style={{ borderBottom: idx < filtered.length-1 ? '1px solid var(--line)' : 'none', background: isActive ? 'transparent' : 'var(--bg-tint,#f9f9fb)', transition: 'background 120ms' }}
                    onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--cream)'; }}
                    onMouseLeave={(e) => { e.currentTarget.style.background = isActive ? 'transparent' : 'var(--bg-tint,#f9f9fb)'; }}>
                    <td style={{ padding: '10px 14px' }}>
                      <input type="checkbox" checked={selected.has(it.id)} onChange={() => toggleSelectOne(it.id)} />
                    </td>
                    <td style={{ padding: '10px 14px' }}>
                      {imgSrc ? (
                        <img src={imgSrc} alt="" style={{ width: 48, height: 48, objectFit: 'cover', borderRadius: 8, border: '1px solid var(--line)', display: 'block' }} />
                      ) : (
                        <div style={{ width: 48, height: 48, borderRadius: 8, background: 'var(--gold-tint,#fdf8f0)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                          <Icon name="image" size={20} style={{ color: 'var(--gold-deep)' }} />
                        </div>
                      )}
                    </td>
                    <td style={{ padding: '10px 14px' }}>
                      <div style={{ fontWeight: 600, maxWidth: 160, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{it.name_en}</div>
                      {it.name_ar && <div style={{ fontSize: 11.5, color: 'var(--fg-secondary)', direction: 'rtl', textAlign: 'start' }}>{it.name_ar}</div>}
                      <span style={{ display: 'inline-block', padding: '1px 7px', borderRadius: 10, fontSize: 10.5, fontWeight: 700, background: typeColors[listType] + '1A', color: typeColors[listType], marginTop: 3 }}>{typeLabel[listType]}</span>{it.meta && Array.isArray(it.meta.variations) && it.meta.variations.length ? <span title="Has variations" style={{ display: 'inline-block', marginInlineStart: 6, padding: '1px 7px', borderRadius: 10, fontSize: 10.5, fontWeight: 700, background: '#EEF2FF', color: '#4338CA', marginTop: 3 }}>{it.meta.variations.length + (it.meta.variations.length === 1 ? ' option set' : ' option sets')}</span> : null}{it.is_digital ? <span title="Digital product" style={{ display: 'inline-block', marginInlineStart: 6, padding: '1px 7px', borderRadius: 10, fontSize: 10.5, fontWeight: 700, background: '#FEF3C7', color: '#92400E', marginTop: 3 }}>Digital</span> : null}{it.is_digital && !(it.meta && it.meta.digital_file && it.meta.digital_file.path) ? <span title="No downloadable file uploaded" style={{ display: 'inline-block', marginInlineStart: 6, padding: '1px 7px', borderRadius: 10, fontSize: 10.5, fontWeight: 700, background: '#FEE2E2', color: '#991B1B', marginTop: 3 }}>No file</span> : null}
                    </td>
                    <td style={{ padding: '10px 14px', color: 'var(--fg-secondary)', fontSize: 12.5 }}>{(it.categories && (it.categories.name_en)) || '—'}</td>
                    <td style={{ padding: '10px 14px', color: 'var(--fg-secondary)', fontSize: 12.5 }}>{vendorName}</td>
                    <td style={{ padding: '10px 14px', whiteSpace: 'nowrap' }}>{price ? `AED ${Number(price).toLocaleString()}` : '—'}</td>
                    <td style={{ padding: '10px 14px' }}>
                      <div style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'flex-start' }}>
                        {(() => { const s = it.status || 'approved'; const m = s === 'approved' ? { l: 'Approved', bg: '#DCFCE7', c: '#15803D' } : s === 'pending' ? { l: 'Pending', bg: '#FEF3C7', c: '#92400E' } : { l: 'Rejected', bg: '#FEE2E2', c: '#991B1B' }; return <span style={{ padding: '2px 9px', borderRadius: 20, fontSize: 11, fontWeight: 700, background: m.bg, color: m.c }}>{m.l}</span>; })()}
                        <span style={{ padding: '2px 9px', borderRadius: 20, fontSize: 11, fontWeight: 600, background: isActive ? '#EFF6FF' : '#F3F4F6', color: isActive ? '#2563EB' : '#6B7280' }}>{isActive ? 'Active' : 'Inactive'}</span>
                      </div>
                    </td>
                    <td style={{ padding: '10px 14px' }}>
                      <button onClick={() => toggle(it.id, 'is_active', isActive)} disabled={busyId === it.id+'is_active'} title={isActive ? 'Deactivate' : 'Activate'} style={{ width: 32, height: 20, borderRadius: 10, border: 'none', cursor: 'pointer', position: 'relative', background: isActive ? '#16A34A' : '#D1D5DB', transition: 'background 200ms' }}>
                        <span style={{ position: 'absolute', top: 2, left: isActive ? 14 : 2, width: 16, height: 16, borderRadius: 8, background: '#fff', transition: 'left 200ms', display: 'block' }} />
                      </button>
                    </td>
                    <td style={{ padding: '10px 14px' }}>
                      <button onClick={() => toggle(it.id, 'is_popular', isPopular)} disabled={busyId === it.id+'is_popular'} title={isPopular ? 'Unfeature' : 'Feature'} style={{ width: 32, height: 20, borderRadius: 10, border: 'none', cursor: 'pointer', position: 'relative', background: isPopular ? '#B8965A' : '#D1D5DB', transition: 'background 200ms' }}>
                        <span style={{ position: 'absolute', top: 2, left: isPopular ? 14 : 2, width: 16, height: 16, borderRadius: 8, background: '#fff', transition: 'left 200ms', display: 'block' }} />
                      </button>
                    </td>
                    <td style={{ padding: '10px 14px' }}>
                      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
                        <button onClick={() => openDetailsWindow(it)} style={{ padding: '4px 11px', borderRadius: 7, border: '1px solid var(--line-strong)', background: 'var(--white)', color: 'var(--fg-primary)', cursor: 'pointer', fontSize: 12, fontWeight: 600 }}>View</button>
                        <button onClick={() => openEdit(it)} disabled={editOpening} style={{ padding: '4px 11px', borderRadius: 7, border: '1px solid var(--gold-deep)', background: 'var(--gold-deep)', color: '#fff', cursor: editOpening ? 'wait' : 'pointer', fontSize: 12, fontWeight: 600 }}>Edit</button>
                        {it.status && it.status !== 'approved' && <button onClick={() => setStatus(it.id, 'approved')} disabled={busyId === it.id+'status'} style={{ padding: '4px 11px', borderRadius: 7, border: 'none', background: '#16A34A', color: '#fff', cursor: 'pointer', fontSize: 12, fontWeight: 600 }}>Approve</button>}
                        {it.status === 'pending' && <button onClick={() => setStatus(it.id, 'rejected')} disabled={busyId === it.id+'status'} style={{ padding: '4px 11px', borderRadius: 7, border: '1px solid var(--line)', background: 'var(--white)', color: '#dc2626', cursor: 'pointer', fontSize: 12, fontWeight: 600 }}>Reject</button>}
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        </div>
      )}
      {!loading && items.length >= limit && (
        <div style={{ textAlign: 'center', padding: '4px 0 8px' }}>
          <button onClick={() => setLimit((l) => l + 100)} style={{ padding: '8px 18px', borderRadius: 8, border: '1px solid var(--line-strong)', background: 'var(--white)', cursor: 'pointer', fontSize: 13, fontWeight: 600, color: 'var(--fg-primary)' }}>Load more — showing first {limit}</button>
        </div>
      )}

      {editItem && window.ListingFormModal ? (
        <window.ListingFormModal
          type={listType}
          initial={editItem}
          vendorId={editItem.vendor_id}
          categories={editCats}
          canDiscount={true}
          ar={false}
          onClose={() => setEditItem(null)}
          onSave={onEditSaved}
        />
      ) : null}
    </div>
  );
}

/* ============================================================
   ADMIN PLATFORM IMAGE CMS
   ============================================================ */
function AdminReviewsModeration() {
  const db = window.SarayaDB;
  const [items, setItems] = window.React.useState([]);
  const [loading, setLoading] = window.React.useState(true);
  const [busyId, setBusyId] = window.React.useState(null);

  const load = async () => {
    setLoading(true);
    const { data, error } = await db.from('reviews').select('*, profiles(display_name)').eq('status', 'pending').order('created_at', { ascending: false });
    setItems(error ? [] : (data || []));
    setLoading(false);
  };

  window.React.useEffect(() => { if (db) load(); }, []);

  const decide = async (id, newStatus) => {
    setBusyId(id);
    await db.from('reviews').update({ status: newStatus }).eq('id', id);
    setBusyId(null);
    load();
  };

  if (loading) return <div style={{ padding: 20, color: 'var(--fg-muted)' }}>Loading reviews...</div>;
  if (!items.length) return <div style={{ padding: 20, color: 'var(--fg-muted)' }}>No reviews waiting for moderation.</div>;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
      {items.map((r) => (
        <div key={r.id} style={{ border: '1px solid var(--line)', borderRadius: 12, padding: 16, background: 'var(--white)' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12, flexWrap: 'wrap' }}>
            <div>
              <div style={{ fontWeight: 600, marginBottom: 4 }}>
                {'★'.repeat(r.rating || 0)}{'☆'.repeat(5 - (r.rating || 0))}
                {r.title ? ' — ' + r.title : ''}
              </div>
              <div style={{ fontSize: 13, color: 'var(--fg-muted)', marginBottom: 8 }}>
                {(r.profiles && r.profiles.display_name) || 'Customer'} · {new Date(r.created_at).toLocaleDateString()}
              </div>
              <div style={{ fontSize: 14 }}>{r.body}</div>
            </div>
            <div style={{ display: 'flex', gap: 8, flexShrink: 0 }}>
              <button disabled={busyId === r.id} onClick={() => decide(r.id, 'published')} style={{ padding: '8px 14px', borderRadius: 8, border: 'none', background: '#16A34A', color: '#fff', fontWeight: 600, cursor: 'pointer' }}>Approve</button>
              <button disabled={busyId === r.id} onClick={() => decide(r.id, 'rejected')} style={{ padding: '8px 14px', borderRadius: 8, border: '1px solid var(--line)', background: 'transparent', fontWeight: 600, cursor: 'pointer' }}>Reject</button>
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

function AdminPlatformImageCMS() {
  const db = window.SarayaDB;
  const [images, setImages]         = window.React.useState([]);
  const [loading, setLoading]       = window.React.useState(true);
  const [tableExists, setTableExists] = window.React.useState(null);
  const [uploading, setUploading]   = window.React.useState('');
  const [showAddForm, setShowAddForm] = window.React.useState(false);
  const [newImg, setNewImg]         = window.React.useState({ page_key: 'home', section_key: 'hero', image_url: '', image_alt_en: '', title_en: '' });

  const PAGE_KEYS    = ['home','store','rental','service','showroom','global'];
  const SECTION_KEYS = ['hero','banner','category','promo','logo'];

  const load = async () => {
    if (!db) { setLoading(false); return; }
    try {
      const { data, error } = await db.from('platform_images').select('*').order('page_key').order('image_order');
      if (error && error.code === '42P01') { setTableExists(false); setLoading(false); return; }
      setTableExists(true);
      if (!error && data) setImages(data);
    } catch (_e) { setTableExists(false); }
    setLoading(false);
  };

  window.React.useEffect(() => { load(); }, []);

  const toggleActive = async (id, current) => {
    await db.from('platform_images').update({ is_active: !current }).eq('id', id);
    setImages((prev) => prev.map((im) => im.id === id ? { ...im, is_active: !current } : im));
  };

  const deleteImage = async (id) => {
    if (!window.confirm('Delete this platform image?')) return;
    await db.from('platform_images').delete().eq('id', id);
    setImages((prev) => prev.filter((im) => im.id !== id));
  };

  const handleFileUpload = async (e, existingId) => {
    const file = e.target.files && e.target.files[0];
    if (!file || !window.SarayaService) return;
    setUploading(existingId || 'new');
    const { url, error } = await window.SarayaService.storage.uploadListingImage('platform', file);
    if (!error && url) {
      if (existingId) {
        await db.from('platform_images').update({ image_url: url }).eq('id', existingId);
        setImages((prev) => prev.map((im) => im.id === existingId ? { ...im, image_url: url } : im));
      } else {
        setNewImg((p) => ({ ...p, image_url: url }));
      }
    }
    setUploading('');
    e.target.value = '';
  };

  const addImage = async () => {
    if (!newImg.page_key) { alert('Please select a page.'); return; }
    if (!newImg.section_key) { alert('Please select a section.'); return; }
    if (!newImg.image_url) { alert('Please upload or enter an image URL first.'); return; }
    if (!newImg.image_alt_en || !newImg.image_alt_en.trim()) { alert('Please enter alt text describing the image (required for accessibility and SEO).'); return; }
    const { data, error } = await db.from('platform_images').insert({ ...newImg, is_active: true, image_order: 1 }).select();
    if (!error && data) { setImages((prev) => [...prev, data[0]]); setShowAddForm(false); setNewImg({ page_key: 'home', section_key: 'hero', image_url: '', image_alt_en: '', title_en: '' }); }
  };

  if (loading) return <div style={{ textAlign: 'center', padding: 32, color: 'var(--fg-muted)' }}><Icon name="loader" size={24} style={{ animation: 'sarayaSpin 1s linear infinite' }} /></div>;

  if (tableExists === false) return (
    <div style={{ padding: '20px 24px', borderRadius: 12, background: '#FFFBEB', border: '1.5px solid #FCD34D' }}>
      <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 8, display: 'flex', alignItems: 'center', gap: 8 }}><Icon name="alert-triangle" size={16} style={{ color: '#D97706' }} /> Migration Required</div>
      <p style={{ fontSize: 13, color: 'var(--fg-secondary)', margin: '0 0 12px', lineHeight: 1.6 }}>
        The <code>platform_images</code> table does not exist yet. Run the Supabase migration (Task 34) to enable this CMS. Once the migration runs, this panel will activate automatically.
      </p>
      <code style={{ display: 'block', background: '#1B2A4A', color: '#E5C98C', padding: '12px 16px', borderRadius: 8, fontSize: 12, lineHeight: 1.7, whiteSpace: 'pre-wrap' }}>
        {`-- Migration: create platform_images table\nCREATE TABLE platform_images (\n  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n  page_key text NOT NULL,\n  section_key text NOT NULL,\n  image_url text NOT NULL,\n  image_alt_en text, image_alt_ar text,\n  title_en text, title_ar text,\n  is_active boolean DEFAULT true,\n  image_order int DEFAULT 1,\n  uploaded_by uuid,\n  created_at timestamptz DEFAULT now(),\n  updated_at timestamptz DEFAULT now()\n);\nALTER TABLE platform_images ENABLE ROW LEVEL SECURITY;\nCREATE POLICY "Public reads active" ON platform_images FOR SELECT USING (is_active = true);\nCREATE POLICY "Admin full access" ON platform_images USING (true) WITH CHECK (true);`}
      </code>
    </div>
  );

  const grouped = PAGE_KEYS.reduce((acc, k) => { acc[k] = images.filter((im) => im.page_key === k); return acc; }, {});

  return (
    <div style={{ display: 'grid', gap: 20 }}>
      <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <Button variant="primary" small onClick={() => setShowAddForm(!showAddForm)}>
          <Icon name="plus" size={14} /> Add Platform Image
        </Button>
      </div>

      {/* Add image form */}
      {showAddForm && (
        <div style={{ padding: '20px 22px', borderRadius: 14, border: '1.5px solid var(--gold-deep)', background: 'var(--gold-tint,#fdf8f0)' }}>
          <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 14 }}>Add New Platform Image</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 12 }}>
            <div>
              <label style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--fg-secondary)', display: 'block', marginBottom: 4 }}>Page</label>
              <select value={newImg.page_key} onChange={(e) => setNewImg((p) => ({ ...p, page_key: e.target.value }))} style={{ width: '100%', padding: '8px 10px', borderRadius: 8, border: '1px solid var(--line)', fontSize: 13 }}>
                {PAGE_KEYS.map((k) => <option key={k} value={k}>{k}</option>)}
              </select>
            </div>
            <div>
              <label style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--fg-secondary)', display: 'block', marginBottom: 4 }}>Section</label>
              <select value={newImg.section_key} onChange={(e) => setNewImg((p) => ({ ...p, section_key: e.target.value }))} style={{ width: '100%', padding: '8px 10px', borderRadius: 8, border: '1px solid var(--line)', fontSize: 13 }}>
                {SECTION_KEYS.map((k) => <option key={k} value={k}>{k}</option>)}
              </select>
            </div>
            <div>
              <label style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--fg-secondary)', display: 'block', marginBottom: 4 }}>Alt Text (EN)</label>
              <input value={newImg.image_alt_en} onChange={(e) => setNewImg((p) => ({ ...p, image_alt_en: e.target.value }))} placeholder="Image description" style={{ width: '100%', padding: '8px 10px', borderRadius: 8, border: '1px solid var(--line)', fontSize: 13, boxSizing: 'border-box' }} />
            </div>
            <div>
              <label style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--fg-secondary)', display: 'block', marginBottom: 4 }}>Title (EN)</label>
              <input value={newImg.title_en} onChange={(e) => setNewImg((p) => ({ ...p, title_en: e.target.value }))} placeholder="Optional headline" style={{ width: '100%', padding: '8px 10px', borderRadius: 8, border: '1px solid var(--line)', fontSize: 13, boxSizing: 'border-box' }} />
            </div>
          </div>
          <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginBottom: 14 }}>
            {newImg.image_url && <img src={newImg.image_url} alt="" style={{ width: 64, height: 64, objectFit: 'cover', borderRadius: 8, border: '1px solid var(--line)' }} />}
            <div>
              <input value={newImg.image_url} onChange={(e) => setNewImg((p) => ({ ...p, image_url: e.target.value }))} placeholder="https:// image URL" style={{ width: 260, padding: '8px 10px', borderRadius: 8, border: '1px solid var(--line)', fontSize: 13, display: 'block', marginBottom: 6 }} />
              <label style={{ display: 'inline-flex', alignItems: 'center', gap: 6, cursor: uploading==='new'?'not-allowed':'pointer', fontSize: 12.5, color: 'var(--gold-deep)', fontWeight: 600 }}>
                <Icon name="upload" size={13} /> {uploading==='new' ? 'Uploading…' : 'Or upload file'}
                <input type="file" accept="image/*" onChange={(e) => handleFileUpload(e, null)} disabled={uploading==='new'} style={{ display: 'none' }} />
              </label>
            </div>
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <Button variant="primary" small onClick={addImage}>Save Image</Button>
            <Button variant="secondary" small onClick={() => setShowAddForm(false)}>Cancel</Button>
          </div>
        </div>
      )}

      {/* Existing images grouped by page */}
      {PAGE_KEYS.map((page) => grouped[page].length === 0 ? null : (
        <div key={page} style={{ background: 'var(--white)', borderRadius: 14, border: '1px solid var(--line)', overflow: 'hidden' }}>
          <div style={{ padding: '12px 18px', background: 'var(--bg-tint)', borderBottom: '1px solid var(--line)', fontWeight: 700, fontSize: 13.5, color: 'var(--fg-primary)', textTransform: 'capitalize' }}>
            {page} page
          </div>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
            <thead>
              <tr style={{ background: 'var(--bg-canvas,#f7f5f0)', borderBottom: '1px solid var(--line)' }}>
                {['Preview','Section','Title / Alt','Active','Actions'].map((h) => (
                  <th key={h} style={{ padding: '9px 14px', textAlign: 'start', fontWeight: 600, fontSize: 11.5, color: 'var(--fg-secondary)', textTransform: 'uppercase', letterSpacing: '.05em' }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {grouped[page].map((im, idx) => (
                <tr key={im.id} style={{ borderBottom: idx < grouped[page].length-1 ? '1px solid var(--line)' : 'none' }}>
                  <td style={{ padding: '10px 14px' }}>
                    <img src={im.image_url} alt={im.image_alt_en || ''} style={{ width: 72, height: 48, objectFit: 'cover', borderRadius: 7, border: '1px solid var(--line)', display: 'block' }} onError={(e) => { e.target.style.display='none'; }} />
                  </td>
                  <td style={{ padding: '10px 14px' }}>
                    <span style={{ padding: '3px 9px', borderRadius: 10, background: '#E3F0FB', color: '#1B2A4A', fontSize: 12, fontWeight: 700 }}>{im.section_key}</span>
                    <span style={{ fontSize: 11, color: 'var(--fg-muted)', display: 'block', marginTop: 3 }}>Order: {im.image_order}</span>
                  </td>
                  <td style={{ padding: '10px 14px' }}>
                    <div style={{ fontWeight: 600, fontSize: 13 }}>{im.title_en || '—'}</div>
                    <div style={{ fontSize: 12, color: 'var(--fg-secondary)', marginTop: 2 }}>{im.image_alt_en || 'No alt text'}</div>
                  </td>
                  <td style={{ padding: '10px 14px' }}>
                    <button onClick={() => toggleActive(im.id, im.is_active)} style={{ width: 32, height: 20, borderRadius: 10, border: 'none', cursor: 'pointer', position: 'relative', background: im.is_active ? '#16A34A' : '#D1D5DB', transition: 'background 200ms' }}>
                      <span style={{ position: 'absolute', top: 2, left: im.is_active ? 14 : 2, width: 16, height: 16, borderRadius: 8, background: '#fff', transition: 'left 200ms', display: 'block' }} />
                    </button>
                  </td>
                  <td style={{ padding: '10px 14px' }}>
                    <div style={{ display: 'flex', gap: 6 }}>
                      <label style={{ padding: '4px 10px', borderRadius: 7, border: '1px solid var(--gold-deep)', background: 'var(--gold-tint,#fdf8f0)', cursor: uploading===im.id?'not-allowed':'pointer', fontSize: 12, fontWeight: 600, color: 'var(--gold-deep)' }}>
                        {uploading===im.id ? 'Uploading…' : 'Replace'}
                        <input type="file" accept="image/*" onChange={(e) => handleFileUpload(e, im.id)} disabled={uploading===im.id} style={{ display: 'none' }} />
                      </label>
                      <button onClick={() => deleteImage(im.id)} style={{ padding: '4px 10px', borderRadius: 7, border: '1px solid var(--error,#dc2626)', background: 'var(--error-bg,#fef2f2)', cursor: 'pointer', fontSize: 12, fontWeight: 600, color: 'var(--error,#dc2626)' }}>Delete</button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      ))}

      {images.length === 0 && (
        <div style={{ textAlign: 'center', padding: 40, background: 'var(--white)', borderRadius: 14, border: '1px dashed var(--line)', color: 'var(--fg-muted)', fontSize: 14 }}>
          No platform images yet. Click "Add Platform Image" to upload the first one.
        </div>
      )}
    </div>
  );
}

/* ============================================================
   MAIN ADMIN DASHBOARD PAGE
   ============================================================ */
function AdminDashboardPage() {
  const db = window.SarayaDB;
  const { isAdmin, isStaff, staffPerms, user, openAuthModal, loading: authLoading } = useAuth();
  const isDevMode = (typeof window !== 'undefined') && (
    window.location.hostname === 'localhost' ||
    window.location.hostname === '127.0.0.1' ||
    window.localStorage.getItem('saraya_enable_dev_tools') === 'true'
  );
  const { lang } = useLang();
  const { go } = useNav();
  const ar = lang === 'ar';

  const [activeTab, setActiveTab] = useStateAD(() => {
    const stored = localStorage.getItem('saraya_admin_tab');
    if (stored) { localStorage.removeItem('saraya_admin_tab'); return stored; }
    return 'overview';
  });
  // Which tabs a staff member (non-admin) may see, based on their permissions.
  const canSeeTab = (key) => {
    if (isAdmin || (staffPerms || []).includes('full')) return true;
    if (!isStaff) return false;
    const need = { overview: '*', marketplace: 'listings', marketplace_activity: 'listings', staff_tasks: 'listings', orders: 'orders', complaints: 'complaints', rfqs: 'rfqs', leads: 'rfqs' }[key];
    if (need === '*') return true;
    return need ? (staffPerms || []).includes(need) : false;
  };
  useEffectAD(() => { if (!canSeeTab(activeTab)) setActiveTab('overview'); }, [activeTab, isAdmin, isStaff, staffPerms]);
  const [stats, setStats]           = useStateAD(null);
  const [vendors, setVendors]       = useStateAD([]);
  const [payouts, setPayouts]       = useStateAD([]);
  const [complaints, setComplaints]  = useStateAD([]);
  const [notifications, setNotifications] = useStateAD([]);
  const [toastsAD, setToastsAD] = useStateAD([]);
  const lastNotifAtAD = useRefAD(null);
  const dismissToastAD = useCallbackAD((id) => setToastsAD((prev) => prev.filter((x) => x.id !== id)), []);
  const pushToast = (title, body) => {
    const id = 'tst-' + Date.now() + '-' + Math.floor(Math.random() * 1000);
    setToastsAD((prev) => [...prev, { id, title, body }].slice(-4));
    setTimeout(() => dismissToastAD(id), 6000);
  };
  const pollNotificationsAD = useCallbackAD(async () => {
    if (!db || !user || !isAdmin) return;
    const { data, error } = await db.from('notifications').select('*').order('created_at', { ascending: false }).limit(10);
    if (error || !data || !data.length) return;
    const newest = data[0].created_at;
    if (lastNotifAtAD.current === null) { lastNotifAtAD.current = newest; return; }
    const fresh = data.filter((r) => new Date(r.created_at) > new Date(lastNotifAtAD.current));
    if (fresh.length) {
      lastNotifAtAD.current = newest;
      const items = fresh.map((r) => ({ id: r.id, title: r.title, body: r.body }));
      items.forEach((it) => { setTimeout(() => dismissToastAD(it.id), 8000); });
      setToastsAD((prev) => [...prev, ...items].slice(-4));
    }
  }, [db, user, isAdmin, dismissToastAD]);
  useEffectAD(() => {
    pollNotificationsAD();
    const t = setInterval(pollNotificationsAD, 25000);
    return () => clearInterval(t);
  }, [pollNotificationsAD]);
  const [viewingComplaint, setViewingComplaint] = useStateAD(null);
  const [viewingOrder, setViewingOrder]         = useStateAD(null);
  const openOrderDetail = async (r) => {
    setViewingOrder({ ...r, _loading: true });
    let detail = r, booking = null;
    try {
      const { data } = await db.from('orders')
        .select('id, reference, type, status, paid_at, created_at, customer_confirmed_at, notes, subtotal, discount_amount, delivery_fee, vat_amount, total_amount, commission_amount, vendor_payout_amount, delivery_address, guest_name, guest_email, guest_phone, vendor_id, profiles!customer_id(display_name, phone), order_items(id, name_en, name_ar, unit_price, quantity, line_total)')
        .eq('id', r.id).single();
      if (data) {
        detail = data;
        if (data.type === 'rental') { const rb = await db.from('rental_bookings').select('start_date, end_date, deposit_amount, deposit_paid, notes').eq('order_id', r.id).maybeSingle(); if (rb && rb.data) booking = { kind: 'rental', ...rb.data }; }
        else if (data.type === 'service') { const sb = await db.from('service_bookings').select('event_date, event_time, guest_count, venue, notes').eq('order_id', r.id).maybeSingle(); if (sb && sb.data) booking = { kind: 'service', ...sb.data }; }
      }
    } catch (e) {}
    setViewingOrder({ ...detail, booking });
  };
  const [tiers, setTiers]           = useStateAD([]);
  const [orders, setOrders]         = useStateAD([]);
  const [leads, setLeads]           = useStateAD([]);
  const [leadAssigns, setLeadAssigns] = useStateAD({});
  const [rfqs, setRfqs]             = useStateAD([]);
  const [loading, setLoading]       = useStateAD(true);
  const [confirm, setConfirm]       = useStateAD(null);
  const [tierEdit, setTierEdit]     = useStateAD(null);
  const [tierBusy, setTierBusy]     = useStateAD(false);
  const [busyId, setBusyId]         = useStateAD('');
  const [activationModal, setActivationModal] = useStateAD(null);
  const [activationBusy, setActivationBusy]   = useStateAD(false);

  // Register global so AdminBar can switch tabs without full navigation
  useEffectAD(() => {
    window.setAdminDashboardTab = (tab) => setActiveTab(tab);
    return () => { window.setAdminDashboardTab = null; };
  }, []);

  // Map of lead -> assigned vendor ids (for the Assign column count + broadcast).
  useEffectAD(() => {
    if (!db) return;
    db.from('lead_assignments').select('lead_id, vendor_id').then(({ data }) => {
      const m = {}; (data || []).forEach((a) => { (m[a.lead_id] = m[a.lead_id] || []).push(a.vendor_id); }); setLeadAssigns(m);
    });
  }, [db, leads]);

  const load = useCallbackAD(async () => {
    if (!db) { setLoading(false); return; }
    setLoading(true);

    // Safe fetch wrapper — never rejects; returns default on any error
    const safe = (promise, fallback = { data: [], count: 0 }) =>
      promise.then((res) => res.error ? fallback : res).catch(() => fallback);

    try {
      const [vendorRes, payoutRes, complaintRes, tierRes, prodCount, rentCount, svcCount, orderRes, leadRes, rfqRes, custCount, subCount, notifRes] = await Promise.all([
        safe(db.from('vendor_profiles').select('*, profiles(display_name, phone)').order('created_at', { ascending: false })),
        safe(db.from('payouts').select('*, vendor_profiles(trade_name), orders(reference)').order('created_at', { ascending: false }).limit(100)),
        safe(db.from('complaints').select('*, orders(reference)').order('created_at', { ascending: false }).limit(50)),
        safe(db.from('subscription_tiers').select('*').order('sort_order')),
        safe(db.from('products').select('id', { count: 'exact', head: true }), { count: 0 }),
        safe(db.from('rentals').select('id', { count: 'exact', head: true }), { count: 0 }),
        safe(db.from('services').select('id', { count: 'exact', head: true }), { count: 0 }),
        safe(db.from('orders').select('id, reference, type, total_amount, status, paid_at, created_at, guest_name, guest_email, guest_phone, profiles!customer_id(display_name)').order('created_at', { ascending: false }).limit(50)),
        safe(db.from('leads').select('*').order('created_at', { ascending: false }).limit(100)),
        safe(db.from('rfq_requests').select('*').order('created_at', { ascending: false }).limit(50)),
        safe(db.from('profiles').select('id', { count: 'exact', head: true }).eq('role', 'customer'), { count: 0 }),
        safe(db.from('subscriptions').select('id', { count: 'exact', head: true }).in('status', ['trialing','active']), { count: 0 }),
        safe(db.from('notifications').select('*').order('created_at', { ascending: false }).limit(300)),
      ]);

      const allVendors = vendorRes.data || [];
      const allPayouts = payoutRes.data || [];
      const allOrders  = orderRes.data  || [];

      setVendors(allVendors);
      setPayouts(allPayouts);
      setComplaints(complaintRes.data || []);
      setNotifications(notifRes.data || []);
      setTiers(tierRes.data || []);
      setOrders(allOrders);
      setLeads(leadRes.data || []);
      setRfqs(rfqRes.data || []);

      setStats({
        totalVendors:     allVendors.length,
        activeVendors:    allVendors.filter((v) => ['active','approved'].includes(v.status)).length,
        pendingApproval:  allVendors.filter((v) => ['pending_approval','agreement_accepted','under_review'].includes(v.status)).length,
        pendingPayouts:   allPayouts.filter((p) => p.status === 'pending').reduce((s, p) => s + Number(p.amount), 0),
        heldPayouts:      allPayouts.filter((p) => p.status === 'on_hold').reduce((s, p) => s + Number(p.amount), 0),
        totalProducts:    prodCount.count  || 0,
        totalRentals:     rentCount.count  || 0,
        totalServices:    svcCount.count   || 0,
        pendingOrders:    allOrders.filter((o) => o.status === 'pending').length,
        totalRevenue:     allOrders.reduce((s, o) => s + Number(o.total_amount || 0), 0),
        totalLeads:       (leadRes.data || []).length,
        openRfqs:         (rfqRes.data || []).filter((r) => r.status === 'open').length,
        openComplaints:   (complaintRes.data || []).filter((c) => c.status === 'open').length,
        totalCustomers:   custCount.count  || 0,
        activeSubsc:      subCount.count   || 0,
      });
    } catch (e) {
      console.error('AdminDashboard load error:', e);
      // Show empty stats rather than a blank screen
      setStats({ totalVendors:0, activeVendors:0, pendingApproval:0, pendingPayouts:0, heldPayouts:0, totalProducts:0, totalRentals:0, totalServices:0, pendingOrders:0, totalRevenue:0, totalLeads:0, openRfqs:0, openComplaints:0, totalCustomers:0, activeSubsc:0 });
    } finally {
      setLoading(false);
    }
  }, [db]);

  useEffectAD(() => { load(); }, [load]);

  /* ---- vendor status actions ---- */
  const setVendorStatus = async (vendorId, status, reason) => {
    // Activation gate: a vendor can only be approved/activated once KYC + settlement
    // details are complete (also enforced by a DB trigger). Show what's missing.
    if (status === 'approved' || status === 'active') {
      try {
        const { data: st } = await db.rpc('vendor_activation_status', { vid: vendorId });
        if (st) {
          const LABELS = { trade_license_number: 'Trade license number', trade_license_expiry: 'Trade license expiry', trade_license_doc: 'Trade license document', id_doc: 'Emirates ID document', bank_name: 'Bank name', bank_iban: 'Bank IBAN', bank_account_name: 'Account holder name', iban_doc: 'IBAN / bank-letter document' };
          const missingKeys = Object.keys(LABELS).filter((k) => !st[k]);
          if (missingKeys.length) {
            let values = {};
            try {
              const { data: vp } = await db.from('vendor_profiles').select('trade_license_number, trade_license_expiry').eq('id', vendorId).maybeSingle();
              if (vp) { values.trade_license_number = vp.trade_license_number || ''; values.trade_license_expiry = vp.trade_license_expiry || ''; }
              const { data: vb } = await db.from('vendor_banking').select('bank_name, bank_iban, bank_account_name').eq('vendor_id', vendorId).maybeSingle();
              if (vb) { values.bank_name = vb.bank_name || ''; values.bank_iban = vb.bank_iban || ''; values.bank_account_name = vb.bank_account_name || ''; }
            } catch (e) {}
            setActivationModal({ vendorId, status, missing: missingKeys, values });
            return;
          }
        }
      } catch (e) {}
    }
    setBusyId(vendorId);
    const update = { status };
    if (reason) update.rejection_reason = reason;
    const { error: stErr } = await db.from('vendor_profiles').update(update).eq('id', vendorId);
    if (stErr) { setBusyId(''); window.alert(String(stErr.message).replace(/^.*VENDOR_NOT_READY:\s*/, '')); return; }
    await sarayaNotify(vendorId, 'vendor_status', `Your vendor account status has changed to: ${status}`);
    await sarayaLogActivity({ action: `vendor_${status}`, entityType: 'vendor', entityId: vendorId, details: { reason } });
    setBusyId('');
    load();
  };

  /* ---- vendor activation: complete details, or approve as exception ---- */
  const doSaveActivate = async (fields) => {
    const m = activationModal; if (!m || !db) return { error: 'No vendor selected.' };
    setActivationBusy(true);
    try {
      const { error: e1 } = await db.from('vendor_profiles').update({
        trade_license_number: (fields.trade_license_number || '').trim() || null,
        trade_license_expiry: (fields.trade_license_expiry || '').trim() || null,
      }).eq('id', m.vendorId);
      if (e1) { setActivationBusy(false); return { error: e1.message }; }
      const { error: e2 } = await db.from('vendor_banking').upsert({
        vendor_id: m.vendorId,
        bank_name: (fields.bank_name || '').trim() || null,
        bank_iban: (fields.bank_iban || '').trim() || null,
        bank_account_name: (fields.bank_account_name || '').trim() || null,
      }, { onConflict: 'vendor_id' });
      if (e2) { setActivationBusy(false); return { error: e2.message }; }
      const { error: e3 } = await db.from('vendor_profiles').update({ status: m.status }).eq('id', m.vendorId);
      if (e3) { setActivationBusy(false); return { error: String(e3.message).replace(/^.*VENDOR_NOT_READY:\s*/, 'Still missing required items: ') }; }
      try { await sarayaNotify(m.vendorId, 'vendor_status', 'Your vendor account status has changed to: ' + m.status); } catch (e) {}
      try { await sarayaLogActivity({ action: 'vendor_' + m.status, entityType: 'vendor', entityId: m.vendorId, details: { via: 'admin_completed_details' } }); } catch (e) {}
      setActivationBusy(false); setActivationModal(null); load();
      return {};
    } catch (e) { setActivationBusy(false); return { error: String((e && e.message) || e) }; }
  };
  const doOverrideActivate = async (reason) => {
    const m = activationModal; if (!m || !db) return { error: 'No vendor selected.' };
    setActivationBusy(true);
    try {
      const upd = { status: m.status, activation_override: true, activation_override_reason: reason, activation_override_at: new Date().toISOString() };
      try { if (user && user.id) upd.activation_override_by = user.id; } catch (e) {}
      const { error } = await db.from('vendor_profiles').update(upd).eq('id', m.vendorId);
      if (error) { setActivationBusy(false); return { error: String(error.message) }; }
      try { await sarayaNotify(m.vendorId, 'vendor_status', 'Your vendor account status has changed to: ' + m.status); } catch (e) {}
      try { await sarayaLogActivity({ action: 'vendor_' + m.status + '_override', entityType: 'vendor', entityId: m.vendorId, details: { reason, override: true } }); } catch (e) {}
      setActivationBusy(false); setActivationModal(null); load();
      return {};
    } catch (e) { setActivationBusy(false); return { error: String((e && e.message) || e) }; }
  };

  /* ---- payout actions ---- */
  const setPayoutStatus = async (payoutId, status, note) => {
    setBusyId(payoutId);
    const update = { status };
    if (status === 'approved') update.approved_by = user.id, update.approved_at = new Date().toISOString();
    if (status === 'paid')     update.paid_at = new Date().toISOString();
    if (note) update.notes = note;
    await db.from('payouts').update(update).eq('id', payoutId);
    setBusyId('');
    load();
  };

  /* ---- vendor details / notify ---- */
  const openVendorDetailsWindow = (v) => {
    const w = window.open('', '_blank', 'width=760,height=840');
    if (!w) return;
    const esc = (s) => (s == null ? '' : String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'));
    const row = (label, val) => (val == null || val === '') ? '' : (
      '<div style="display:flex;padding:8px 0;border-bottom:1px solid #EEE;"><div style="width:180px;color:#6B7280;font-size:13px;">' + esc(label) + '</div><div style="flex:1;font-size:14px;">' + esc(val) + '</div></div>'
    );
    const html = '<!doctype html><html><head><meta charset="utf-8"><title>' + esc(v.trade_name || 'Vendor Details') +
      '</title><style>body{font-family:-apple-system,Segoe UI,Arial,sans-serif;margin:0;padding:24px;color:#111827;}h1{font-size:20px;margin:0 0 4px;}img{border-radius:8px;border:1px solid #E5E7EB;}</style></head><body>' +
      (v.logo_url ? '<img src="' + esc(v.logo_url) + '" style="width:80px;height:80px;object-fit:cover;margin-bottom:12px;">' : '') +
      '<h1>' + esc(v.trade_name) + '</h1>' +
      (v.trade_name_ar ? '<div style="color:#6B7280;margin-bottom:12px;">' + esc(v.trade_name_ar) + '</div>' : '') +
      row('Status', v.status) +
      row('City', v.city) +
      row('WhatsApp', v.whatsapp) +
      row('Website', v.website) +
      row('Instagram', v.instagram) +
      row('Category', v.business_category) +
      row('Trade License #', v.trade_license_number) +
      row('License Expiry', v.trade_license_expiry) +
      row('Commission Rate', v.commission_rate != null ? ((v.commission_rate * 100) + '%') : null) +
      row('Description (EN)', v.description_en) +
      row('Description (AR)', v.description_ar) +
      row('Registered', v.created_at ? new Date(v.created_at).toLocaleString() : null) +
      row('Agreement', v.agreement_signed_at ? ('Signed v' + (v.agreement_version || '1.0') + ' — ' + new Date(v.agreement_signed_at).toLocaleString()) : 'Not signed') +
      row('Payout (Stripe KYC)', v.connect_payouts_enabled ? 'Active — payouts enabled' : (v.connect_details_submitted ? 'Onboarding submitted (pending)' : 'Not connected')) +
      (v.agreement_signed_at ? '<button id="dlAgr" style="margin-top:20px;padding:10px 18px;background:#c19a3e;color:#fff;border:none;border-radius:8px;font-size:14px;cursor:pointer;">Download signed agreement</button>' : '') +
      '<script>var b=document.getElementById("dlAgr");if(b){b.addEventListener("click",function(){try{window.opener.SarayaAgreement.downloadDoc(' + JSON.stringify({ tradeName: v.trade_name, signedAt: v.agreement_signed_at, version: v.agreement_version || '1.0' }) + ');}catch(e){alert("Keep the Saraya admin tab open, then try again.");}});}<\/script>' +
      '<div style="margin-top:22px;padding:14px 16px;border:1px solid #E5E7EB;border-radius:10px;background:#FAFAFA;">' +
        '<div style="font-weight:600;margin-bottom:4px;">Featured &amp; verification</div>' +
        '<div style="font-size:12px;color:#6B7280;margin-bottom:10px;">A vendor appears in Featured only when Verified + Featured are on, the profile is 100% complete, the trade licence is valid, there are at least 5 approved active listings, and the vendor holds an active Growth or Premium subscription.</div>' +
        '<label style="display:block;font-size:13px;margin-bottom:8px;"><input type="checkbox" id="chkVerified"' + (v.is_verified ? ' checked' : '') + '> Verified vendor</label>' +
        '<label style="display:block;font-size:13px;margin-bottom:8px;"><input type="checkbox" id="chkFeatured"' + (v.is_featured ? ' checked' : '') + '> Featured on homepage</label>' +
        '<div style="font-size:13px;margin-bottom:10px;">Featured order: <input type="number" id="numOrder" value="' + (v.featured_order != null ? v.featured_order : '') + '" style="width:72px;padding:5px;border:1px solid #ccc;border-radius:6px;"></div>' +
        '<button id="btnSaveFeat" style="padding:8px 16px;background:#111827;color:#fff;border:none;border-radius:8px;cursor:pointer;">Save</button>' +
        ' <span id="featMsg" style="font-size:12px;margin-inline-start:8px;"></span>' +
      '</div>' +
      '<script>(function(){var b=document.getElementById("btnSaveFeat");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("numOrder").value;var patch={is_verified:document.getElementById("chkVerified").checked,is_featured:document.getElementById("chkFeatured").checked,featured_order:o===""?null:parseInt(o,10)};var m=document.getElementById("featMsg");m.textContent="Saving…";try{window.opener.sarayaAdminVendorPatch(' + JSON.stringify(v.id) + ',patch).then(function(ok){m.style.color=ok?"#15803D":"#B91C1C";m.textContent=ok?"Saved":"Failed";});}catch(e){m.style.color="#B91C1C";m.textContent="Open the admin tab and retry";}});})();<\/script>' +
      '</body></html>';
    w.document.write(html);
    w.document.close();
  };

  // Bridge for the vendor-details popup's Featured/verification save button.
  window.sarayaAdminVendorPatch = async (id, patch) => {
    try { const { error } = await db.from('vendor_profiles').update(patch).eq('id', id); if (!error && typeof load === 'function') load(); return !error; }
    catch (e) { return false; }
  };

  const notifyVendor = async (vendorId, tradeName) => {
    setBusyId(vendorId);
    try {
      const { data: vendorEmail, error: rpcErr } = await db.rpc('admin_get_vendor_email', { p_vendor_id: vendorId });
      if (rpcErr || !vendorEmail) {
        window.alert('Could not find a login email for this vendor.');
      } else {
        await db.auth.signInWithOtp({ email: vendorEmail, options: { shouldCreateUser: false, emailRedirectTo: window.location.origin + '/#vendor-dashboard' } });
        await sarayaNotify(vendorId, 'vendor_status', 'Please sign in and complete your vendor profile to get approved.');
        await sarayaLogActivity({ action: 'vendor_notify_complete_profile', entityType: 'vendor', entityId: vendorId, details: { trade_name: tradeName } });
        window.alert('Notification sent to ' + tradeName + '.');
      }
    } catch (e) {
      window.alert('Failed to notify vendor: ' + (e && e.message ? e.message : e));
    }
    setBusyId('');
  };

  /* ---- give free subscription ---- */
  const giveFreeAccess = async (vendorId, tierId) => {
    await db.from('subscriptions').upsert({
      vendor_id: vendorId,
      tier_id: tierId,
      status: 'active',
      is_free_access: true,
      current_period_start: new Date().toISOString(),
      current_period_end: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(),
    }, { onConflict: 'vendor_id' });
    load();
  };

  /* ---- tier save ---- */
  const saveTier = async (e) => {
    e.preventDefault();
    if (!tierEdit || !db) return;
    setTierBusy(true);
    const payload = { ...tierEdit };
    delete payload.created_at; delete payload.updated_at;
    payload.price_monthly = Number(payload.price_monthly) || 0;
    payload.price_annual = Number(payload.price_annual) || 0;
    payload.discount_percent = Math.max(0, Math.min(100, Number(payload.discount_percent) || 0));
    payload.commission_rate_override = (payload.commission_rate_override === '' || payload.commission_rate_override == null) ? null : Number(payload.commission_rate_override);
    payload.max_listings = parseInt(payload.max_listings) || 0;
    if (payload.id) {
      await db.from('subscription_tiers').update(payload).eq('id', payload.id);
    } else {
      await db.from('subscription_tiers').insert({ ...payload, sort_order: tiers.length + 1 });
    }
    setTierBusy(false);
    setTierEdit(null);
    load();
  };

  /* ---- guard ---- */
  if (!window.supabaseConfigured) {
    return (
      <main style={{ paddingTop: 120, minHeight: '60vh' }}>
        <Container narrow style={{ textAlign: 'center' }}>
          <Icon name="database" size={44} stroke={1} style={{ color: 'var(--fg-muted)' }} />
          <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 28, fontWeight: 500, marginTop: 14 }}>Database Not Configured</h2>
          <p style={{ color: 'var(--fg-secondary)', marginTop: 8 }}>Fill in src/config.js with your Supabase credentials.</p>
        </Container>
      </main>
    );
  }

  if (authLoading) {
    return (
      <main style={{ paddingTop: 120, minHeight: '60vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ width: 36, height: 36, border: '3px solid var(--line)', borderTopColor: 'var(--gold)', borderRadius: '50%', animation: 'spin 0.8s linear infinite' }} />
      </main>
    );
  }

  if (!user) {
    return (
      <main style={{ paddingTop: 120, minHeight: '60vh' }}>
        <Container narrow style={{ textAlign: 'center' }}>
          <Icon name="lock" size={44} stroke={1} style={{ color: 'var(--fg-muted)' }} />
          <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 28, fontWeight: 500, marginTop: 14 }}>Please Sign In</h2>
          <Button variant="primary" style={{ marginTop: 18 }} onClick={() => openAuthModal('login')}>Sign In</Button>
        </Container>
      </main>
    );
  }

  if (!isAdmin && !isStaff) {
    return (
      <main style={{ paddingTop: 120, minHeight: '60vh' }}>
        <Container narrow style={{ textAlign: 'center' }}>
          <Icon name="shield-off" size={44} stroke={1} style={{ color: 'var(--fg-muted)' }} />
          <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 28, fontWeight: 500, marginTop: 14 }}>Admin Access Required</h2>
        </Container>
      </main>
    );
  }

  const TABS = [
    { key: 'overview',    icon: 'layout-dashboard', label: 'Overview', group: 'main' },
    { key: 'orders',      icon: 'package',          label: 'Orders',       badge: stats?.pendingOrders || 0, group: 'ops' },
    { key: 'rfqs',        icon: 'file-text',        label: 'RFQs',         badge: stats?.openRfqs || 0, group: 'ops' },
    { key: 'leads',       icon: 'inbox',            label: 'Leads', group: 'ops' },
    { key: 'complaints',  icon: 'alert-circle',     label: 'Complaints',   badge: stats?.openComplaints || 0, group: 'ops' },
    { key: 'customer_requests',    icon: 'message-square',   label: 'Customer Requests', badge: (stats?.openRfqs || 0) + (stats?.openComplaints || 0), group: 'ops' },
    { key: 'staff_tasks',          icon: 'check-square',     label: 'Staff Tasks', badge: (stats?.pendingApproval || 0) + (stats?.openComplaints || 0), group: 'ops' },
    { key: 'marketplace', icon: 'shopping-bag',     label: 'Marketplace', group: 'catalog' },
    { key: 'marketplace_activity', icon: 'trending-up',      label: 'Marketplace Activity', group: 'catalog' },
    { key: 'vendors',     icon: 'store',            label: 'Vendors',      badge: stats?.pendingApproval || 0, group: 'vendors' },
    { key: 'subscriptions', icon: 'repeat',           label: 'Subscriptions', group: 'vendors' },
    { key: 'tiers',       icon: 'layers',           label: 'Sub. Tiers', group: 'vendors' },
    { key: 'meetings',    icon: 'headset',          label: 'Vendor Meetings', group: 'vendors' },
    { key: 'payouts',     icon: 'banknote',         label: 'Payouts', group: 'vendors' },
    { key: 'finance',     icon: 'credit-card',      label: 'Finance', group: 'vendors' },
    { key: 'marketing',   icon: 'megaphone',        label: 'Marketing', group: 'growth' },
    { key: 'content',     icon: 'file-edit',        label: 'Content', group: 'growth' },
    { key: 'users',       icon: 'users',            label: 'Users', group: 'system' },
    { key: 'notifications', icon: 'bell', label: 'Notifications', group: 'system' },
    { key: 'activity',    icon: 'activity',         label: 'Activity Log', group: 'system' },
    { key: 'ai_agent_notes',       icon: 'bot',              label: 'AI Agent Notes', group: 'system' },
    { key: 'tools',       icon: 'wrench',           label: 'Tools', group: 'system' },
  ];
  const NAV_GROUPS = [
    { id: 'main', label: '' },
    { id: 'ops', label: 'Operations' },
    { id: 'catalog', label: 'Catalog' },
    { id: 'vendors', label: 'Vendors & Billing' },
    { id: 'growth', label: 'Growth' },
    { id: 'system', label: 'System' },
  ];

  return (
    <main style={{ paddingTop: 80, minHeight: '100vh', background: 'var(--bg-canvas)' }}>
      {toastsAD.length > 0 && (
        <div style={{ position: 'fixed', top: 90, right: 20, zIndex: 9999, display: 'grid', gap: 10, maxWidth: 340 }}>
          {toastsAD.map((t) => (
            <div
              key={t.id}
              onClick={() => { if (window.setAdminDashboardTab) window.setAdminDashboardTab('notifications'); dismissToastAD(t.id); }}
              style={{ background: 'var(--white)', border: '1px solid var(--line)', borderInlineStart: '4px solid var(--gold)', borderRadius: 12, padding: '14px 16px', boxShadow: '0 8px 24px rgba(0,0,0,0.18)', cursor: 'pointer' }}
            >
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 8 }}>
                <div style={{ fontWeight: 700, fontSize: 13.5 }}>{t.title || 'New notification'}</div>
                <button onClick={(e) => { e.stopPropagation(); dismissToastAD(t.id); }} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--fg-muted)', fontSize: 16, lineHeight: 1, padding: 0 }}>×</button>
              </div>
              {t.body && <div style={{ fontSize: 12.5, color: 'var(--fg-secondary)', marginTop: 4, lineHeight: 1.5 }}>{t.body}</div>}
            </div>
          ))}
        </div>
      )}
      <div className="saraya-vd-shell" style={{ display: 'flex', maxWidth: 1400, margin: '0 auto', padding: '0 16px', gap: 0 }}>

        {/* Sidebar */}
        <aside className="saraya-vd-sidebar" style={{ width: 220, flexShrink: 0, paddingTop: 20, paddingBottom: 40, paddingRight: 16 }}>
          <div style={{ background: 'var(--white)', borderRadius: 16, border: '1px solid var(--line)', overflow: 'hidden', position: 'sticky', top: 90 }}>
            <div style={{ padding: '18px 16px 12px', borderBottom: '1px solid var(--line)' }}>
              <Badge tone="gold">Staff</Badge>
              <p style={{ fontFamily: 'var(--font-display)', fontSize: 17, fontWeight: 500, margin: '6px 0 0', color: 'var(--fg-primary)' }}>Saraya Staff Operations</p>
            </div>
            <nav style={{ padding: '8px 8px' }}>
              {NAV_GROUPS.map((g) => {
                const groupTabs = TABS.filter((t) => t.group === g.id && canSeeTab(t.key));
                if (!groupTabs.length) return null;
                return (
                  <div key={g.id} style={{ marginBottom: 4 }}>
                    {g.label && <div style={{ padding: '10px 12px 4px', fontSize: 10, fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--fg-muted)' }}>{g.label}</div>}
                    {groupTabs.map((t) => (
                      <button key={t.key} onClick={() => setActiveTab(t.key)} style={{
                        width: '100%', display: 'flex', alignItems: 'center', gap: 10,
                        padding: '9px 12px', borderRadius: 8, border: 'none', marginBottom: 2,
                        background: activeTab === t.key ? 'var(--espresso)' : 'transparent',
                        color: activeTab === t.key ? 'var(--white)' : 'var(--fg-secondary)',
                        fontFamily: 'var(--font-body)', fontSize: 13.5,
                        fontWeight: activeTab === t.key ? 600 : 400,
                        cursor: 'pointer', transition: 'all 160ms', textAlign: 'left',
                      }}>
                        <Icon name={t.icon} size={15} style={{ flexShrink: 0 }} />
                        <span style={{ flex: 1 }}>{t.label}</span>
                        {t.badge > 0 && (
                          <span style={{ display: 'inline-flex', minWidth: 20, height: 20, borderRadius: 10, background: '#EF4444', color: '#fff', fontSize: 11, fontWeight: 700, alignItems: 'center', justifyContent: 'center', padding: '0 5px' }}>
                            {t.badge}
                          </span>
                        )}
                      </button>
                    ))}
                  </div>
                );
              })}
            </nav>
            <div style={{ padding: '12px 16px', borderTop: '1px solid var(--line)' }}>
              <Button variant="secondary" icon="refresh-cw" onClick={load} style={{ width: '100%', justifyContent: 'center' }}>Refresh</Button>
            </div>
          </div>
        </aside>

        {/* Main content */}
        <div style={{ flex: 1, minWidth: 0, paddingTop: 20, paddingBottom: 40 }}>

        {loading ? (
          <div style={{ textAlign: 'center', padding: 80, color: 'var(--fg-muted)' }}>
            <Icon name="loader" size={36} style={{ animation: 'sarayaSpin 1s linear infinite' }} />
            <p style={{ marginTop: 16, fontSize: 14 }}>Loading platform data…</p>
          </div>
        ) : (
          <>
            {/* OVERVIEW */}
            {activeTab === 'overview' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(180px,1fr))', gap: 14 }}>
                  <AdminStat icon="store"          label="Total Vendors"      value={stats.totalVendors} />
                  <AdminStat icon="user-check"     label="Pending Approval"   value={stats.pendingApproval}  tone="warning" />
                  <AdminStat icon="users"          label="Total Customers"    value={stats.totalCustomers} />
                  <AdminStat icon="inbox"          label="New Leads"          value={stats.totalLeads} />
                  <AdminStat icon="file-text"      label="Open RFQs"          value={stats.openRfqs}         tone={stats.openRfqs > 0 ? 'warning' : 'gold'} />
                  <AdminStat icon="package"        label="Pending Orders"     value={stats.pendingOrders}    tone={stats.pendingOrders > 0 ? 'warning' : 'gold'} />
                  <AdminStat icon="repeat"         label="Active Subscriptions" value={stats.activeSubsc}    tone="success" />
                  <AdminStat icon="alert-circle"   label="Open Complaints"    value={stats.openComplaints}   tone={stats.openComplaints > 0 ? 'danger' : 'gold'} />
                  <AdminStat icon="banknote"       label="Pending Payouts"    value={'AED ' + stats.pendingPayouts.toFixed(0)} tone="warning" />
                  <AdminStat icon="trending-up"    label="Total Revenue"      value={'AED ' + stats.totalRevenue.toFixed(0)} tone="success" />
                  <AdminStat icon="shopping-bag"   label="Products"           value={stats.totalProducts} />
                  <AdminStat icon="archive"        label="Rental Items"       value={stats.totalRentals} />
                </div>

                {/* Action alerts */}
                <div style={{ display: 'grid', gap: 10 }}>
                  {stats.pendingApproval > 0 && (
                    <div onClick={() => setActiveTab('vendors')} style={{ padding: '14px 18px', borderRadius: 10, background: '#FFFBEB', border: '1.5px solid #FCD34D', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 12 }}>
                      <Icon name="alert-triangle" size={18} style={{ color: '#D97706' }} />
                      <span style={{ fontWeight: 600, fontSize: 14 }}>{stats.pendingApproval} vendor{stats.pendingApproval !== 1 ? 's' : ''} awaiting approval</span>
                      <Icon name="chevron-right" size={15} style={{ marginInlineStart: 'auto', color: '#D97706' }} />
                    </div>
                  )}
                  {stats.openRfqs > 0 && (
                    <div onClick={() => setActiveTab('rfqs')} style={{ padding: '14px 18px', borderRadius: 10, background: '#EFF6FF', border: '1.5px solid #93C5FD', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 12 }}>
                      <Icon name="file-text" size={18} style={{ color: '#1D4ED8' }} />
                      <span style={{ fontWeight: 600, fontSize: 14 }}>{stats.openRfqs} open RFQ request{stats.openRfqs !== 1 ? 's' : ''}</span>
                      <Icon name="chevron-right" size={15} style={{ marginInlineStart: 'auto', color: '#1D4ED8' }} />
                    </div>
                  )}
                  {stats.openComplaints > 0 && (
                    <div onClick={() => setActiveTab('complaints')} style={{ padding: '14px 18px', borderRadius: 10, background: '#FEF2F2', border: '1.5px solid #FCA5A5', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 12 }}>
                      <Icon name="alert-circle" size={18} style={{ color: '#B91C1C' }} />
                      <span style={{ fontWeight: 600, fontSize: 14 }}>{stats.openComplaints} open complaint{stats.openComplaints !== 1 ? 's' : ''}</span>
                      <Icon name="chevron-right" size={15} style={{ marginInlineStart: 'auto', color: '#B91C1C' }} />
                    </div>
                  )}
                </div>

                {/* Quick nav grid */}
                <div>
                  <h3 style={{ fontFamily: 'var(--font-display)', fontSize: 18, fontWeight: 500, marginBottom: 14 }}>Quick Access</h3>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(180px,1fr))', gap: 10 }}>
                    {[
                      { tab: 'orders',      icon: 'package',      label: 'Orders & Bookings' },
                      { tab: 'rfqs',        icon: 'file-text',    label: 'RFQ Requests' },
                      { tab: 'leads',       icon: 'inbox',        label: 'Leads & Inquiries' },
                      { tab: 'vendors',     icon: 'store',        label: 'Vendor Management' },
                      { tab: 'marketplace', icon: 'shopping-bag', label: 'Marketplace Listings' },
                      { tab: 'payouts',     icon: 'banknote',     label: 'Vendor Payouts' },
                      { tab: 'finance',     icon: 'credit-card',  label: 'Finance & Payments' },
                      { tab: 'marketing',   icon: 'megaphone',    label: 'Marketing' },
                      { tab: 'content',     icon: 'file-edit',    label: 'Content & Pages' },
                      { tab: 'tiers',       icon: 'layers',       label: 'Subscription Tiers' },
                      { tab: 'users',       icon: 'users',        label: 'Users & Roles' },
                      { tab: 'tools',       icon: 'wrench',       label: 'Developer Tools' },
                    ].map((q) => (
                      <button key={q.tab} onClick={() => setActiveTab(q.tab)} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '12px 14px', borderRadius: 10, background: 'var(--white)', border: '1px solid var(--line)', cursor: 'pointer', fontFamily: 'var(--font-body)', fontSize: 13, color: 'var(--fg-primary)', transition: 'all 120ms', textAlign: 'left' }}
                        onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--gold)'; e.currentTarget.style.background = 'var(--cream)'; }}
                        onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.background = 'var(--white)'; }}>
                        <Icon name={q.icon} size={16} style={{ color: 'var(--gold-deep)', flexShrink: 0 }} />
                        {q.label}
                      </button>
                    ))}
                  </div>
                </div>
              </div>
            )}

            {/* VENDORS */}
            {activeTab === 'vendors' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <VendorManagementPanel vendors={vendors} tiers={tiers} stats={stats} db={db} busyId={busyId} setVendorStatus={setVendorStatus} giveFreeAccess={giveFreeAccess} notifyVendor={notifyVendor} openVendorDetailsWindow={openVendorDetailsWindow} setConfirm={setConfirm} reload={load} />
              </div>
            )}

            {/* VENDOR MEETING REQUESTS */}
            {activeTab === 'meetings' && (
              <window.AdminMeetingRequests ar={false} />
            )}

            {/* PAYOUTS */}
            {activeTab === 'payouts' && (
              <AdminSection title="Payout Management" desc="Approve, hold, or release vendor payouts.">
                <AdminTable
                  emptyMsg="No payouts yet"
                  cols={[
                    { key: 'id',       label: 'ID',     render: (r) => <code style={{ fontSize: 11 }}>{r.id.slice(0, 8)}…</code> },
                    { key: 'vendor',   label: 'Vendor', render: (r) => r.vendor_profiles?.trade_name || '—' },
                    { key: 'order',    label: 'Order',  render: (r) => r.orders?.reference || '—' },
                    { key: 'amount',   label: 'Amount', render: (r) => `AED ${Number(r.amount).toFixed(2)}` },
                    { key: 'status',   label: 'Status', render: (r) => <StatusBadge status={r.status} /> },
                    { key: 'hold_reason', label: 'Hold Reason', wrap: true },
                    {
                      key: 'actions', label: 'Actions',
                      render: (r) => (
                        <div style={{ display: 'flex', gap: 6 }}>
                          {r.status === 'pending' && (
                            <>
                              <Button variant="primary"   small loading={busyId === r.id} onClick={() => { setBusyId(r.id); setPayoutStatus(r.id, 'approved'); }}>Approve</Button>
                              <Button variant="ghost"     small danger onClick={() => { const reason = window.prompt('Hold reason:'); if (reason !== null) setPayoutStatus(r.id, 'on_hold', reason); }}>Hold</Button>
                            </>
                          )}
                          {r.status === 'approved' && (
                            <Button variant="primary" small loading={busyId === r.id} onClick={() => setPayoutStatus(r.id, 'paid')}>Mark Paid</Button>
                          )}
                          {r.status === 'on_hold' && (
                            <Button variant="secondary" small loading={busyId === r.id} onClick={() => setPayoutStatus(r.id, 'approved')}>Release</Button>
                          )}
                        </div>
                      ),
                    },
                  ]}
                  rows={payouts}
                />
              </AdminSection>
            )}

            {/* COMPLAINTS */}
            {activeTab === 'complaints' && (
              <AdminSection title="Complaints" desc="Manage complaints and disputes submitted via the complaint form. WhatsApp is not used for official case handling.">
                <AdminTable
                  emptyMsg="No complaints yet"
                  cols={[
                    { key: 'reference', label: 'Ref' },
                    { key: 'created_at', label: 'Date', render: (r) => r.created_at ? new Date(r.created_at).toLocaleDateString() : '—' },
                    { key: 'submitted_by', label: 'Submitted By', render: (r) => r.contact_name || r.profiles?.display_name || '—' },
                    { key: 'filed_by_role', label: 'User Type', render: (r) => ({ customer: 'Customer', vendor: 'Vendor' }[r.filed_by_role] || 'Other') },
                    { key: 'complaint_type', label: 'Type', render: (r) => COMPLAINT_TYPE_LABELS[r.complaint_type] || r.complaint_type || '—' },
                    { key: 'related', label: 'Related', render: (r) => r.orders?.reference || r.related_reference || '—' },
                    { key: 'status', label: 'Status', render: (r) => <StatusBadge status={r.status} /> },
                    {
                      key: 'actions', label: 'Actions',
                      render: (r) => (
                        <div style={{ display: 'flex', gap: 6 }}>
                          <Button variant="secondary" small onClick={() => setViewingComplaint(r)}>View</Button>
                          {r.status !== 'resolved' && r.status !== 'closed' && (
                            <>
                              <Button variant="secondary" small onClick={async () => {
                                const notes = window.prompt('Resolution notes:');
                                if (notes === null) return;
                                await db.from('complaints').update({ status: 'resolved', resolution_notes: notes, resolved_at: new Date().toISOString(), resolved_by: user.id }).eq('id', r.id);
                                if (r.payout_held) {
                                  await db.from('payouts').update({ status: 'approved', hold_reason: null }).eq('order_id', r.order_id);
                                }
                                load();
                              }}>Resolve</Button>
                              <Button variant="ghost" small danger onClick={async () => {
                                await db.from('complaints').update({ status: 'rejected' }).eq('id', r.id);
                                load();
                              }}>Reject</Button>
                            </>
                          )}
                        </div>
                      ),
                    },
                  ]}
                  rows={complaints}
                />
              </AdminSection>
            )}

            {activeTab === 'notifications' && (
              <AdminSection title="Notifications" desc="Global feed of every notification sent to customers and vendors across the platform.">
                <AdminTable
                  emptyMsg="No notifications yet"
                  cols={[
                    { key: 'created_at', label: 'Sent', render: (r) => new Date(r.created_at).toLocaleString() },
                    { key: 'type', label: 'Type' },
                    { key: 'title', label: 'Title' },
                    { key: 'body', label: 'Message', wrap: true },
                    { key: 'is_read', label: 'Read', render: (r) => (r.is_read ? 'Yes' : 'No') },
                  ]}
                  rows={notifications}
                />
              </AdminSection>
            )}

            {viewingComplaint && (
              <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000, padding: 20 }} onClick={() => setViewingComplaint(null)}>
                <div style={{ background: '#fff', borderRadius: 14, padding: 28, maxWidth: 560, width: '100%', maxHeight: '85vh', overflowY: 'auto' }} onClick={(e) => e.stopPropagation()}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 18 }}>
                    <h3 style={{ margin: 0, fontSize: 19, fontWeight: 700 }}>Complaint {viewingComplaint.reference}</h3>
                    <button onClick={() => setViewingComplaint(null)} style={{ border: 'none', background: 'none', fontSize: 22, cursor: 'pointer', color: '#6B7280', lineHeight: 1 }}>&times;</button>
                  </div>
                  <div style={{ display: 'grid', gap: 10, fontSize: 14 }}>
                    <div><strong>Status:</strong> <StatusBadge status={viewingComplaint.status} /></div>
                    <div><strong>Submitted:</strong> {viewingComplaint.created_at ? new Date(viewingComplaint.created_at).toLocaleString() : '—'}</div>
                    <div><strong>Last updated:</strong> {viewingComplaint.updated_at ? new Date(viewingComplaint.updated_at).toLocaleString() : '—'}</div>
                    <div><strong>Submitted by:</strong> {viewingComplaint.contact_name || viewingComplaint.profiles?.display_name || '—'}</div>
                    <div><strong>User type:</strong> {({ customer: 'Customer', vendor: 'Vendor' }[viewingComplaint.filed_by_role] || 'Other')}</div>
                    <div><strong>Email:</strong> {viewingComplaint.contact_email || '—'}</div>
                    <div><strong>Phone:</strong> {viewingComplaint.contact_phone || '—'}</div>
                    <div><strong>Complaint type:</strong> {COMPLAINT_TYPE_LABELS[viewingComplaint.complaint_type] || viewingComplaint.complaint_type || '—'}</div>
                    <div><strong>Related order/listing/vendor:</strong> {viewingComplaint.orders?.reference || viewingComplaint.related_reference || '—'}</div>
                    <div><strong>Description:</strong><div style={{ marginTop: 4, padding: 10, background: '#F9FAFB', borderRadius: 8, whiteSpace: 'pre-wrap' }}>{viewingComplaint.description}</div></div>
                    {viewingComplaint.attachment_url && (
                      <div>
                        <strong>Attachment:</strong>{' '}
                        <Button variant="secondary" small onClick={async () => {
                          const { data } = await db.storage.from('complaint-attachments').createSignedUrl(viewingComplaint.attachment_url, 300);
                          if (data?.signedUrl) window.open(data.signedUrl, '_blank');
                        }}>Open attachment</Button>
                      </div>
                    )}
                    <div style={{ marginTop: 6 }}>
                      <label style={{ fontWeight: 600, fontSize: 12.5, textTransform: 'uppercase', color: '#6B7280', display: 'block', marginBottom: 6 }}>Update Status</label>
                      <select
                        value={viewingComplaint.status}
                        onChange={async (e) => {
                          const newStatus = e.target.value;
                          await db.from('complaints').update({ status: newStatus }).eq('id', viewingComplaint.id);
                          setViewingComplaint({ ...viewingComplaint, status: newStatus });
                          load();
                        }}
                        style={{ padding: '8px 12px', borderRadius: 8, border: '1px solid #D1D5DB', fontSize: 14 }}
                      >
                        <option value="open">New</option>
                        <option value="under_review">Under Review</option>
                        <option value="awaiting_customer_response">Waiting for Customer</option>
                        <option value="awaiting_vendor_response">Waiting for Vendor</option>
                        <option value="resolved">Resolved</option>
                        <option value="closed">Closed</option>
                        <option value="escalated">Escalated</option>
                        <option value="rejected">Rejected</option>
                      </select>
                    </div>
                  </div>
                </div>
              </div>
            )}

            {viewingOrder && (() => {
              const o = viewingOrder;
              const money = (v) => 'AED ' + Number(v || 0).toFixed(2);
              const custName = o.profiles?.display_name || o.guest_name || 'Guest';
              const custPhone = o.profiles?.phone || o.guest_phone;
              const addr = (o.delivery_address && (o.delivery_address.address || o.delivery_address.emirate)) ? [o.delivery_address.address, o.delivery_address.emirate].filter(Boolean).join(', ') : '';
              const vName = (vendors.find((v) => v.id === o.vendor_id) || {}).trade_name;
              const pb = o.status === 'refunded' ? { l: 'Refunded', c: '#B91C1C', bg: '#FEE2E2' } : (o.paid_at ? { l: 'Paid', c: '#15803D', bg: '#DCFCE7' } : { l: 'Unpaid', c: '#6B7280', bg: '#F3F4F6' });
              const row = (label, val) => <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12 }}><span style={{ color: '#6B7280' }}>{label}</span><span style={{ fontWeight: 600 }}>{val}</span></div>;
              return (
                <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000, padding: 20 }} onClick={() => setViewingOrder(null)}>
                  <div style={{ background: '#fff', borderRadius: 14, padding: 28, maxWidth: 580, width: '100%', maxHeight: '85vh', overflowY: 'auto' }} onClick={(e) => e.stopPropagation()}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 18 }}>
                      <div>
                        <h3 style={{ margin: 0, fontSize: 19, fontWeight: 700 }}>Order {o.reference || o.id?.slice(0,8)}</h3>
                        <div style={{ fontSize: 12.5, color: '#6B7280', marginTop: 3, textTransform: 'capitalize' }}>{o.type || 'order'}{o.created_at ? ' · ' + new Date(o.created_at).toLocaleString() : ''}</div>
                      </div>
                      <button onClick={() => setViewingOrder(null)} style={{ border: 'none', background: 'none', fontSize: 22, cursor: 'pointer', color: '#6B7280', lineHeight: 1 }}>&times;</button>
                    </div>
                    {o._loading ? <div style={{ padding: 30, textAlign: 'center', color: '#6B7280' }}>Loading…</div> : (
                    <div style={{ display: 'grid', gap: 16, fontSize: 14 }}>
                      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
                        <span style={{ padding: '4px 12px', borderRadius: 20, fontSize: 12.5, fontWeight: 600, background: pb.bg, color: pb.c }}>{pb.l}</span>
                        <StatusBadge status={o.status} />
                        {o.paid_at ? <span style={{ fontSize: 12, color: '#6B7280' }}>Paid {new Date(o.paid_at).toLocaleDateString()}</span> : null}
                      </div>
                      {(o.order_items || []).length > 0 && (
                        <div>
                          <div style={{ fontSize: 11.5, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: '#6B7280', marginBottom: 6 }}>Items</div>
                          {(o.order_items || []).map((it) => (
                            <div key={it.id} style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 0', borderTop: '1px solid var(--line)', gap: 12 }}>
                              <div style={{ flex: 1 }}><div style={{ fontWeight: 500 }}>{it.name_en || it.name_ar}</div><div style={{ fontSize: 12, color: '#6B7280' }}>Qty {it.quantity} · {money(it.unit_price)} each</div></div>
                              <div style={{ fontWeight: 700 }}>{money(it.line_total)}</div>
                            </div>
                          ))}
                        </div>
                      )}
                      <div style={{ display: 'grid', gap: 5, padding: '12px 14px', background: '#F9FAFB', borderRadius: 10 }}>
                        {Number(o.subtotal) ? row('Subtotal', money(o.subtotal)) : null}
                        {Number(o.discount_amount) ? row('Discount', '−' + money(o.discount_amount)) : null}
                        {Number(o.delivery_fee) ? row('Delivery', money(o.delivery_fee)) : null}
                        {Number(o.vat_amount) ? row('VAT', money(o.vat_amount)) : null}
                        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, paddingTop: 6, borderTop: '1px solid var(--line)', fontSize: 15 }}><span style={{ fontWeight: 700 }}>Total</span><span style={{ fontWeight: 700, color: 'var(--gold-deep)' }}>{money(o.total_amount)}</span></div>
                        {Number(o.commission_amount) ? row('Platform commission', money(o.commission_amount)) : null}
                        {Number(o.vendor_payout_amount) ? row('Vendor payout', money(o.vendor_payout_amount)) : null}
                      </div>
                      <div>
                        <div style={{ fontSize: 11.5, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: '#6B7280', marginBottom: 6 }}>Customer &amp; Delivery</div>
                        <div style={{ display: 'grid', gap: 4 }}>
                          <div style={{ fontWeight: 600 }}>{custName}</div>
                          {custPhone ? <a href={'tel:' + custPhone} style={{ color: 'var(--gold-deep)', textDecoration: 'none' }}>{custPhone}</a> : null}
                          {o.guest_email ? <a href={'mailto:' + o.guest_email} style={{ color: 'var(--gold-deep)', textDecoration: 'none' }}>{o.guest_email}</a> : null}
                          {addr ? <div style={{ color: '#374151' }}>{addr}</div> : null}
                        </div>
                      </div>
                      {o.booking && (
                        <div>
                          <div style={{ fontSize: 11.5, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: '#6B7280', marginBottom: 6 }}>Booking</div>
                          <div style={{ fontWeight: 600 }}>{o.booking.kind === 'rental' ? ((o.booking.start_date || '') + ' → ' + (o.booking.end_date || '')) : ((o.booking.event_date || '') + (o.booking.event_time ? ' · ' + o.booking.event_time : ''))}</div>
                          {o.booking.kind === 'service' && (o.booking.guest_count || o.booking.venue) ? <div style={{ fontSize: 12.5, color: '#6B7280', marginTop: 3 }}>{[o.booking.guest_count ? o.booking.guest_count + ' guests' : '', o.booking.venue].filter(Boolean).join(' · ')}</div> : null}
                          {o.booking.notes ? <div style={{ fontSize: 12.5, color: '#6B7280', marginTop: 3 }}>{o.booking.notes}</div> : null}
                        </div>
                      )}
                      {vName ? <div><span style={{ color: '#6B7280' }}>Vendor: </span><span style={{ fontWeight: 600 }}>{vName}</span></div> : (o.vendor_id ? null : <div style={{ fontSize: 12.5, color: '#6B7280' }}>Unassigned / house order</div>)}
                      {o.notes ? <div><div style={{ fontSize: 11.5, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: '#6B7280', marginBottom: 4 }}>Notes</div><div style={{ padding: 10, background: '#F9FAFB', borderRadius: 8, whiteSpace: 'pre-wrap', fontSize: 13 }}>{o.notes}</div></div> : null}
                      {o.customer_confirmed_at ? <div style={{ padding: '10px 12px', background: '#F0FDF4', borderRadius: 8, color: '#15803D', fontSize: 13 }}>Customer confirmed delivery on {new Date(o.customer_confirmed_at).toLocaleDateString()}</div> : null}
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', paddingTop: 8, borderTop: '1px solid var(--line)' }}>
                        <label style={{ fontSize: 12.5, color: '#6B7280' }}>Status</label>
                        <select value={o.status} onChange={async (e) => {
                          const newStatus = e.target.value;
                          await db.from('orders').update({ status: newStatus }).eq('id', o.id);
                          setOrders((prev) => prev.map((x) => x.id === o.id ? { ...x, status: newStatus } : x));
                          setViewingOrder({ ...o, status: newStatus });
                          sarayaLogActivity(db, user, 'order_status_update', { order_id: o.id, status: newStatus });
                        }} style={{ padding: '6px 10px', borderRadius: 6, border: '1px solid var(--line)', fontSize: 13, background: 'var(--white)', cursor: 'pointer' }}>
                          {['processing','pending','paid','confirmed','prep','out','done','cancelled','refunded'].map((s) => <option key={s} value={s}>{s}</option>)}
                        </select>
                        {o.status !== 'refunded' && o.status !== 'cancelled' && (
                          <button onClick={async () => {
                            if (!window.refundOrder) return;
                            if (!window.confirm('Refund the full amount for order ' + (o.reference || o.id.slice(0,8)) + '? This cannot be undone.')) return;
                            try {
                              const res = await window.refundOrder({ orderId: o.id });
                              setOrders((prev) => prev.map((x) => x.id === o.id ? { ...x, status: res.full ? 'refunded' : x.status } : x));
                              setViewingOrder({ ...o, status: res.full ? 'refunded' : o.status });
                              sarayaLogActivity(db, user, 'order_refund', { order_id: o.id, amount: res.amount });
                              window.alert('Refunded AED ' + Number(res.amount).toFixed(2));
                            } catch (err) { window.alert('Refund failed: ' + err.message); }
                          }} style={{ padding: '6px 12px', borderRadius: 6, border: '1px solid #B91C1C', background: 'transparent', color: '#B91C1C', fontSize: 13, fontWeight: 600, cursor: 'pointer', marginLeft: 'auto' }}>Refund</button>
                        )}
                      </div>
                    </div>
                    )}
                  </div>
                </div>
              );
            })()}

            {/* SUBSCRIPTION MANAGEMENT */}
            {activeTab === 'subscriptions' && (
              <AdminSubscriptionsTab db={db} vendors={vendors} tiers={tiers} />
            )}

            {/* SUBSCRIPTION TIERS */}
            {activeTab === 'tiers' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <AdminSection
                  title="Subscription Tiers"
                  desc="Edit tier names, prices, and limits. Changes take effect immediately."
                  action={
                    <Button variant="primary" icon="plus" onClick={() => setTierEdit({
                      name: '', name_ar: '', description_en: '', description_ar: '',
                      price_monthly: 0, price_annual: 0, discount_percent: 0, max_listings: 20, rfq_responses_per_month: 10,
                      rfq_access: true, promotion_access: false, commission_rate_override: null, visibility_priority: 0,
                      can_create_discounts: false, featured_placement: false, banner_eligibility: false,
                      priority_support: false, analytics_level: 'basic', is_active: true,
                    })}>New Tier</Button>
                  }
                >
                  <AdminTable
                    emptyMsg="No tiers configured"
                    cols={[
                      { key: 'name',         label: 'Name' },
                      { key: 'price_monthly', label: 'Price/mo', render: (r) => `AED ${r.price_monthly}` },
                      { key: 'price_annual', label: 'Price/yr', render: (r) => r.price_annual ? `AED ${r.price_annual}` : '—' },
                      { key: 'discount_percent', label: 'Promo', render: (r) => Number(r.discount_percent) > 0 ? `${Math.round(Number(r.discount_percent))}% off` : '—' },
                      { key: 'max_listings', label: 'Max Listings' },
                      { key: 'rfq_responses_per_month', label: 'RFQ/mo', render: (r) => r.rfq_responses_per_month ?? '∞' },
                      { key: 'featured_placement', label: 'Featured', render: (r) => r.featured_placement ? '✓' : '—' },
                      { key: 'is_active', label: 'Active', render: (r) => r.is_active ? <span style={{ color: '#16A34A', fontWeight: 600 }}>Yes</span> : <span style={{ color: '#9CA3AF' }}>No</span> },
                      {
                        key: 'actions', label: 'Edit',
                        render: (r) => (
                          <Button variant="ghost" small icon="pencil" onClick={() => setTierEdit({ ...r })}>Edit</Button>
                        ),
                      },
                    ]}
                    rows={tiers}
                  />
                </AdminSection>

                {/* Tier edit form */}
                {tierEdit && (
                  <div style={{ position: 'fixed', inset: 0, zIndex: 400, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16, background: 'rgba(42,31,26,0.5)' }}>
                    <div style={{ background: 'var(--white)', borderRadius: 20, padding: '28px', maxWidth: 560, width: '100%', maxHeight: '90vh', overflowY: 'auto', boxShadow: 'var(--shadow-deep)' }}>
                      <h3 style={{ fontFamily: 'var(--font-display)', fontSize: 22, fontWeight: 500, marginBottom: 20 }}>{tierEdit.id ? 'Edit Tier' : 'New Tier'}</h3>
                      <form onSubmit={saveTier} style={{ display: 'grid', gap: 14 }}>
                        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
                          <Field label="Name (EN)"><TextInput value={tierEdit.name} onChange={(e) => setTierEdit((p) => ({ ...p, name: e.target.value }))} required /></Field>
                          <Field label="Name (AR)"><TextInput value={tierEdit.name_ar || ''} onChange={(e) => setTierEdit((p) => ({ ...p, name_ar: e.target.value }))} dir="rtl" /></Field>
                          <Field label="Price / Month (AED)"><TextInput type="number" value={tierEdit.price_monthly} onChange={(e) => setTierEdit((p) => ({ ...p, price_monthly: e.target.value }))} required /></Field>
                          <Field label="Price / Year (AED)"><TextInput type="number" value={tierEdit.price_annual ?? ''} onChange={(e) => setTierEdit((p) => ({ ...p, price_annual: e.target.value }))} placeholder="e.g. 50% off 12 months" /></Field>
                          <Field label="Max Listings"><TextInput type="number" value={tierEdit.max_listings} onChange={(e) => setTierEdit((p) => ({ ...p, max_listings: e.target.value }))} required /></Field>
                          <Field label="RFQ Responses / mo (blank = unlimited)"><TextInput type="number" value={tierEdit.rfq_responses_per_month ?? ''} onChange={(e) => setTierEdit((p) => ({ ...p, rfq_responses_per_month: e.target.value === '' ? null : parseInt(e.target.value) }))} placeholder="Leave blank for unlimited" /></Field>
                          <Field label="Analytics Level">
                            <select value={tierEdit.analytics_level} onChange={(e) => setTierEdit((p) => ({ ...p, analytics_level: e.target.value }))} style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 14 }}>
                              <option value="none">None</option>
                              <option value="basic">Basic</option>
                              <option value="advanced">Advanced (+ revenue reports)</option>
                              <option value="full">Full (suite + export)</option>
                            </select>
                          </Field>
                          <Field label="Promo Discount % (0 = none)"><TextInput type="number" value={tierEdit.discount_percent ?? 0} onChange={(e) => setTierEdit((p) => ({ ...p, discount_percent: e.target.value }))} placeholder="0" /></Field>
                          <Field label="Commission % (per confirmed transaction)"><TextInput type="number" step="0.1" value={tierEdit.commission_rate_override ?? ''} onChange={(e) => setTierEdit((p) => ({ ...p, commission_rate_override: e.target.value === '' ? null : e.target.value }))} placeholder="e.g. 2" /></Field>
                        </div>
                        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, alignItems: 'center', padding: '10px 14px', borderRadius: 8, background: 'var(--cream)', border: '1px solid var(--line)' }}>
                          <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12.5, fontWeight: 600, color: 'var(--fg-secondary)' }}>
                            Yearly discount %
                            <input type="number" min="0" max="100" step="1"
                              value={(() => { const m = Number(tierEdit.price_monthly) || 0; const y = Number(tierEdit.price_annual) || 0; return (m > 0 && y > 0) ? Math.round((1 - y / (m * 12)) * 100) : ''; })()}
                              onChange={(e) => setTierEdit((p) => { const pct = Math.max(0, Math.min(100, Number(e.target.value) || 0)); const m = Number(p.price_monthly) || 0; return { ...p, price_annual: Math.round(m * 12 * (1 - pct / 100)) }; })}
                              placeholder="e.g. 25"
                              style={{ width: 72, padding: '7px 9px', borderRadius: 7, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 13 }} />
                          </label>
                          <span style={{ fontSize: 12.5, color: 'var(--fg-secondary)' }}>
                            {(() => {
                              const m = Number(tierEdit.price_monthly) || 0;
                              const y = Number(tierEdit.price_annual) || 0;
                              const d = Number(tierEdit.discount_percent) || 0;
                              const yOff = m > 0 && y > 0 ? Math.round((1 - y / (m * 12)) * 100) : 0;
                              const effM = d > 0 ? Math.round(m * (1 - d / 100)) : m;
                              return `Yearly AED ${y || '—'}${yOff ? ` (${yOff}% off — what vendors see & pay)` : ''}` + (d > 0 ? ` · Monthly promo: AED ${effM} (${Math.round(d)}% off)` : '');
                            })()}
                          </span>
                        </div>
                        {[
                          { k: 'rfq_access',            l: 'RFQ Access (vendor can receive quote requests)' },
                          { k: 'promotion_access',      l: 'Promotion Tools' },
                          { k: 'can_create_discounts',  l: 'Can Create Discounts' },
                          { k: 'featured_placement',    l: 'Featured Placement' },
                          { k: 'banner_eligibility',    l: 'Banner Eligibility' },
                          { k: 'priority_support',      l: 'Priority Support' },
                          { k: 'is_active',             l: 'Active' },
                        ].map((f) => (
                          <label key={f.k} style={{ display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer', fontSize: 14 }}>
                            <input type="checkbox" checked={!!tierEdit[f.k]} onChange={(e) => setTierEdit((p) => ({ ...p, [f.k]: e.target.checked }))} style={{ width: 16, height: 16, accentColor: 'var(--gold-deep)' }} />
                            {f.l}
                          </label>
                        ))}
                        <Field label="Description (EN)">
                          <textarea value={tierEdit.description_en || ''} onChange={(e) => setTierEdit((p) => ({ ...p, description_en: e.target.value }))} rows={2} style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 14, resize: 'vertical', boxSizing: 'border-box' }} />
                        </Field>
                        <Field label="Description (AR)">
                          <textarea value={tierEdit.description_ar || ''} onChange={(e) => setTierEdit((p) => ({ ...p, description_ar: e.target.value }))} dir="rtl" rows={2} style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 14, resize: 'vertical', boxSizing: 'border-box' }} />
                        </Field>
                        <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 8 }}>
                          <Button variant="ghost" onClick={() => setTierEdit(null)}>Cancel</Button>
                          <Button variant="primary" type="submit" loading={tierBusy}>Save Tier</Button>
                        </div>
                      </form>
                    </div>
                  </div>
                )}
              </div>
            )}

            {/* ORDERS & BOOKINGS */}
            {activeTab === 'orders' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <AdminSection title="Orders & Bookings" desc="All platform orders and service bookings.">
                  {<AdminTable
                      emptyMsg="No orders yet"
                      cols={[
                        { key: 'reference',    label: 'Reference', render: (r) => <button onClick={() => openOrderDetail(r)} style={{ border: 'none', background: 'none', padding: 0, cursor: 'pointer', font: 'inherit' }}><code style={{ fontSize: 12, color: 'var(--gold-deep)', textDecoration: 'underline' }}>{r.reference || r.id?.slice(0,8)}</code></button> },
                        { key: 'customer',     label: 'Customer',  render: (r) => {
                          const nm = r.profiles?.display_name || r.guest_name || '—';
                          const contact = [r.guest_phone, r.guest_email].filter(Boolean).join(' · ');
                          return contact
                            ? <div><div>{nm}</div><div style={{ fontSize: 11, color: 'var(--fg-muted)' }}>{contact}</div></div>
                            : nm;
                        } },
                        { key: 'total_amount', label: 'Total',     render: (r) => 'AED ' + Number(r.total_amount || 0).toFixed(2) },
                        { key: 'status',       label: 'Status',    render: (r) => <StatusBadge status={r.status} /> },
                        { key: 'payment',      label: 'Payment',   render: (r) => {
                          const pb = r.status === 'refunded' ? { l: 'Refunded', c: '#B91C1C', bg: '#FEE2E2' } : (r.paid_at ? { l: 'Paid', c: '#15803D', bg: '#DCFCE7' } : { l: 'Unpaid', c: '#6B7280', bg: '#F3F4F6' });
                          return <span style={{ padding: '3px 9px', borderRadius: 6, background: pb.bg, color: pb.c, fontSize: 12, fontWeight: 600 }}>{pb.l}</span>;
                        } },
                        { key: 'created_at',   label: 'Date',      render: (r) => new Date(r.created_at).toLocaleDateString() },
                        { key: 'actions',      label: '',          render: (r) => (
                          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                          <button onClick={() => openOrderDetail(r)} style={{ padding: '5px 10px', borderRadius: 6, border: '1px solid var(--line)', background: 'var(--white)', color: 'var(--ink)', fontFamily: 'var(--font-body)', fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>Details</button>
                          <select
                            value={r.status}
                            onChange={async (e) => {
                              const newStatus = e.target.value;
                              await db.from('orders').update({ status: newStatus }).eq('id', r.id);
                              setOrders((prev) => prev.map((o) => o.id === r.id ? { ...o, status: newStatus } : o));
                              sarayaLogActivity(db, user, 'order_status_update', { order_id: r.id, status: newStatus });
                            }}
                            style={{ padding: '5px 8px', borderRadius: 6, border: '1px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 12, background: 'var(--white)', cursor: 'pointer' }}
                          >
                            {['processing','pending','paid','confirmed','prep','out','done','cancelled','refunded'].map((s) => (
                              <option key={s} value={s}>{s}</option>
                            ))}
                          </select>
                          {r.status !== 'refunded' && r.status !== 'cancelled' && (
                            <button onClick={async () => {
                              if (!window.refundOrder) return;
                              if (!window.confirm('Refund the full amount for order ' + (r.reference || r.id.slice(0,8)) + '? This cannot be undone.')) return;
                              try {
                                const res = await window.refundOrder({ orderId: r.id });
                                setOrders((prev) => prev.map((o) => o.id === r.id ? { ...o, status: res.full ? 'refunded' : o.status } : o));
                                sarayaLogActivity(db, user, 'order_refund', { order_id: r.id, amount: res.amount });
                                window.alert('Refunded AED ' + Number(res.amount).toFixed(2));
                              } catch (e) { window.alert('Refund failed: ' + e.message); }
                            }} style={{ padding: '5px 10px', borderRadius: 6, border: '1px solid #B91C1C', background: 'transparent', color: '#B91C1C', fontFamily: 'var(--font-body)', fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>Refund</button>
                          )}
                          </div>
                        )},
                      ]}
                      rows={orders}
                    />}
                </AdminSection>
              </div>
            )}

            {/* RFQ REQUESTS */}
            {activeTab === 'rfqs' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <AdminSection title="RFQ Requests" desc="Quote requests submitted by customers.">
                  {<AdminTable
                      emptyMsg="No RFQ requests yet"
                      cols={[
                        { key: 'id',         label: 'ID',       render: (r) => <code style={{ fontSize: 11 }}>{r.id?.slice(0,8)}</code> },
                        { key: 'name',       label: 'Customer', render: (r) => r.name || r.customer_name || '—' },
                        { key: 'event_type', label: 'Event Type' },
                        { key: 'budget',     label: 'Budget' },
                        { key: 'status',     label: 'Status',   render: (r) => <StatusBadge status={r.status || 'open'} /> },
                        { key: 'created_at', label: 'Date',     render: (r) => new Date(r.created_at).toLocaleDateString() },
                      ]}
                      rows={rfqs}
                    />}
                </AdminSection>
              </div>
            )}

            {/* LEADS & INQUIRIES */}
            {activeTab === 'leads' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <AdminSection title="Leads & Inquiries" desc="All leads captured from website forms, WhatsApp, and Request Quote modal.">
                  {leads.length === 0 ? (
                    <div style={{ padding: '32px 22px', textAlign: 'center', color: 'var(--fg-muted)', fontSize: 14 }}>No leads yet</div>
                  ) : (
                    <div style={{ display: 'grid', gap: 12 }}>
                      {leads.map((r) => {
                        const approved = vendors.filter((v) => v.status === 'approved' || v.status === 'active');
                        const cats = [...new Set(approved.flatMap((v) => Array.isArray(v.business_category) ? v.business_category : []))].sort();
                        const count = (leadAssigns[r.id] || []).length;
                        const doAssign = async (val) => {
                          if (!val) return;
                          let targets = [];
                          if (val === '__all__') targets = approved;
                          else if (val.indexOf('__cat__') === 0) { const c = val.slice(7); targets = approved.filter((v) => (v.business_category || []).includes(c)); }
                          else targets = approved.filter((v) => v.id === val);
                          if (!targets.length) { pushToast('No matching vendors', 'None of the approved vendors match that selection.'); return; }
                          const at = new Date().toISOString();
                          for (const v of targets) {
                            const { error } = await db.from('lead_assignments').upsert({ lead_id: r.id, vendor_id: v.id, status: 'new', assigned_at: at, assigned_by: user.id }, { onConflict: 'lead_id,vendor_id' });
                            if (error) { pushToast('Assign failed', error.message); return; }
                            try { await sarayaNotify(v.id, 'lead', 'A new lead was assigned to you: ' + (r.name || 'inquiry'), { lead_id: r.id }); } catch (e2) {}
                          }
                          if (targets.length === 1) await db.from('leads').update({ vendor_id: targets[0].id, assigned_at: at }).eq('id', r.id);
                          sarayaLogActivity({ action: 'lead_assigned', entityType: 'lead', entityId: r.id, entityLabel: r.name, details: { count: targets.length, vendors: targets.map((t) => t.id) } });
                          pushToast('Lead assigned', 'Sent to ' + targets.length + ' vendor(s) — each was notified.');
                          load();
                        };
                        const msg = (r.message || '').slice(0, 140);
                        const selStyle = { display: 'block', marginTop: 4, width: '100%', fontSize: 13, padding: '7px 10px', borderRadius: 8, border: '1px solid var(--line-strong)', background: 'var(--white)', fontFamily: 'var(--font-body)', color: 'var(--fg-primary)', cursor: 'pointer' };
                        const lblStyle = { fontSize: 10.5, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--fg-muted)' };
                        return (
                          <div key={r.id} style={{ background: 'var(--white)', border: '1px solid var(--line)', borderRadius: 12, padding: '14px 16px', display: 'flex', gap: 16, justifyContent: 'space-between', flexWrap: 'wrap', alignItems: 'flex-start' }}>
                            <div style={{ flex: '1 1 260px', minWidth: 230 }}>
                              <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                                <span style={{ fontWeight: 700, fontSize: 14.5, color: 'var(--fg-primary)' }}>{r.name || 'Unknown'}</span>
                                <StatusBadge status={r.lead_type || r.leadType || 'inquiry'} />
                                {count > 0 && <span style={{ fontSize: 11, fontWeight: 600, color: '#16A34A', background: '#DCFCE7', padding: '2px 8px', borderRadius: 20 }}>{count} assigned</span>}
                              </div>
                              <div style={{ fontSize: 13, color: 'var(--fg-secondary)', marginTop: 5, display: 'flex', gap: 16, flexWrap: 'wrap' }}>
                                {r.email && <a href={'mailto:' + r.email} style={{ color: 'var(--fg-secondary)', textDecoration: 'none' }}>✉ {r.email}</a>}
                                {r.phone && <a href={'tel:' + r.phone} style={{ color: 'var(--fg-secondary)', textDecoration: 'none' }}>☎ {r.phone}</a>}
                              </div>
                              {msg && <div style={{ fontSize: 12.5, color: 'var(--fg-muted)', marginTop: 7, fontStyle: 'italic', lineHeight: 1.5 }}>“{msg}{(r.message || '').length > 140 ? '…' : ''}”</div>}
                              <div style={{ fontSize: 11.5, color: 'var(--fg-muted)', marginTop: 7 }}>{r.source || 'website'}{' · '}{r.created_at ? new Date(r.created_at).toLocaleDateString('en-AE', { day: 'numeric', month: 'short', year: 'numeric' }) : '—'}</div>
                            </div>
                            <div style={{ display: 'flex', gap: 10, flex: '0 0 auto', flexWrap: 'wrap' }}>
                              <label style={{ ...lblStyle, minWidth: 130 }}>Status
                                <select value={r.status || 'new'} onChange={async (e) => { const newStatus = e.target.value; await db.from('leads').update({ status: newStatus }).eq('id', r.id); setLeads((prev) => prev.map((l) => l.id === r.id ? { ...l, status: newStatus } : l)); }} style={selStyle}>
                                  <option value="new">New</option>
                                  <option value="contacted">Contacted</option>
                                  <option value="quoted">Quoted</option>
                                  <option value="won">Won</option>
                                  <option value="lost">Lost</option>
                                  <option value="closed">Closed</option>
                                </select>
                              </label>
                              <label style={{ ...lblStyle, minWidth: 180 }}>Assign to
                                <select value="" onChange={(e) => { const v = e.target.value; e.target.value = ''; doAssign(v); }} style={selStyle}>
                                  <option value="">{count ? count + ' assigned · add…' : 'Assign…'}</option>
                                  <optgroup label="Broadcast">
                                    <option value="__all__">All approved vendors ({approved.length})</option>
                                    {cats.map((c) => { const n = approved.filter((v) => (v.business_category || []).includes(c)).length; return <option key={c} value={'__cat__' + c}>All "{c}" ({n})</option>; })}
                                  </optgroup>
                                  <optgroup label="Assign one vendor">
                                    {approved.map((v) => <option key={v.id} value={v.id}>{v.trade_name || String(v.id).slice(0,8)}</option>)}
                                  </optgroup>
                                </select>
                              </label>
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  )}
                </AdminSection>
              </div>
            )}

            {/* MARKETPLACE */}
            {activeTab === 'marketplace' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(180px,1fr))', gap: 14 }}>
                  <AdminStat icon="shopping-bag" label="Product Listings" value={stats?.totalProducts} />
                  <AdminStat icon="archive"      label="Rental Listings" value={stats?.totalRentals} />
                  <AdminStat icon="briefcase"    label="Vendor Service Listings" value={stats?.totalServices} />
                  <AdminStat icon="store"        label="Active Vendors" value={stats?.activeVendors} tone="success" />
                </div>
                <AdminSection title="Marketplace Listings" desc="Review and manage vendor-submitted products, rentals, and services. Note: the public Services page also shows curated marketing service categories, which are separate from the vendor-submitted service listings tracked below.">
                  <AdminListingsApproval />
                </AdminSection>
              <AdminSection title="Customer Reviews" desc="New reviews are held as pending until approved here, to keep negative or inappropriate comments off the site.">
                <AdminReviewsModeration />
              </AdminSection>
                <AdminSection title="Virtual Showroom Subscriptions" desc="Manage showroom access for vendors.">
                  <AdminPlaceholder note="Virtual Showroom subscriptions will appear here. Requires the 'subscriptions' table with showroom_tier field." />
                </AdminSection>
              </div>
            )}

            {/* FINANCE */}
            {activeTab === 'finance' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(200px,1fr))', gap: 14 }}>
                  <AdminStat icon="trending-up"  label="Total Revenue"      value={'AED ' + (stats?.totalRevenue || 0).toFixed(0)} tone="success" />
                  <AdminStat icon="banknote"     label="Pending Payouts"    value={'AED ' + (stats?.pendingPayouts || 0).toFixed(0)} tone="warning" />
                  <AdminStat icon="alert-circle" label="Held Payouts"       value={'AED ' + (stats?.heldPayouts || 0).toFixed(0)}    tone="danger" />
                  <AdminStat icon="repeat"       label="Active Subscriptions" value={stats?.activeSubsc} tone="success" />
                
                </div>
                {(() => {
                  const _sc = (window.getStripeCfg && window.getStripeCfg()) || {};
                  const _isLive = !!(_sc.live && /^pk_live/.test(_sc.publishableKey || '') && _sc.backendUrl);
                  return _isLive ? (
                <div style={{ padding: '16px 20px', borderRadius: 12, background: 'var(--success-bg)', border: '1.5px solid var(--success)', display: 'flex', gap: 12, alignItems: 'flex-start' }}>
                  <Icon name="check-circle" size={18} style={{ color: 'var(--success)', flexShrink: 0, marginTop: 2 }} />
                  <div>
                    <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 3 }}>Payment integration status: Live</div>
                    <div style={{ fontSize: 13, color: 'var(--fg-secondary)', lineHeight: 1.6 }}>
                      Stripe is in live mode -- real card payments are being processed. Keep the secret key server-side only (Vercel environment variables / Supabase Edge Functions), never in frontend code.
                    </div>
                  </div>
                </div>
                  ) : (
                <div style={{ padding: '16px 20px', borderRadius: 12, background: '#FFFBEB', border: '1.5px solid #FCD34D', display: 'flex', gap: 12, alignItems: 'flex-start' }}>
                  <Icon name="alert-triangle" size={18} style={{ color: '#D97706', flexShrink: 0, marginTop: 2 }} />
                  <div>
                    <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 3 }}>Payment integration status: Not live</div>
                    <div style={{ fontSize: 13, color: 'var(--fg-secondary)', lineHeight: 1.6 }}>
                      Stripe keys, backend payment records, and webhook processing are not yet configured for production. No real payments have been processed. Secret keys must never be stored or exposed in frontend code -- use Supabase Edge Functions or a backend server only.
                    </div>
                  </div>
                </div>
                  );
                })()}
                <AdminSection title="Payments" desc="All payment transactions across the platform.">
                  <AdminPlaceholder
                    note="The 'payments' Supabase table already exists and is ready to receive records. What is still missing is the Stripe webhook itself (a Supabase Edge Function) that writes a row here after a real charge succeeds — until that is built and Stripe goes live, this will stay empty."
                    items={[
                      { icon: 'credit-card', label: 'All Payments',    desc: 'Stripe payment transactions' },
                      { icon: 'percent',     label: 'Commissions',     desc: 'Platform commission per order' },
                      { icon: 'rotate-ccw', label: 'Refunds',          desc: 'Refund requests and status' },
                      { icon: 'zap',        label: 'Stripe Settings',  desc: 'Stripe keys, webhooks, and config' },
                    ]}
                  />
                </AdminSection>
                <AdminSection title="Stripe Settings">
                  <div style={{ padding: '16px 22px' }}>
                    <div style={{ display: 'grid', gap: 12, fontSize: 14 }}>
                      {[
                        { label: 'Publishable Key', key: 'STRIPE_PUBLISHABLE_KEY', desc: 'Frontend key — safe to expose. Set in src/config.js.' },
                        { label: 'Secret Key',      key: 'STRIPE_SECRET_KEY',      desc: 'NEVER put in frontend. Use Supabase Edge Function or backend server only.' },
                        { label: 'Webhook Secret',  key: 'STRIPE_WEBHOOK_SECRET',  desc: 'Validates Stripe webhook events. Server-side only.' },
                      ].map((item) => (
                        <div key={item.key} style={{ padding: '12px 16px', borderRadius: 10, background: 'var(--bg-canvas)', border: '1px solid var(--line)' }}>
                          <div style={{ fontWeight: 600, marginBottom: 3 }}>{item.label}</div>
                          <code style={{ fontSize: 12, color: 'var(--fg-secondary)' }}>{item.key}</code>
                          <p style={{ fontSize: 12.5, color: 'var(--fg-muted)', margin: '4px 0 0' }}>{item.desc}</p>
                        </div>
                      ))}
                    </div>
                  </div>
                </AdminSection>
              </div>
            )}

            {/* MARKETING */}
            {activeTab === 'marketing' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <AdminSection title="Platform Image CMS" desc="Manage hero images, banners, and promotional visuals for all pages. Backed by the platform_images table.">
                  <AdminPlatformImageCMS />
                </AdminSection>
                <AdminSection title="Customer Leads" desc="Leads submitted by customers via quote forms and inquiries.">
                  <AdminTable emptyMsg="No customer leads yet" cols={[
                    { key: 'name',       label: 'Name' },
                    { key: 'phone',      label: 'Phone' },
                    { key: 'source',     label: 'Source' },
                    { key: 'created_at', label: 'Date', render: (r) => new Date(r.created_at).toLocaleDateString() },
                  ]} rows={leads.filter((l) => (l.lead_type || l.leadType || '').includes('customer'))} />
                </AdminSection>
                <AdminSection title="Vendor Leads" desc="Vendor partnership and application inquiries.">
                  <AdminTable emptyMsg="No vendor leads yet" cols={[
                    { key: 'name',       label: 'Business / Name' },
                    { key: 'phone',      label: 'Phone' },
                    { key: 'source',     label: 'Source' },
                    { key: 'created_at', label: 'Date', render: (r) => new Date(r.created_at).toLocaleDateString() },
                  ]} rows={leads.filter((l) => (l.lead_type || l.leadType || '').includes('vendor'))} />
                </AdminSection>
              </div>
            )}

            {/* CONTENT */}
            {activeTab === 'content' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <div style={{ padding: '16px 20px', borderRadius: 12, background: '#ECFDF5', border: '1.5px solid #6EE7B7', display: 'flex', gap: 12, alignItems: 'flex-start' }}>
                  <Icon name="check-circle" size={18} style={{ color: '#059669', flexShrink: 0, marginTop: 2 }} />
                  <div>
                    <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 3 }}>Text edits now sync to Supabase</div>
                    <div style={{ fontSize: 13, color: 'var(--fg-secondary)', lineHeight: 1.6 }}>
                      Toggle <strong>Content Editing Mode</strong> in the left Admin sidebar to edit images and text inline on any page. Use the pencil icon on any element to edit it directly. Text and layout edits now save to the <code>content_blocks</code> Supabase table and reach every staff device and every site visitor within a few seconds of saving. Uploaded images still save to this browser only (via IndexedDB) — they will not appear on other devices or for other visitors until a real media library is built; use Export/Import in the admin bar to move them manually for now.
                    </div>
                  </div>
                </div>
                <AdminSection title="Page Content" desc="Content sections for each page of the platform.">
                  <div style={{ display: 'grid', gap: 16, padding: '4px 0 4px' }}>
                    <div style={{ padding: '12px 20px', borderRadius: 10, background: '#ECFDF5', border: '1px solid #6EE7B7', fontSize: 12.5, color: 'var(--fg-secondary)', lineHeight: 1.6 }}>
                      Production-persistent: edits save to the <code>content_blocks</code> Supabase table (fields: page_key, section_key, content_type, language, title, subtitle, body, image_url, button_label, button_url, sort_order, is_active, updated_by, updated_at) and are visible platform-wide. Uploaded images remain device-local only until a media library is built.
                    </div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(220px,1fr))', gap: 12 }}>
                      {[
                        { icon: 'home',        label: 'Home Page',          desc: 'Hero, features, testimonials, CTA sections' },
                        { icon: 'shopping-bag',label: 'Marketplace',        desc: 'Marketplace header and category banners' },
                        { icon: 'archive',     label: 'Rentals',            desc: 'Rental page headers and featured categories' },
                        { icon: 'monitor',     label: 'Virtual Showroom',   desc: 'Showroom intro and vendor spotlights' },
                      ].map((item, i) => (
                        <div key={i} style={{ padding: '18px 20px', borderRadius: 12, background: 'var(--white)', border: '1px solid var(--line)' }}>
                          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
                            <span style={{ display: 'inline-flex', width: 32, height: 32, borderRadius: 8, background: 'var(--cream)', alignItems: 'center', justifyContent: 'center' }}>
                              <Icon name={item.icon} size={16} style={{ color: 'var(--gold-deep)' }} />
                            </span>
                            <span style={{ fontWeight: 600, fontSize: 13.5 }}>{item.label}</span>
                          </div>
                          <p style={{ fontSize: 12.5, color: 'var(--fg-secondary)', lineHeight: 1.5, margin: 0 }}>{item.desc}</p>
                        </div>
                      ))}
                    </div>
                  </div>
                </AdminSection>
                <AdminSection title="Legal Pages" desc="Terms, privacy policy, cancellation and complaints policies.">
                  <div style={{ padding: '12px 22px', display: 'grid', gap: 10 }}>
                    {[
                      { label: 'Terms of Use',             route: 'terms',               icon: 'scale' },
                      { label: 'Privacy Policy',           route: 'privacy',             icon: 'shield' },
                      { label: 'Cancellation & Refund',    route: 'cancellation-refund', icon: 'rotate-ccw' },
                      { label: 'Complaints Policy',        route: 'complaints',          icon: 'alert-circle' },
                    ].map((p) => (
                      <div key={p.route} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px', borderRadius: 10, background: 'var(--bg-canvas)', border: '1px solid var(--line)' }}>
                        <Icon name={p.icon} size={16} style={{ color: 'var(--gold-deep)', flexShrink: 0 }} />
                        <span style={{ flex: 1, fontSize: 14, fontWeight: 500 }}>{p.label}</span>
                        <button onClick={function() { location.hash = '#' + p.route; }} style={{ background: 'none', border: '1px solid var(--line)', borderRadius: 7, padding: '4px 12px', fontSize: 12.5, cursor: 'pointer', color: 'var(--fg-secondary)' }}>View</button>
                      </div>
                    ))}
                  </div>
                </AdminSection>
                <AdminSection title="Footer & Navigation" desc="Footer links, social links, and main navigation structure.">
                  <AdminPlaceholder note="Footer and navigation content is currently defined in chrome.jsx and data.js. A CMS-driven nav editor requires a 'navigation' Supabase table." />
                </AdminSection>
              </div>
            )}

            {/* USERS */}
            {activeTab === 'users' && (
              <AdminSection title="Users & Roles" desc="All registered users and their platform roles.">
                <UsersTable db={db} />
              </AdminSection>
            )}

            {activeTab === 'activity' && (
              <AdminActivityLog db={db} />
            )}

            {activeTab === 'customer_requests' && (
              <AdminCustomerRequests db={db} setActiveTab={setActiveTab} stats={stats} />
            )}

            {activeTab === 'marketplace_activity' && (
              <AdminMarketplaceActivity db={db} />
            )}

            {activeTab === 'staff_tasks' && (
              <AdminStaffTasks db={db} setActiveTab={setActiveTab} stats={stats} />
            )}

            {activeTab === 'ai_agent_notes' && (
              <AdminAgentNotes />
            )}

            {activeTab === 'tools' && (
              <div style={{ display: 'grid', gap: 20 }}>
                <AdminSection title="Developer Tools" desc="One-time data operations, migrations, and utilities. Hidden from normal staff in production.">
                  {isDevMode ? (
                    <DataMigrationTool db={db} />
                  ) : (
                    <div style={{ padding: '16px 22px' }}>
                      <div style={{ padding: '12px 16px', borderRadius: 10, background: '#FFFBEB', border: '1px solid #FCD34D', fontSize: 13, color: '#92400E' }}>
                        Developer tools (data seeding/import) are hidden in production and only run in local development.
                      </div>
                    </div>
                  )}
                </AdminSection>
                <AdminSection title="Demo &amp; Test Accounts" desc="For local development only.">
                  <div style={{ padding: '16px 22px', display: 'grid', gap: 12 }}>
                    <div style={{ padding: '12px 16px', borderRadius: 10, background: '#FEF2F2', border: '1px solid #FCA5A5', fontSize: 13, color: '#B91C1C', fontWeight: 600 }}>
                      Demo accounts are for local development only and must not be displayed in production. No credentials, including passwords, are ever shown on this page.
                    </div>
                    {isDevMode ? (
                      [
                        { role: 'Admin',    purpose: 'Admin Dashboard + Admin Mode access' },
                        { role: 'Vendor',   purpose: 'Vendor Dashboard, listings, RFQs' },
                        { role: 'Customer', purpose: 'Customer browsing, orders, complaints' },
                      ].map((a) => (
                        <div key={a.role} style={{ padding: '12px 16px', borderRadius: 10, background: 'var(--bg-canvas)', border: '1px solid var(--line)' }}>
                          <StatusBadge status={a.role.toLowerCase()} />
                          <div style={{ fontSize: 12.5, color: 'var(--fg-secondary)', marginTop: 6 }}>{a.purpose}</div>
                        </div>
                      ))
                    ) : null}
                    <p style={{ fontSize: 12.5, color: 'var(--fg-secondary)', margin: 0 }}>
                      Actual email/password values live only in <code>src/project/DEMO_ACCOUNTS.md</code> (internal documentation, not rendered here). Create these accounts in your Supabase Auth dashboard, then set their <code>role</code> in the <code>profiles</code> table.
                    </p>
                  </div>
                </AdminSection>
                <AdminSection title="Reset Local Changes" desc="Clear browser-stored content edits and overrides.">
                  <div style={{ padding: '16px 22px' }}>
                    <p style={{ fontSize: 13.5, color: 'var(--fg-secondary)', marginBottom: 16 }}>
                      Clears only content saved to <em>this browser</em> via Content Editing Mode. Does not affect Supabase data or other users.
                    </p>
                    <button onClick={function() {
                      if (window.confirm('Clear all local content overrides? This cannot be undone.')) {
                        localStorage.removeItem('saraya_overrides_v1');
                        window.location.reload();
                      }
                    }} style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'8px 16px', borderRadius:8, background:'none', border:'1px solid var(--line)', cursor:'pointer', fontSize:13.5, color:'var(--fg)' }}>
                      Reset Local Content
                    </button>
                  </div>
                </AdminSection>
              </div>
            )}
          </>
        )}
        </div> {/* end main content */}
      </div> {/* end flex wrapper */}

      {activationModal && (
        <VendorActivationModal
          modal={activationModal}
          busy={activationBusy}
          onClose={() => setActivationModal(null)}
          onSave={doSaveActivate}
          onOverride={doOverrideActivate}
        />
      )}

      {confirm && (
        <ConfirmDialog
          msg={confirm.msg}
          dangerous={confirm.dangerous}
          onOk={confirm.onOk}
          onCancel={() => setConfirm(null)}
        />
      )}
    </main>
  );
}
window.AdminDashboardPage = AdminDashboardPage;

/* Vendor activation dialog: fill missing details, or approve as an exception. */
function VendorActivationModal({ modal, busy, onClose, onSave, onOverride }) {
  const R = window.React;
  const EDITABLE = {
    trade_license_number: { label: 'Trade license number', type: 'text', ph: 'e.g. CN-1234567' },
    trade_license_expiry: { label: 'Trade license expiry', type: 'date', ph: '' },
    bank_name: { label: 'Bank name', type: 'text', ph: 'e.g. Emirates NBD' },
    bank_iban: { label: 'Bank IBAN', type: 'text', ph: 'AE00 0000 0000 0000 0000 000' },
    bank_account_name: { label: 'Account holder name', type: 'text', ph: '' },
  };
  const DOCS = { trade_license_doc: 'Trade license document', id_doc: 'Emirates ID document', iban_doc: 'IBAN / bank-letter document' };
  const [form, setForm] = R.useState(() => Object.assign({}, modal.values || {}));
  const [reason, setReason] = R.useState('');
  const [err, setErr] = R.useState('');
  const set = (k, v) => setForm((p) => Object.assign({}, p, { [k]: v }));
  const missingEditable = (modal.missing || []).filter((k) => EDITABLE[k]);
  const missingDocs = (modal.missing || []).filter((k) => DOCS[k]);
  const inp = { width: '100%', padding: '9px 11px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 14, outline: 'none', background: 'var(--white)', boxSizing: 'border-box' };
  const lbl = { display: 'block', fontSize: 12.5, fontWeight: 600, color: 'var(--fg-secondary)', marginBottom: 5 };
  const doSave = async () => { setErr(''); const r = await onSave(form); if (r && r.error) setErr(r.error); };
  const doOverride = async () => { setErr(''); if (!reason.trim()) { setErr('Please enter a reason for the exception.'); return; } const r = await onOverride(reason.trim()); if (r && r.error) setErr(r.error); };
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20 }}>
      <div onClick={busy ? null : onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(20,15,10,0.55)' }} />
      <div style={{ position: 'relative', width: 'min(560px,100%)', maxHeight: '90vh', overflowY: 'auto', background: 'var(--white)', borderRadius: 16, boxShadow: 'var(--shadow-deep)', padding: '24px 26px' }}>
        <div style={{ fontFamily: 'var(--font-display)', fontSize: 21, fontWeight: 600, marginBottom: 4 }}>Complete vendor details to activate</div>
        <div style={{ fontSize: 13.5, color: 'var(--fg-muted)', marginBottom: 18 }}>Fill in the missing details below and activate, or approve as an exception.</div>
        {missingEditable.length > 0 && (
          <div style={{ display: 'grid', gap: 13 }}>
            {missingEditable.map((k) => (
              <div key={k}>
                <label style={lbl}>{EDITABLE[k].label}</label>
                <input type={EDITABLE[k].type} value={form[k] || ''} placeholder={EDITABLE[k].ph || ''} onChange={(e) => set(k, e.target.value)} style={inp} />
              </div>
            ))}
          </div>
        )}
        {missingDocs.length > 0 && (
          <div style={{ marginTop: 16, padding: '12px 14px', background: 'var(--cream)', borderRadius: 10, border: '1px solid var(--line)' }}>
            <div style={{ fontSize: 12.5, fontWeight: 600, marginBottom: 6, color: 'var(--fg-secondary)' }}>Missing documents (uploaded by the vendor)</div>
            <ul style={{ margin: 0, paddingInlineStart: 18, fontSize: 13, color: 'var(--fg-muted)' }}>
              {missingDocs.map((k) => <li key={k}>{DOCS[k]}</li>)}
            </ul>
            <div style={{ fontSize: 12, color: 'var(--fg-muted)', marginTop: 6 }}>Documents are not entered here. Either the vendor uploads them, or use the exception option below.</div>
          </div>
        )}
        {err && <div style={{ marginTop: 14, color: '#c0392b', fontSize: 13 }}>{err}</div>}
        <div style={{ display: 'flex', gap: 10, marginTop: 22, flexWrap: 'wrap' }}>
          <button onClick={doSave} disabled={busy} style={{ flex: 1, minWidth: 160, padding: '11px 16px', borderRadius: 10, background: 'var(--espresso)', color: 'var(--ivory)', border: 'none', fontFamily: 'var(--font-body)', fontSize: 14, fontWeight: 600, cursor: busy ? 'wait' : 'pointer' }}>{busy ? 'Working...' : 'Save details & activate'}</button>
          <button onClick={busy ? null : onClose} disabled={busy} style={{ padding: '11px 16px', borderRadius: 10, background: 'var(--white)', color: 'var(--fg-secondary)', border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 14, cursor: 'pointer' }}>Cancel</button>
        </div>
        <div style={{ marginTop: 20, paddingTop: 16, borderTop: '1px solid var(--line)' }}>
          <div style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--fg-secondary)', marginBottom: 6 }}>Approve as an exception (override)</div>
          <div style={{ fontSize: 12.5, color: 'var(--fg-muted)', marginBottom: 8 }}>Activates the vendor even though required details are missing. Recorded with your reason for audit.</div>
          <input type="text" value={reason} placeholder="Reason for the exception (required)" onChange={(e) => setReason(e.target.value)} style={inp} />
          <button onClick={doOverride} disabled={busy} style={{ marginTop: 10, padding: '9px 16px', borderRadius: 10, background: 'var(--white)', color: '#b45309', border: '1.5px solid #f0c987', fontFamily: 'var(--font-body)', fontSize: 13.5, fontWeight: 600, cursor: busy ? 'wait' : 'pointer' }}>Approve anyway (exception)</button>
        </div>
      </div>
    </div>
  );
}
window.VendorActivationModal = VendorActivationModal;

/* ---- Users sub-component (separate to keep load lazy) ---- */
const STAFF_PERM_OPTIONS = [
  { key: 'listings',   label: 'Listings moderator — approve/reject vendor listings' },
  { key: 'orders',     label: 'Orders & bookings' },
  { key: 'complaints', label: 'Complaints & support' },
  { key: 'rfqs',       label: 'RFQs & leads' },
  { key: 'full',       label: 'Full admin access' },
];
const ROLE_COLOR = { admin: '#7C3AED', staff: '#2563EB', vendor: '#D97706', customer: '#16A34A' };

// Compact row-actions dropdown. Uses fixed positioning so the menu never gets
// clipped by table overflow, and a full-screen overlay to close on outside click.
function RowActionsMenu({ items }) {
  const [open, setOpen] = useStateAD(false);
  const [pos, setPos] = useStateAD({ top: 0, right: 0 });
  const openMenu = (e) => {
    const r = e.currentTarget.getBoundingClientRect();
    setPos({ top: r.bottom + 4, right: Math.max(8, window.innerWidth - r.right) });
    setOpen(true);
  };
  return (
    <div style={{ display: 'inline-block' }}>
      <button type="button" onClick={openMenu} title="Actions" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '6px 12px', borderRadius: 8, border: '1px solid var(--line-strong)', background: 'var(--white)', cursor: 'pointer', fontFamily: 'var(--font-body)', fontSize: 13, fontWeight: 600, color: 'var(--fg-primary)' }}>
        <Icon name="more-horizontal" size={16} /> Actions
      </button>
      {open && (
        <React.Fragment>
          <div onClick={() => setOpen(false)} style={{ position: 'fixed', inset: 0, zIndex: 9998 }} />
          <div style={{ position: 'fixed', top: pos.top, right: pos.right, zIndex: 9999, minWidth: 180, background: 'var(--white)', border: '1px solid var(--line)', borderRadius: 10, boxShadow: 'var(--shadow-deep)', padding: 4 }}>
            {items.filter(Boolean).map((it, i) => (
              <button key={i} type="button" onClick={() => { setOpen(false); it.onClick(); }}
                style={{ display: 'flex', alignItems: 'center', gap: 9, width: '100%', textAlign: 'start', padding: '9px 12px', borderRadius: 6, border: 'none', background: 'none', cursor: 'pointer', fontFamily: 'var(--font-body)', fontSize: 13, fontWeight: 500, color: it.danger ? '#B91C1C' : 'var(--fg-primary)' }}
                onMouseEnter={(e) => { e.currentTarget.style.background = it.danger ? '#FEE2E2' : 'var(--cream)'; }}
                onMouseLeave={(e) => { e.currentTarget.style.background = 'none'; }}>
                {it.icon && <Icon name={it.icon} size={14} />}{it.label}
              </button>
            ))}
          </div>
        </React.Fragment>
      )}
    </div>
  );
}

function UsersTable({ db }) {
  const [rows, setRows] = useStateAD([]);
  const [loaded, setLoaded] = useStateAD(false);
  const [filter, setFilter] = useStateAD('all');
  const [edit, setEdit] = useStateAD(null);
  const [addStaff, setAddStaff] = useStateAD(false);
  const [pick, setPick] = useStateAD('');
  const [perms, setPerms] = useStateAD([]);
  const [busy, setBusy] = useStateAD(false);
  const [msg, setMsg] = useStateAD(null);
  const [reg, setReg] = useStateAD(null);

  const reload = () => {
    db.from('profiles').select('*').order('created_at', { ascending: false }).limit(300)
      .then(({ data }) => { setRows(data || []); setLoaded(true); });
  };
  useEffectAD(() => { if (db) reload(); }, [db]);

  const saveEdit = async () => {
    if (!edit) return;
    setBusy(true); setMsg(null);
    const patch = { role: edit.role, staff_permissions: edit.role === 'staff' ? (edit.staff_permissions || []) : [] };
    const { error } = await db.from('profiles').update(patch).eq('id', edit.id);
    setBusy(false);
    if (error) { setMsg({ ok: false, text: error.message }); return; }
    setEdit(null); reload();
  };

  const toggleSuspend = async (u) => {
    const { error } = await db.from('profiles').update({ is_suspended: !u.is_suspended }).eq('id', u.id);
    if (error) { window.alert('Could not update: ' + error.message); return; }
    reload();
  };

  const del = async (u) => {
    if (!window.confirm('Delete ' + (u.display_name || 'this user') + '? This permanently removes their account and cannot be undone. To only block access, use Suspend instead.')) return;
    try {
      const { data, error } = await db.functions.invoke('admin-delete-user', { body: { id: u.id } });
      const errText = (data && data.error) || (error && error.message);
      if (errText) { window.alert(errText); return; }
      reload();
    } catch (e) { window.alert(String((e && e.message) || e)); }
  };

  const doAddStaff = async () => {
    if (!pick) return;
    setBusy(true); setMsg(null);
    const { error } = await db.from('profiles').update({ role: 'staff', staff_permissions: perms }).eq('id', pick);
    setBusy(false);
    if (error) { setMsg({ ok: false, text: error.message }); return; }
    setAddStaff(false); setPick(''); setPerms([]); reload();
  };

  const doCreateUser = async () => {
    if (!reg) return;
    if (!reg.email.trim() || !reg.password || reg.password.length < 6) {
      setMsg({ ok: false, text: 'Enter an email and a password of at least 6 characters.' });
      return;
    }
    setBusy(true); setMsg(null);
    try {
      const { data, error } = await db.functions.invoke('admin-create-user', { body: {
        email: reg.email, password: reg.password, display_name: reg.display_name,
        phone: reg.phone, role: reg.role, staff_permissions: reg.staff_permissions || [],
      } });
      setBusy(false);
      const errText = (data && data.error) || (error && error.message);
      if (errText) { setMsg({ ok: false, text: errText }); return; }
      setReg(null); reload();
    } catch (e) { setBusy(false); setMsg({ ok: false, text: String((e && e.message) || e) }); }
  };

  if (!loaded) return <div style={{ padding: '32px', textAlign: 'center', color: 'var(--fg-muted)' }}><Icon name="loader" size={24} /></div>;

  const filtered = filter === 'all' ? rows : rows.filter((r) => r.role === filter);
  const candidates = rows.filter((r) => r.role !== 'staff' && r.role !== 'admin');
  const permLabel = (u) => u.role === 'staff' && u.staff_permissions && u.staff_permissions.length
    ? ' · ' + (u.staff_permissions.includes('full') ? 'full' : u.staff_permissions.join(', ')) : '';

  return (
    <div>
      <div style={{ padding: '0 22px 12px', display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
        {[['all', 'All'], ['admin', 'Admins'], ['staff', 'Staff'], ['vendor', 'Vendors'], ['customer', 'Customers']].map(([k, l]) => (
          <button key={k} onClick={() => setFilter(k)} style={{ padding: '6px 14px', borderRadius: 20, cursor: 'pointer', fontSize: 12.5, fontWeight: 600, border: '1px solid ' + (filter === k ? 'var(--gold-deep)' : 'var(--line)'), background: filter === k ? 'var(--gold-deep)' : 'var(--white)', color: filter === k ? '#fff' : 'var(--fg-secondary)' }}>{l}</button>
        ))}
        <div style={{ marginInlineStart: 'auto', display: 'flex', gap: 8 }}>
          <Button variant="secondary" small icon="user-plus" onClick={() => { setReg({ email: '', display_name: '', password: '', phone: '', role: 'vendor', staff_permissions: ['listings'] }); setMsg(null); }}>Register User</Button>
          <Button variant="primary" small icon="shield" onClick={() => { setAddStaff(true); setPick(''); setPerms(['listings']); setMsg(null); }}>Add Staff</Button>
        </div>
      </div>
      <AdminTable
        emptyMsg="No users"
        rows={filtered}
        cols={[
          { key: 'id',           label: 'ID',      render: (r) => <code style={{ fontSize: 11 }}>{r.id.slice(0, 8)}…</code> },
          { key: 'display_name', label: 'Name',    render: (r) => r.display_name || r.full_name || '—' },
          { key: 'email',        label: 'Email',   render: (r) => r.email ? <span style={{ fontSize: 12.5 }}>{r.email}</span> : <span style={{ color: 'var(--fg-muted)' }}>—</span> },
          { key: 'role',         label: 'Role',    render: (r) => <span style={{ padding: '3px 10px', borderRadius: 20, fontSize: 12, fontWeight: 600, background: (ROLE_COLOR[r.role] || '#6B7280') + '18', color: ROLE_COLOR[r.role] || '#6B7280', textTransform: 'capitalize' }}>{r.role}{permLabel(r)}</span> },
          { key: 'status',       label: 'Status',  render: (r) => r.is_suspended ? <span style={{ color: '#B91C1C', fontWeight: 600 }}>Suspended</span> : <span style={{ color: '#16A34A', fontWeight: 600 }}>Active</span> },
          { key: 'phone',        label: 'Phone',   render: (r) => r.phone || '—' },
          { key: 'created_at',   label: 'Joined',  render: (r) => new Date(r.created_at).toLocaleDateString() },
          { key: 'actions',      label: 'Actions', render: (r) => (
            <RowActionsMenu items={[
              { label: 'Edit', icon: 'pencil', onClick: () => { setEdit({ ...r, staff_permissions: r.staff_permissions || [] }); setMsg(null); } },
              { label: r.is_suspended ? 'Unsuspend' : 'Suspend', icon: r.is_suspended ? 'check-circle' : 'ban', onClick: () => toggleSuspend(r) },
              { label: 'Delete', icon: 'trash-2', danger: true, onClick: () => del(r) },
            ]} />
          ) },
        ]}
      />

      {edit && (
        <div style={{ position: 'fixed', inset: 0, zIndex: 400, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16, background: 'rgba(42,31,26,0.5)' }}>
          <div style={{ background: 'var(--white)', borderRadius: 20, padding: 28, maxWidth: 460, width: '100%', maxHeight: '90vh', overflowY: 'auto', boxShadow: 'var(--shadow-deep)' }}>
            <h3 style={{ fontFamily: 'var(--font-display)', fontSize: 20, fontWeight: 500, marginBottom: 6 }}>Edit user</h3>
            <p style={{ fontSize: 13, color: 'var(--fg-muted)', marginBottom: 16 }}>{edit.display_name || edit.full_name || edit.id.slice(0, 8)}</p>
            {msg && !msg.ok && <div style={{ padding: '8px 12px', borderRadius: 8, background: '#FEE2E2', color: '#B91C1C', fontSize: 12.5, marginBottom: 12 }}>{msg.text}</div>}
            <Field label="Role">
              <select value={edit.role} onChange={(e) => setEdit((p) => ({ ...p, role: e.target.value }))} style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 14 }}>
                <option value="customer">Customer</option>
                <option value="vendor">Vendor</option>
                <option value="staff">Staff</option>
                <option value="admin">Admin</option>
              </select>
            </Field>
            {edit.role === 'staff' && (
              <div style={{ marginTop: 14 }}>
                <div style={{ fontSize: 12.5, fontWeight: 700, marginBottom: 8, color: 'var(--fg-secondary)' }}>Staff permissions</div>
                <div style={{ display: 'grid', gap: 8 }}>
                  {STAFF_PERM_OPTIONS.map((o) => (
                    <label key={o.key} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 13.5, cursor: 'pointer' }}>
                      <input type="checkbox" checked={(edit.staff_permissions || []).includes(o.key)} onChange={(e) => setEdit((p) => { const s = new Set(p.staff_permissions || []); if (e.target.checked) s.add(o.key); else s.delete(o.key); return { ...p, staff_permissions: [...s] }; })} style={{ width: 16, height: 16, accentColor: 'var(--gold-deep)' }} />
                      {o.label}
                    </label>
                  ))}
                </div>
              </div>
            )}
            <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 20 }}>
              <Button variant="ghost" onClick={() => setEdit(null)}>Cancel</Button>
              <Button variant="primary" loading={busy} onClick={saveEdit}>Save</Button>
            </div>
          </div>
        </div>
      )}

      {addStaff && (
        <div style={{ position: 'fixed', inset: 0, zIndex: 400, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16, background: 'rgba(42,31,26,0.5)' }}>
          <div style={{ background: 'var(--white)', borderRadius: 20, padding: 28, maxWidth: 460, width: '100%', maxHeight: '90vh', overflowY: 'auto', boxShadow: 'var(--shadow-deep)' }}>
            <h3 style={{ fontFamily: 'var(--font-display)', fontSize: 20, fontWeight: 500, marginBottom: 6 }}>Add staff user</h3>
            <p style={{ fontSize: 12.5, color: 'var(--fg-muted)', marginBottom: 16, lineHeight: 1.5 }}>The person must already have a registered account. Select them and choose what they can do — they'll get staff access limited to those areas only.</p>
            {msg && !msg.ok && <div style={{ padding: '8px 12px', borderRadius: 8, background: '#FEE2E2', color: '#B91C1C', fontSize: 12.5, marginBottom: 12 }}>{msg.text}</div>}
            <Field label="User">
              <select value={pick} onChange={(e) => setPick(e.target.value)} style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 14 }}>
                <option value="">— Select a registered user —</option>
                {candidates.map((u) => <option key={u.id} value={u.id}>{(u.display_name || u.full_name || u.id.slice(0, 8)) + ' · ' + u.role}</option>)}
              </select>
            </Field>
            <div style={{ marginTop: 14 }}>
              <div style={{ fontSize: 12.5, fontWeight: 700, marginBottom: 8, color: 'var(--fg-secondary)' }}>Permissions</div>
              <div style={{ display: 'grid', gap: 8 }}>
                {STAFF_PERM_OPTIONS.map((o) => (
                  <label key={o.key} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 13.5, cursor: 'pointer' }}>
                    <input type="checkbox" checked={perms.includes(o.key)} onChange={(e) => { const s = new Set(perms); if (e.target.checked) s.add(o.key); else s.delete(o.key); setPerms([...s]); }} style={{ width: 16, height: 16, accentColor: 'var(--gold-deep)' }} />
                    {o.label}
                  </label>
                ))}
              </div>
            </div>
            <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 20 }}>
              <Button variant="ghost" onClick={() => { setAddStaff(false); setMsg(null); }}>Cancel</Button>
              <Button variant="primary" loading={busy} disabled={!pick} onClick={doAddStaff}>Make Staff</Button>
            </div>
          </div>
        </div>
      )}

      {reg && (
        <div style={{ position: 'fixed', inset: 0, zIndex: 400, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16, background: 'rgba(42,31,26,0.5)' }}>
          <div style={{ background: 'var(--white)', borderRadius: 20, padding: 28, maxWidth: 480, width: '100%', maxHeight: '90vh', overflowY: 'auto', boxShadow: 'var(--shadow-deep)' }}>
            <h3 style={{ fontFamily: 'var(--font-display)', fontSize: 20, fontWeight: 500, marginBottom: 6 }}>Register new user</h3>
            <p style={{ fontSize: 12.5, color: 'var(--fg-muted)', marginBottom: 16, lineHeight: 1.5 }}>Creates a real login account with the email + password below and assigns the role. The email is confirmed immediately — share the password with the person so they can sign in (they can change it later).</p>
            {msg && !msg.ok && <div style={{ padding: '8px 12px', borderRadius: 8, background: '#FEE2E2', color: '#B91C1C', fontSize: 12.5, marginBottom: 12 }}>{msg.text}</div>}
            <div style={{ display: 'grid', gap: 12 }}>
              <Field label="Email"><TextInput type="email" value={reg.email} onChange={(e) => setReg((p) => ({ ...p, email: e.target.value }))} required /></Field>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
                <Field label="Name"><TextInput value={reg.display_name} onChange={(e) => setReg((p) => ({ ...p, display_name: e.target.value }))} /></Field>
                <Field label="Phone"><TextInput value={reg.phone} onChange={(e) => setReg((p) => ({ ...p, phone: e.target.value }))} /></Field>
              </div>
              <Field label="Temporary password (min 6 characters)"><TextInput type="text" value={reg.password} onChange={(e) => setReg((p) => ({ ...p, password: e.target.value }))} required /></Field>
              <Field label="Role">
                <select value={reg.role} onChange={(e) => setReg((p) => ({ ...p, role: e.target.value }))} style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 14 }}>
                  <option value="customer">Customer</option>
                  <option value="vendor">Vendor</option>
                  <option value="staff">Staff</option>
                  <option value="admin">Admin</option>
                </select>
              </Field>
              {reg.role === 'staff' && (
                <div>
                  <div style={{ fontSize: 12.5, fontWeight: 700, marginBottom: 8, color: 'var(--fg-secondary)' }}>Staff permissions</div>
                  <div style={{ display: 'grid', gap: 8 }}>
                    {STAFF_PERM_OPTIONS.map((o) => (
                      <label key={o.key} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 13.5, cursor: 'pointer' }}>
                        <input type="checkbox" checked={(reg.staff_permissions || []).includes(o.key)} onChange={(e) => setReg((p) => { const s = new Set(p.staff_permissions || []); if (e.target.checked) s.add(o.key); else s.delete(o.key); return { ...p, staff_permissions: [...s] }; })} style={{ width: 16, height: 16, accentColor: 'var(--gold-deep)' }} />
                        {o.label}
                      </label>
                    ))}
                  </div>
                </div>
              )}
            </div>
            <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 20 }}>
              <Button variant="ghost" onClick={() => { setReg(null); setMsg(null); }}>Cancel</Button>
              <Button variant="primary" loading={busy} onClick={doCreateUser}>Create User</Button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ---- One-time data migration / seed tool ---- */
function DataMigrationTool({ db }) {
  const [vendorId, setVendorId] = useStateAD('');
  const [vendors, setVendors]   = useStateAD([]);
  const [result, setResult]     = useStateAD(null);
  const [running, setRunning]   = useStateAD(false);

  useEffectAD(() => {
    if (!db) return;
    db.from('vendor_profiles').select('id, trade_name').eq('status', 'active')
      .then(({ data }) => setVendors(data || []));
  }, [db]);

  const runSeed = async () => {
    if (!vendorId) { alert('Select a vendor to assign the seeded products to.'); return; }
    if (!window.SarayaService) { alert('SarayaService not loaded.'); return; }
    if (!window.confirm('This will import demo/static data into Supabase. Continue? (Inserts all data.js products under the selected vendor -- run only once.)')) return;
    setRunning(true); setResult(null);
    const res = await window.SarayaService.seedFromDataJs(vendorId);
    setResult(res);
    setRunning(false);
  };

  return (
    <div style={{ display: 'grid', gap: 20 }}>
      <div style={{ padding: '20px 22px', borderRadius: 14, border: '1px solid var(--gold-light)', background: 'var(--cream)' }}>
        <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginBottom: 10 }}>
          <Icon name="alert-triangle" size={18} style={{ color: 'var(--gold-deep)' }} />
          <strong style={{ fontSize: 14 }}>Seed data.js Products → Supabase</strong>
        </div>
        <p style={{ fontSize: 13.5, color: 'var(--fg-secondary)', lineHeight: 1.6, marginBottom: 18 }}>
          Imports all existing <code>data.js</code> products into the <code>products</code> table. Run once after Supabase is configured. Assigns all products to the selected vendor.
        </p>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
          <select value={vendorId} onChange={(e) => setVendorId(e.target.value)}
            style={{ padding: '9px 12px', borderRadius: 9, border: '1px solid var(--line-strong)', fontFamily: 'var(--font-body)', fontSize: 14, minWidth: 220 }}>
            <option value="">— Select a vendor —</option>
            {vendors.map((v) => <option key={v.id} value={v.id}>{v.trade_name}</option>)}
          </select>
          <Button variant="primary" onClick={runSeed} disabled={running || !vendorId}>
            {running ? 'Running…' : 'Run Seed'}
          </Button>
        </div>
        {result && (
          <div style={{ marginTop: 14, padding: '10px 14px', borderRadius: 9, background: result.error ? 'var(--error-bg,#fef2f2)' : '#DCFCE7', color: result.error ? '#dc2626' : '#16a34a', fontSize: 13.5 }}>
            {result.error
              ? `Error: ${result.error}`
              : `Done — ${result.inserted} inserted, ${result.skipped} skipped (duplicates or missing category).`}
          </div>
        )}
      </div>
    </div>
  );
}

/* ---- Customer Requests (consolidated RFQs + Leads + Complaints) ---- */
function AdminCustomerRequests({ db, setActiveTab, stats }) {
  const cards = [
    { key: 'rfqs',       label: 'Open RFQs',       value: stats?.openRfqs || 0,      color: '#7C3AED', desc: 'Requests for quote awaiting a vendor response.' },
    { key: 'leads',      label: 'Total Leads',     value: stats?.totalLeads || 0,     color: '#0EA5E9', desc: 'Inbound customer inquiries captured platform-wide.' },
    { key: 'complaints', label: 'Open Complaints', value: stats?.openComplaints || 0, color: '#DC2626', desc: 'Disputes awaiting staff resolution.' },
  ];
  return (
    <AdminSection title="Customer Requests" desc="A unified view of everything customers are waiting on across RFQs, leads, and complaints. Each card links through to its full working tab; nothing here replaces those tabs.">
      <div style={{ padding: '16px 22px 22px', display: 'grid', gap: 14, gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))' }}>
        {cards.map((c) => (
          <div key={c.key} style={{ border: '1px solid var(--line)', borderRadius: 12, padding: 16, background: 'var(--white)' }}>
            <div style={{ fontSize: 28, fontWeight: 700, color: c.color }}>{c.value}</div>
            <div style={{ fontSize: 13.5, fontWeight: 600, marginTop: 4 }}>{c.label}</div>
            <div style={{ fontSize: 12, color: 'var(--fg-secondary)', marginTop: 4, lineHeight: 1.4 }}>{c.desc}</div>
            <div style={{ marginTop: 12 }}>
              <Button small variant="secondary" onClick={() => setActiveTab(c.key)}>Open {c.key === 'rfqs' ? 'RFQs' : c.key === 'leads' ? 'Leads' : 'Complaints'}</Button>
            </div>
          </div>
        ))}
      </div>
    </AdminSection>
  );
}

/* ---- Marketplace Activity (listing events only, separate from Activity Log) ---- */
function AdminMarketplaceActivity({ db }) {
  const [logs, setLogs]       = useStateAD([]);
  const [loading, setLoading] = useStateAD(true);

  useEffectAD(() => {
    if (!db) return;
    db.from('activity_logs')
      .select('*')
      .in('entity_type', ['product', 'rental', 'service'])
      .order('created_at', { ascending: false })
      .limit(150)
      .then(({ data }) => { setLogs(data || []); setLoading(false); });
  }, [db]);

  return (
    <AdminSection title="Marketplace Activity" desc="Listing events only, submissions, approvals, and rejections for products, rentals, and services. For all staff actions platform-wide, see Activity Log.">
      {loading ? (
        <div style={{ padding: 22, color: 'var(--fg-secondary)' }}>Loading...</div>
      ) : logs.length === 0 ? (
        <div style={{ padding: 22, color: 'var(--fg-secondary)' }}>No listing activity recorded yet.</div>
      ) : (
        <div style={{ padding: '0 22px 22px' }}>
          {logs.map((l) => (
            <div key={l.id} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, padding: '10px 0', borderBottom: '1px solid var(--line)' }}>
              <div>
                <div style={{ fontSize: 13.5, fontWeight: 600 }}>{l.action}</div>
                <div style={{ fontSize: 12, color: 'var(--fg-secondary)' }}>{l.entity_label || l.entity_type} by {l.actor_label || 'system'}</div>
              </div>
              <div style={{ fontSize: 12, color: 'var(--fg-secondary)', whiteSpace: 'nowrap' }}>{new Date(l.created_at).toLocaleString()}</div>
            </div>
          ))}
        </div>
      )}
    </AdminSection>
  );
}

/* ---- Staff Tasks (auto-generated queue from pending items) ---- */
function AdminStaffTasks({ db, setActiveTab, stats }) {
  const [pendingListings, setPendingListings] = useStateAD({ products: 0, rentals: 0, services: 0 });
  const [loading, setLoading] = useStateAD(true);

  useEffectAD(() => {
    if (!db) return;
    (async () => {
      const [p, r, s] = await Promise.all([
        db.from('products').select('id', { count: 'exact', head: true }).eq('status', 'pending'),
        db.from('rentals').select('id', { count: 'exact', head: true }).eq('status', 'pending'),
        db.from('services').select('id', { count: 'exact', head: true }).eq('status', 'pending'),
      ]);
      setPendingListings({ products: p.count || 0, rentals: r.count || 0, services: s.count || 0 });
      setLoading(false);
    })();
  }, [db]);

  const totalPendingListings = pendingListings.products + pendingListings.rentals + pendingListings.services;

  const tasks = [
    { key: 'vendors',     label: 'Vendor approvals waiting',   count: stats?.pendingApproval || 0, go: 'vendors' },
    { key: 'marketplace', label: 'Listings awaiting approval', count: totalPendingListings,         go: 'marketplace' },
    { key: 'complaints',  label: 'Open complaints',            count: stats?.openComplaints || 0,  go: 'complaints' },
    { key: 'payouts',     label: 'Payouts on hold',            count: stats?.heldPayouts || 0,      go: 'payouts' },
  ];

  return (
    <AdminSection title="Staff Tasks" desc="Auto-generated queue of everything waiting on staff action right now. Click a row to jump to the working tab.">
      {loading ? (
        <div style={{ padding: 22, color: 'var(--fg-secondary)' }}>Loading...</div>
      ) : (
        <div style={{ padding: '4px 0 12px' }}>
          {tasks.map((t) => (
            <div key={t.key} onClick={() => setActiveTab(t.go)} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '14px 22px', borderBottom: '1px solid var(--line)', cursor: 'pointer' }}>
              <div style={{ fontSize: 13.5, fontWeight: 600 }}>{t.label}</div>
              <span style={{ padding: '3px 12px', borderRadius: 20, background: t.count > 0 ? '#DC262618' : 'var(--bg-secondary)', color: t.count > 0 ? '#DC2626' : 'var(--fg-secondary)', fontSize: 12.5, fontWeight: 700 }}>{t.count}</span>
            </div>
          ))}
          {tasks.every((t) => t.count === 0) && (
            <div style={{ padding: '10px 22px', color: 'var(--fg-secondary)', fontSize: 13 }}>Nothing pending, staff queue is clear.</div>
          )}
        </div>
      )}
    </AdminSection>
  );
}

/* ---- AI Agent Notes (placeholder spec, not a live monitor) ---- */
function AdminAgentNotes() {
  const watchItems = [
    { title: 'Vendor approval SLA', detail: 'Alert if a vendor application sits pending for more than 48 hours without staff action.' },
    { title: 'Listing approval backlog', detail: 'Alert if pending products, rentals, or services exceed a threshold (e.g. 10 items) or sit unreviewed for more than 24 hours.' },
    { title: 'Complaint aging', detail: 'Alert if an open complaint has no resolution after 72 hours, especially where a payout is held.' },
    { title: 'Payout holds', detail: 'Flag payouts held longer than the stated review window so vendor payments do not silently stall.' },
    { title: 'Anomalous activity', detail: 'Watch activity_logs for unusual spikes, such as mass rejections or repeated failed status changes, that suggest a bug rather than normal usage.' },
    { title: 'Live-payment drift', detail: 'Re-check Finance and Payments messaging whenever real payment processing goes live, since current copy assumes no live Stripe integration.' },
  ];
  return (
    <AdminSection title="AI Agent Notes" desc="Placeholder: what a future monitoring agent would watch for, based on the go-live readiness review. Nothing here runs automatically yet, this is a spec, not a live monitor.">
      <div style={{ padding: '6px 22px 20px' }}>
        {watchItems.map((w) => (
          <div key={w.title} style={{ padding: '12px 0', borderBottom: '1px solid var(--line)' }}>
            <div style={{ fontSize: 13.5, fontWeight: 600 }}>{w.title}</div>
            <div style={{ fontSize: 12.5, color: 'var(--fg-secondary)', marginTop: 3, lineHeight: 1.5 }}>{w.detail}</div>
          </div>
        ))}
      </div>
    </AdminSection>
  );
}

/* ---- Activity Logs component ---- */
function AdminActivityLog({ db }) {
  const [logs, setLogs]       = useStateAD([]);
  const [loading, setLoading] = useStateAD(true);
  const [filter, setFilter]   = useStateAD('');

  useEffectAD(() => {
    if (!db) return;
    db.from('activity_logs')
      .select('*')
      .order('created_at', { ascending: false })
      .limit(200)
      .then(({ data }) => { setLogs(data || []); setLoading(false); });
  }, [db]);

  const filtered = filter ? logs.filter((l) => l.action?.includes(filter) || l.actor_label?.includes(filter) || l.entity_label?.includes(filter)) : logs;

  return (
    <AdminSection title="Admin Activity Log" desc="All admin and vendor actions logged in chronological order.">
      <div style={{ display: 'flex', gap: 10, marginBottom: 16 }}>
        <input
          value={filter}
          onChange={(e) => setFilter(e.target.value)}
          placeholder="Filter by action, actor, or entity…"
          style={{ flex: 1, padding: '9px 14px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 13.5, background: 'var(--white)', color: 'var(--fg-primary)' }}
        />
        {filter && <button onClick={() => setFilter('')} style={{ padding: '9px 14px', borderRadius: 8, border: '1px solid var(--line)', background: 'var(--white)', cursor: 'pointer', fontSize: 13.5, color: 'var(--fg-muted)' }}>Clear</button>}
      </div>
      {loading && <div style={{ padding: '32px', textAlign: 'center', color: 'var(--fg-muted)' }}><Icon name="loader" size={22} /></div>}
      {!loading && (
        <AdminTable
          emptyMsg="No activity logged yet."
          rows={filtered}
          cols={[
            { key: 'created_at',  label: 'When',   render: (r) => new Date(r.created_at).toLocaleString('en-AE', { dateStyle: 'short', timeStyle: 'short' }) },
            { key: 'actor_label', label: 'Actor',  render: (r) => <span style={{ fontSize: 12.5 }}>{r.actor_label || '—'}<br/><span style={{ color: 'var(--fg-muted)', fontSize: 11 }}>{r.actor_role}</span></span> },
            { key: 'action',      label: 'Action', render: (r) => <code style={{ fontSize: 12, background: 'var(--cream)', padding: '2px 7px', borderRadius: 4 }}>{r.action}</code> },
            { key: 'entity',      label: 'Entity', render: (r) => r.entity_type ? `${r.entity_type}: ${r.entity_label || r.entity_id?.slice(0, 8) || ''}` : '—' },
            { key: 'ip_address',  label: 'IP',     render: (r) => <span style={{ fontSize: 11, color: 'var(--fg-muted)' }}>{r.ip_address || '—'}</span> },
          ]}
        />
      )}
    </AdminSection>
  );
}


/* ---- Admin Subscriptions Management Tab ---- */
function AdminSubscriptionsTab({ db, vendors, tiers }) {
  const [subs, setSubs]               = useStateAD([]);
  const [settings, setSettings]       = useStateAD({});
  const [loading, setLoading]         = useStateAD(true);
  const [filterStatus, setFilterStatus] = useStateAD('all');
  const [filterPkg, setFilterPkg]     = useStateAD('all');
  const [showExpiring, setShowExpiring] = useStateAD(false);
  const [promoBusy, setPromoBusy]     = useStateAD(false);
  const [busyId, setBusyId]           = useStateAD('');
  const [selectedSub, setSelectedSub] = useStateAD(null); // for override modal
  const [overrideMode, setOverrideMode] = useStateAD(''); // 'extend'|'assign'|'cancel'
  const [overrideDays, setOverrideDays] = useStateAD(30);
  const [overridePkg, setOverridePkg] = useStateAD(2);
  const [overrideNote, setOverrideNote] = useStateAD('');
  const [editForm, setEditForm]       = useStateAD(null); // for full 'edit' mode
  const [reminderMap, setReminderMap] = useStateAD({});   // subscription_id -> latest reminder row

  const loadData = useCallbackAD(async () => {
    if (!db) return;
    setLoading(true);
    try {
      const [{ data: subData }, { data: settData }] = await Promise.all([
        db.from('subscriptions')
          .select('*, subscription_tiers!subscriptions_tier_id_fkey(*), vendor_profiles(trade_name, status, whatsapp)')
          .in('status', ['trialing', 'active', 'restricted', 'expired', 'cancelled'])
          .order('created_at', { ascending: false }),
        db.from('platform_settings')
          .select('key, value')
          .in('key', ['launch_promotion_active', 'launch_trial_days', 'default_trial_package_level']),
      ]);
      setSubs(subData || []);
      const settObj = {};
      (settData || []).forEach((s) => { settObj[s.key] = s.value; });
      setSettings(settObj);
    } catch (e) { console.error(e); }
    // Reminder history (non-fatal: if it fails the column just shows as —)
    try {
      const { data: remData } = await db.from('subscription_reminders')
        .select('subscription_id, stage, sent_at')
        .order('sent_at', { ascending: false });
      const remMap = {};
      (remData || []).forEach((x) => { if (!remMap[x.subscription_id]) remMap[x.subscription_id] = x; });
      setReminderMap(remMap);
    } catch (e) { /* non-fatal */ }
    setLoading(false);
  }, [db]);

  useEffectAD(() => { loadData(); }, [loadData]);

  const promoActive = settings['launch_promotion_active'] === true || settings['launch_promotion_active'] === 'true';

  const togglePromo = async () => {
    const newVal = !promoActive;
    if (!window.confirm(`${newVal ? 'Turn ON' : 'Turn OFF'} the launch promotion? This changes free package access for newly approved vendors.`)) return;
    setPromoBusy(true);
    await db.from('platform_settings')
      .update({ value: newVal, updated_at: new Date().toISOString() })
      .eq('key', 'launch_promotion_active');
    await sarayaLogActivity({ action: 'platform_setting_update', entityType: 'setting', entityLabel: 'launch_promotion_active', details: { value: newVal } });
    await loadData();
    setPromoBusy(false);
  };

  const doOverride = async () => {
    if (!selectedSub) return;
    setBusyId(selectedSub.id);
    try {
      if (overrideMode === 'extend') {
        const newEnd = new Date((selectedSub.trial_end_date ? new Date(selectedSub.trial_end_date) : new Date()).getTime() + overrideDays * 86400000);
        await db.from('subscriptions').update({
          trial_end_date: newEnd.toISOString(),
          status: 'trialing',
          is_trial_active: true,
          notes: overrideNote || null,
          package_changed_at: new Date().toISOString(),
        }).eq('id', selectedSub.id);
        await sarayaLogActivity({ action: 'trial_extended', entityType: 'subscription', entityId: selectedSub.id, entityLabel: selectedSub.vendor_profiles?.trade_name, details: { days: overrideDays, new_end: newEnd.toISOString(), note: overrideNote } });
      } else if (overrideMode === 'assign') {
        const tier = tiers.find((t) => t.package_level === overridePkg);
        if (!tier) { alert('Tier not found'); setBusyId(''); return; }
        await db.from('subscriptions').update({
          tier_id: tier.id,
          status: 'active',
          is_trial_active: false,
          is_free_access: true,
          current_period_start: new Date().toISOString(),
          current_period_end: new Date(Date.now() + overrideDays * 86400000).toISOString(),
          admin_override: 'free_access',
          notes: overrideNote || null,
          package_changed_at: new Date().toISOString(),
        }).eq('id', selectedSub.id);
        await sarayaLogActivity({ action: 'package_assigned', entityType: 'subscription', entityId: selectedSub.id, entityLabel: selectedSub.vendor_profiles?.trade_name, details: { pkg: overridePkg, days: overrideDays, note: overrideNote } });
      } else if (overrideMode === 'cancel') {
        await db.from('subscriptions').update({
          status: 'restricted',
          is_trial_active: false,
          notes: overrideNote || null,
          package_changed_at: new Date().toISOString(),
        }).eq('id', selectedSub.id);
        await db.from('vendor_profiles').update({ status: 'active' }).eq('id', selectedSub.vendor_id);
        await sarayaLogActivity({ action: 'trial_cancelled', entityType: 'subscription', entityId: selectedSub.id, entityLabel: selectedSub.vendor_profiles?.trade_name, details: { note: overrideNote } });
      } else if (overrideMode === 'edit') {
        const f = editForm || {};
        const toIso = (d) => (d ? new Date(d + 'T00:00:00Z').toISOString() : null);
        const upd = {
          status: f.status || 'active',
          is_trial_active: (f.status === 'trialing'),
          is_free_access: !!f.is_free_access,
          stripe_sub_id: (f.stripe_sub_id || '').trim() || null,
          trial_end_date: toIso(f.trial_end_date),
          notes: overrideNote || selectedSub.notes || null,
          package_changed_at: new Date().toISOString(),
        };
        if (f.tier_id) upd.tier_id = f.tier_id;
        const periodEnd = toIso(f.current_period_end);
        if (periodEnd) upd.current_period_end = periodEnd;
        if (selectedSub.id) {
          const { error } = await db.from('subscriptions').update(upd).eq('id', selectedSub.id);
          if (error) throw error;
        } else {
          if (!f.tier_id) throw new Error('Please choose a package to create a subscription.');
          let defEnd;
          if (f.status === 'trialing' && upd.trial_end_date) defEnd = upd.trial_end_date;
          else if (upd.is_free_access) defEnd = new Date(Date.now() + 365 * 86400000).toISOString();
          else defEnd = new Date(Date.now() + 30 * 86400000).toISOString();
          const ins = Object.assign({
            vendor_id: selectedSub.vendor_id,
            current_period_start: new Date().toISOString(),
            current_period_end: periodEnd || defEnd,
          }, upd);
          const { error } = await db.from('subscriptions').insert(ins);
          if (error) throw error;
        }
        await sarayaLogActivity({ action: 'subscription_edited', entityType: 'subscription', entityId: selectedSub.id, entityLabel: selectedSub.vendor_profiles?.trade_name, details: { status: upd.status, tier_id: f.tier_id, trial_end: upd.trial_end_date, period_end: periodEnd, stripe: upd.stripe_sub_id, free: upd.is_free_access } });
      }
    } catch (e) { console.error(e); window.alert('Could not save the change: ' + (e && e.message ? e.message : e)); }
    setSelectedSub(null);
    setOverrideMode('');
    setOverrideNote('');
    setBusyId('');
    loadData();
  };

  const now = new Date();
  const in7days = new Date(now.getTime() + 7 * 86400000);

  // Build vendor lookup from subs (subs have vendor_id)
  // Also add vendors with NO subscription
  const vendorSubMap = {};
  subs.forEach((s) => { if (s.vendor_id) vendorSubMap[s.vendor_id] = s; });

  const rows = vendors
    .filter((v) => ['active', 'approved', 'agreement_accepted'].includes(v.status))
    .map((v) => {
      const sub = vendorSubMap[v.id] || null;
      const tier = sub?.subscription_tiers || null;
      const trialEnd = sub?.trial_end_date ? new Date(sub.trial_end_date) : null;
      const trialDaysLeft = trialEnd ? Math.max(0, Math.ceil((trialEnd - now) / 86400000)) : null;
      const isTrial = sub?.is_trial_active && sub?.status === 'trialing';
      const isExpiringSoon = isTrial && trialEnd && trialEnd <= in7days && trialEnd >= now;
      const effectiveStatus = !sub ? 'no_sub'
        : sub.status === 'trialing' && trialEnd && trialEnd < now ? 'trial_expired'
        : sub.status;
      return { ...v, sub, tier, trialEnd, trialDaysLeft, isTrial, isExpiringSoon, effectiveStatus };
    });

  const filtered = rows.filter((r) => {
    if (showExpiring && !r.isExpiringSoon) return false;
    if (filterStatus !== 'all' && r.effectiveStatus !== filterStatus) return false;
    if (filterPkg !== 'all' && String(r.tier?.package_level ?? '0') !== filterPkg) return false;
    return true;
  });

  const statusColor = { trialing: '#D97706', active: '#16A34A', restricted: '#DC2626', trial_expired: '#DC2626', expired: '#9CA3AF', cancelled: '#9CA3AF', no_sub: '#6B7280' };
  const statusLabel = { trialing: 'Trial', active: 'Active', restricted: 'Restricted', trial_expired: 'Trial Expired', expired: 'Expired', cancelled: 'Cancelled', no_sub: 'No Plan' };

  const inputStyle = { padding: '9px 12px', borderRadius: 8, border: '1.5px solid var(--line)', fontFamily: 'var(--font-body)', fontSize: 13.5, background: 'var(--white)', color: 'var(--fg-primary)', outline: 'none' };
  const labelStyle = { fontSize: 12.5, fontWeight: 600, color: 'var(--fg-secondary)', marginBottom: 5, display: 'block' };

  return (
    <div style={{ display: 'grid', gap: 20 }}>

      {/* Launch Promotion Toggle */}
      <div style={{ padding: '18px 22px', borderRadius: 14, border: '1.5px solid var(--gold-light)', background: 'var(--cream)', display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap' }}>
        <Icon name="zap" size={20} style={{ color: 'var(--gold-deep)', flexShrink: 0 }} />
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 700, fontSize: 14, color: 'var(--fg-primary)', marginBottom: 2 }}>Launch Promotion</div>
          <div style={{ fontSize: 13, color: 'var(--fg-secondary)' }}>
            When <strong>ON</strong>, new approved vendors automatically receive a {settings['launch_trial_days'] || 60}-day free trial on the Growth Vendor package. Currently: <strong style={{ color: promoActive ? '#16A34A' : '#DC2626' }}>{promoActive ? 'ACTIVE' : 'INACTIVE'}</strong>
          </div>
        </div>
        <button
          onClick={togglePromo}
          disabled={promoBusy}
          style={{
            padding: '10px 22px', borderRadius: 10, border: 'none', cursor: promoBusy ? 'not-allowed' : 'pointer',
            fontFamily: 'var(--font-body)', fontSize: 13.5, fontWeight: 600,
            background: promoActive ? '#FEF2F2' : '#F0FDF4',
            color: promoActive ? '#DC2626' : '#16A34A',
            transition: 'all 160ms',
          }}
        >
          {promoBusy ? 'Saving…' : promoActive ? 'Turn OFF Promo' : 'Turn ON Promo'}
        </button>
      </div>

      {/* Stats row */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(160px,1fr))', gap: 12 }}>
        {[
          { label: 'Trial Active',   value: rows.filter((r) => r.isTrial).length,                               color: '#D97706' },
          { label: 'Paid Active',    value: rows.filter((r) => r.effectiveStatus === 'active' && !r.sub?.is_free_access).length, color: '#16A34A' },
          { label: 'Free Access',    value: rows.filter((r) => r.sub?.is_free_access && ['active','trialing'].includes(r.effectiveStatus)).length,                   color: '#2563EB' },
          { label: 'Expiring ≤7d',   value: rows.filter((r) => r.isExpiringSoon).length,                        color: '#DC2626' },
          { label: 'Restricted',     value: rows.filter((r) => ['restricted','trial_expired','no_sub'].includes(r.effectiveStatus)).length, color: '#9CA3AF' },
        ].map((s) => (
          <div key={s.label} style={{ background: 'var(--white)', borderRadius: 12, border: '1px solid var(--line)', padding: '14px 16px', textAlign: 'center' }}>
            <div style={{ fontSize: 24, fontWeight: 700, color: s.color }}>{s.value}</div>
            <div style={{ fontSize: 12, color: 'var(--fg-muted)', marginTop: 2 }}>{s.label}</div>
          </div>
        ))}
      </div>

      {/* Filters */}
      <AdminSection title="Vendor Subscriptions" desc="Manage packages, trials, and overrides for all active vendors.">
        <div style={{ padding: '12px 20px 0', display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
          <select value={filterStatus} onChange={(e) => setFilterStatus(e.target.value)} style={{ ...inputStyle, minWidth: 150 }}>
            <option value="all">All Statuses</option>
            <option value="trialing">Trial Active</option>
            <option value="active">Paid/Free Active</option>
            <option value="restricted">Restricted</option>
            <option value="trial_expired">Trial Expired</option>
            <option value="no_sub">No Subscription</option>
          </select>
          <select value={filterPkg} onChange={(e) => setFilterPkg(e.target.value)} style={{ ...inputStyle, minWidth: 150 }}>
            <option value="all">All Packages</option>
            <option value="1">Starter Vendor</option>
            <option value="2">Growth Vendor</option>
            <option value="3">Premium Vendor</option>
            <option value="0">No Package</option>
          </select>
          <button
            onClick={() => setShowExpiring((v) => !v)}
            style={{ padding: '9px 14px', borderRadius: 8, border: `1.5px solid ${showExpiring ? '#DC2626' : 'var(--line)'}`, fontFamily: 'var(--font-body)', fontSize: 13, fontWeight: 600, background: showExpiring ? '#FEF2F2' : 'var(--white)', color: showExpiring ? '#DC2626' : 'var(--fg-secondary)', cursor: 'pointer' }}
          >
            <Icon name="clock" size={13} style={{ marginRight: 5 }} />Expiring Soon
          </button>
          {(filterStatus !== 'all' || filterPkg !== 'all' || showExpiring) && (
            <button onClick={() => { setFilterStatus('all'); setFilterPkg('all'); setShowExpiring(false); }} style={{ padding: '9px 12px', borderRadius: 8, border: '1px solid var(--line)', background: 'var(--white)', fontSize: 13, color: 'var(--fg-muted)', cursor: 'pointer' }}>Clear</button>
          )}
          <span style={{ fontSize: 12.5, color: 'var(--fg-muted)', marginLeft: 'auto' }}>{filtered.length} vendor{filtered.length !== 1 ? 's' : ''}</span>
        </div>

        {loading ? (
          <div style={{ padding: 40, textAlign: 'center', color: 'var(--fg-muted)' }}><Icon name="loader" size={22} /></div>
        ) : (
          <div style={{ overflowX: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13.5 }}>
              <thead>
                <tr style={{ borderBottom: '2px solid var(--line)' }}>
                  {['Vendor', 'Package', 'Status', 'Trial / Expiry', 'Days Left', 'Stripe', 'Last reminded', 'Actions'].map((h) => (
                    <th key={h} style={{ padding: '10px 14px', textAlign: 'left', fontWeight: 600, color: 'var(--fg-secondary)', fontSize: 12.5, whiteSpace: 'nowrap' }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {filtered.length === 0 && (
                  <tr><td colSpan={8} style={{ padding: '32px', textAlign: 'center', color: 'var(--fg-muted)' }}>No vendors match the selected filters.</td></tr>
                )}
                {filtered.map((r) => (
                  <tr key={r.id} style={{ borderBottom: '1px solid var(--line)', background: r.isExpiringSoon ? '#FFFBEB' : 'var(--white)', transition: 'background 120ms' }}>
                    <td style={{ padding: '10px 14px' }}>
                      <div style={{ fontWeight: 600, color: 'var(--fg-primary)', display: 'flex', alignItems: 'center', gap: 6 }}>{r.trade_name}{/test/i.test(r.trade_name || '') && <span style={{ padding: '1px 6px', borderRadius: 5, background: '#FEE2E2', color: '#DC2626', fontSize: 10, fontWeight: 700 }}>TEST</span>}</div>
                      <div style={{ fontSize: 11.5, color: 'var(--fg-muted)' }}>{r.sub?.vendor_id?.slice(0,8) || r.id?.slice(0,8)}</div>
                    </td>
                    <td style={{ padding: '10px 14px' }}>
                      {r.tier ? (
                        <span style={{ padding: '3px 9px', borderRadius: 6, background: 'var(--cream)', color: 'var(--gold-deep)', fontSize: 12, fontWeight: 600 }}>
                          {r.tier.name.replace(' Vendor', '')} Package
                        </span>
                      ) : <span style={{ color: 'var(--fg-muted)' }}>—</span>}
                    </td>
                    <td style={{ padding: '10px 14px' }}>
                      <span style={{ padding: '3px 9px', borderRadius: 6, background: (statusColor[r.effectiveStatus] || '#9CA3AF') + '18', color: statusColor[r.effectiveStatus] || '#9CA3AF', fontSize: 12, fontWeight: 600 }}>
                        {statusLabel[r.effectiveStatus] || r.effectiveStatus}
                      </span>
                      {r.sub?.is_free_access && ['active','trialing'].includes(r.effectiveStatus) && <span style={{ marginLeft: 5, padding: '2px 7px', borderRadius: 6, background: '#EFF6FF', color: '#2563EB', fontSize: 11, fontWeight: 600 }}>FREE</span>}
                    </td>
                    <td style={{ padding: '10px 14px', fontSize: 12.5, color: 'var(--fg-secondary)', whiteSpace: 'nowrap' }}>
                      {r.trialEnd ? new Date(r.trialEnd).toLocaleDateString('en-AE') : '—'}
                    </td>
                    <td style={{ padding: '10px 14px', textAlign: 'center' }}>
                      {r.isTrial && r.trialDaysLeft !== null ? (
                        <span style={{ fontWeight: 700, color: r.trialDaysLeft <= 7 ? '#DC2626' : r.trialDaysLeft <= 14 ? '#D97706' : '#16A34A', fontSize: 13 }}>
                          {r.trialDaysLeft}d
                        </span>
                      ) : <span style={{ color: 'var(--fg-muted)' }}>—</span>}
                    </td>
                    <td style={{ padding: '10px 14px', fontSize: 12, color: 'var(--fg-muted)' }}>
                      {r.sub?.stripe_sub_id
                        ? <span style={{ color: '#16A34A', fontWeight: 600 }}>✓ {r.sub.stripe_sub_id.slice(0,12)}…</span>
                        : <span style={{ color: '#9CA3AF' }}>No Stripe</span>}
                    </td>
                    <td style={{ padding: '10px 14px', fontSize: 12, color: 'var(--fg-secondary)', whiteSpace: 'nowrap' }}>
                      {(() => {
                        const rm = r.sub && reminderMap[r.sub.id];
                        if (!rm) return <span style={{ color: 'var(--fg-muted)' }}>-</span>;
                        const label = rm.stage === 0 ? 'Expired notice' : rm.stage + '-day reminder';
                        return (
                          <span title={label + ' - ' + new Date(rm.sent_at).toLocaleString('en-AE')}>
                            {label}
                            <div style={{ color: 'var(--fg-muted)', fontSize: 11 }}>{new Date(rm.sent_at).toLocaleDateString('en-AE')}</div>
                          </span>
                        );
                      })()}
                    </td>
                    <td style={{ padding: '10px 14px' }}>
                      <RowActionsMenu items={[
                        { label: 'Edit', icon: 'pencil', onClick: () => { setSelectedSub(r.sub ? { ...r.sub, vendor_profiles: { trade_name: r.trade_name } } : { vendor_id: r.id, id: null, vendor_profiles: { trade_name: r.trade_name } }); setOverrideMode('edit'); setEditForm({ tier_id: (r.sub && r.sub.tier_id) || (r.tier && r.tier.id) || '', status: (r.sub && r.sub.status) || 'active', trial_end_date: (r.sub && r.sub.trial_end_date) ? String(r.sub.trial_end_date).slice(0, 10) : '', current_period_end: (r.sub && r.sub.current_period_end) ? String(r.sub.current_period_end).slice(0, 10) : '', stripe_sub_id: (r.sub && r.sub.stripe_sub_id) || '', is_free_access: !!(r.sub && r.sub.is_free_access) }); setOverrideNote(''); } },
                        { label: 'Grant / extend trial', icon: 'gift', onClick: () => { setSelectedSub(r.sub ? { ...r.sub, vendor_profiles: { trade_name: r.trade_name } } : { vendor_id: r.id, id: null, vendor_profiles: { trade_name: r.trade_name } }); setOverrideMode('extend'); setOverrideDays(30); setOverrideNote(''); } },
                        { label: 'Assign package', icon: 'layers', onClick: () => { setSelectedSub(r.sub ? { ...r.sub, vendor_profiles: { trade_name: r.trade_name } } : { vendor_id: r.id, id: null, vendor_profiles: { trade_name: r.trade_name } }); setOverrideMode('assign'); setOverridePkg(2); setOverrideDays(365); setOverrideNote(''); } },
                        (r.isTrial || r.effectiveStatus === 'active') ? { label: 'Restrict', icon: 'ban', danger: true, onClick: () => { setSelectedSub(r.sub ? { ...r.sub, vendor_profiles: { trade_name: r.trade_name } } : { vendor_id: r.id, id: null, vendor_profiles: { trade_name: r.trade_name } }); setOverrideMode('cancel'); setOverrideNote(''); } } : null,
                      ]} />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </AdminSection>

      {/* Override Modal */}
      {selectedSub && overrideMode && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.55)', zIndex: 9999, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20 }}
          onClick={(e) => { if (e.target === e.currentTarget) { setSelectedSub(null); setOverrideMode(''); } }}>
          <div style={{ background: 'var(--white)', borderRadius: 18, padding: '28px 30px', maxWidth: 440, width: '100%', boxShadow: '0 20px 60px rgba(0,0,0,0.25)' }}>
            <div style={{ fontFamily: 'var(--font-display)', fontSize: 18, fontWeight: 600, marginBottom: 6 }}>
              {overrideMode === 'extend' ? 'Extend / Grant Trial' : overrideMode === 'assign' ? 'Assign Package' : overrideMode === 'edit' ? 'Edit Subscription' : 'Restrict Vendor'}
            </div>
            <div style={{ fontSize: 13.5, color: 'var(--fg-secondary)', marginBottom: 20 }}>
              Vendor: <strong>{selectedSub.vendor_profiles?.trade_name || selectedSub.vendor_id}</strong>
            </div>

            {overrideMode === 'extend' && (
              <div style={{ display: 'grid', gap: 14 }}>
                <div>
                  <label style={labelStyle}>Extend Trial by (days)</label>
                  <div style={{ display: 'flex', gap: 8 }}>
                    {[7, 14, 30, 60].map((d) => (
                      <button key={d} onClick={() => setOverrideDays(d)}
                        style={{ flex: 1, padding: '8px 0', borderRadius: 8, border: `1.5px solid ${overrideDays === d ? 'var(--gold-deep)' : 'var(--line)'}`, background: overrideDays === d ? 'var(--cream)' : 'var(--white)', color: overrideDays === d ? 'var(--gold-deep)' : 'var(--fg-secondary)', fontWeight: 600, fontSize: 13, cursor: 'pointer' }}
                      >{d}d</button>
                    ))}
                  </div>
                </div>
              </div>
            )}

            {overrideMode === 'assign' && (
              <div style={{ display: 'grid', gap: 14 }}>
                <div>
                  <label style={labelStyle}>Package</label>
                  <div style={{ display: 'flex', gap: 8 }}>
                    {[{l:1,n:'Starter'},{l:2,n:'Growth'},{l:3,n:'Premium'}].map((p) => (
                      <button key={p.l} onClick={() => setOverridePkg(p.l)}
                        style={{ flex: 1, padding: '8px 0', borderRadius: 8, border: `1.5px solid ${overridePkg === p.l ? 'var(--gold-deep)' : 'var(--line)'}`, background: overridePkg === p.l ? 'var(--cream)' : 'var(--white)', color: overridePkg === p.l ? 'var(--gold-deep)' : 'var(--fg-secondary)', fontWeight: 600, fontSize: 12.5, cursor: 'pointer' }}
                      >P{p.l}<br/><span style={{ fontSize: 11, fontWeight: 400 }}>{p.n}</span></button>
                    ))}
                  </div>
                </div>
                <div>
                  <label style={labelStyle}>Duration (days of free access)</label>
                  <input type="number" value={overrideDays} onChange={(e) => setOverrideDays(Number(e.target.value))} min={1} style={{ ...inputStyle, width: '100%' }} />
                </div>
              </div>
            )}

            {overrideMode === 'edit' && editForm && (
              <div style={{ display: 'grid', gap: 14 }}>
                <div>
                  <label style={labelStyle}>Package</label>
                  <select value={editForm.tier_id || ''} onChange={(e) => setEditForm((p) => ({ ...p, tier_id: e.target.value }))} style={{ ...inputStyle, width: '100%' }}>
                    <option value="">- No package -</option>
                    {(tiers || []).map((t) => <option key={t.id} value={t.id}>{t.name} (P{t.package_level})</option>)}
                  </select>
                </div>
                <div>
                  <label style={labelStyle}>Status</label>
                  <select value={editForm.status || 'active'} onChange={(e) => setEditForm((p) => ({ ...p, status: e.target.value }))} style={{ ...inputStyle, width: '100%' }}>
                    <option value="active">Active</option>
                    <option value="trialing">Trial</option>
                    <option value="restricted">Restricted</option>
                    <option value="expired">Expired</option>
                    <option value="cancelled">Cancelled</option>
                  </select>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
                  <div>
                    <label style={labelStyle}>Trial end</label>
                    <input type="date" value={editForm.trial_end_date || ''} onChange={(e) => setEditForm((p) => ({ ...p, trial_end_date: e.target.value }))} style={{ ...inputStyle, width: '100%', boxSizing: 'border-box' }} />
                  </div>
                  <div>
                    <label style={labelStyle}>Paid expiry</label>
                    <input type="date" value={editForm.current_period_end || ''} onChange={(e) => setEditForm((p) => ({ ...p, current_period_end: e.target.value }))} style={{ ...inputStyle, width: '100%', boxSizing: 'border-box' }} />
                  </div>
                </div>
                <div>
                  <label style={labelStyle}>Stripe subscription ID</label>
                  <input type="text" value={editForm.stripe_sub_id || ''} placeholder="sub_..." onChange={(e) => setEditForm((p) => ({ ...p, stripe_sub_id: e.target.value }))} style={{ ...inputStyle, width: '100%', boxSizing: 'border-box' }} />
                </div>
                <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: 'var(--fg-secondary)', cursor: 'pointer' }}>
                  <input type="checkbox" checked={!!editForm.is_free_access} onChange={(e) => setEditForm((p) => ({ ...p, is_free_access: e.target.checked }))} /> Free access (no charge)
                </label>
              </div>
            )}

            {overrideMode === 'cancel' && (
              <div style={{ padding: '12px 16px', borderRadius: 10, background: '#FEF2F2', border: '1px solid #FCA5A5', fontSize: 13.5, color: '#DC2626', marginBottom: 4 }}>
                This vendor will be set to <strong>Restricted</strong> — they can log in and view their dashboard but cannot publish listings, respond to RFQs, or appear in the marketplace until they subscribe.
              </div>
            )}

            <div style={{ marginTop: 16 }}>
              <label style={labelStyle}>Admin Note (optional)</label>
              <textarea value={overrideNote} onChange={(e) => setOverrideNote(e.target.value)}
                placeholder="Internal note saved to subscription log…"
                rows={2}
                style={{ ...inputStyle, width: '100%', resize: 'vertical', boxSizing: 'border-box' }}
              />
            </div>

            <div style={{ display: 'flex', gap: 10, marginTop: 20 }}>
              <button onClick={() => { setSelectedSub(null); setOverrideMode(''); }}
                style={{ flex: 1, padding: '10px 0', borderRadius: 9, border: '1px solid var(--line)', background: 'var(--white)', fontSize: 14, cursor: 'pointer', color: 'var(--fg-secondary)', fontWeight: 600 }}
              >Cancel</button>
              <button onClick={doOverride} disabled={!!busyId}
                style={{ flex: 1, padding: '10px 0', borderRadius: 9, border: 'none', fontSize: 14, cursor: busyId ? 'not-allowed' : 'pointer', fontWeight: 700,
                  background: overrideMode === 'cancel' ? '#DC2626' : 'var(--espresso)', color: 'var(--white)' }}
              >{busyId ? 'Saving…' : overrideMode === 'extend' ? 'Extend Trial' : overrideMode === 'assign' ? 'Assign Package' : overrideMode === 'edit' ? 'Save Changes' : 'Restrict Vendor'}</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ---- sarayaLogActivity — call from anywhere after an admin action ---- */
async function sarayaLogActivity({ action, entityType, entityId, entityLabel, details }) {
  const db = window.SarayaDB;
  if (!db) return;
  const { data: { user } } = await db.auth.getUser().catch(() => ({ data: {} }));
  if (!user) return;
  const { data: profile } = await Promise.resolve(db.from('profiles').select('display_name, role').eq('id', user.id).single()).catch(() => ({ data: null }));
  await Promise.resolve(db.from('activity_logs').insert({
    actor_id:     user.id,
    actor_role:   profile?.role || 'unknown',
    actor_label:  profile?.display_name || user.email,
    action,
    entity_type:  entityType || null,
    entity_id:    entityId   || null,
    entity_label: entityLabel || null,
    details:      details     || {},
  })).catch(() => {});
}
window.sarayaLogActivity = sarayaLogActivity;
