// PPEScreen.jsx — AegisComply (Supabase-powered CRUD + real-time)

const PPE_PAGE_SIZE = 15;

// ── Sortable column header helper ───────────────────────────────────────────
function SortHeaderPPE({ label, field, sort, setSort, style }) {
  const active = sort.field === field;
  const dir = active ? sort.dir : null;
  const click = () => setSort({ field, dir: !active ? 'asc' : sort.dir === 'asc' ? 'desc' : 'asc' });
  return (
    <div onClick={click} style={{ ...style, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 4, userSelect: 'none' }}>
      <span>{label}</span>
      <span style={{ fontSize: 9, color: active ? '#0D9488' : '#CBD5E1', lineHeight: 1 }}>
        {dir === 'asc' ? '▲' : dir === 'desc' ? '▼' : '↕'}
      </span>
    </div>
  );
}
const ISSUANCE_LIMIT = 10;
const PPE_CATEGORIES = ['GLOVES', 'EAR PROTECTION', 'SAFETY SHOES', 'HEAD PROTECTION', 'EYE PROTECTION', 'BODY PROTECTION', 'RESPIRATORY', 'FALL PROTECTION', 'OTHER'];
const PPE_STATUS_OPTIONS = [
  { value: 'ok',       label: 'OK' },
  { value: 'low',      label: 'Low' },
  { value: 'critical', label: 'Critical' },
];
const PPE_UNITS = ['pcs', 'pairs', 'sets', 'boxes'];
const PPE_CONDITIONS = ['Good', 'Fair', 'Damaged', 'Expired'];
const DEPARTMENTS = ['Operations', 'Maintenance', 'Quality', 'HSE', 'Logistics', 'Production', 'Engineering', 'Workshop', 'Warehouse', 'Lab', 'Semiconductor', 'Utilities', 'Food Processing'];

// ── Helpers ─────────────────────────────────────────────────────────────────
function computePPEStatus(balance, minStock) {
  if (!minStock || minStock <= 0) return 'ok';
  if (balance <= 0)                   return 'critical';
  if (balance < minStock * 0.5)       return 'critical';
  if (balance < minStock)             return 'low';
  return 'ok';
}

function isoToDMY_PPE(iso) {
  if (!iso) return '';
  const m = String(iso).match(/^(\d{4})-(\d{2})-(\d{2})/);
  return m ? `${m[3]}/${m[2]}/${m[1]}` : String(iso);
}

function fmtDate_PPE(d) {
  if (!d) return '—';
  try { return new Date(d).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }); }
  catch { return d; }
}

function fmtDateTime_PPE(d) {
  if (!d) return '—';
  try { return new Date(d).toLocaleString('en-MY', { dateStyle: 'medium', timeStyle: 'short' }); }
  catch { return d; }
}

function parseExcelDate_PPE(value) {
  if (value === null || value === undefined || value === '') return null;
  if (value instanceof Date) {
    const y = value.getFullYear(); const m = String(value.getMonth()+1).padStart(2,'0'); const d = String(value.getDate()).padStart(2,'0');
    return `${y}-${m}-${d}`;
  }
  const s = String(value).trim();
  const dmy = s.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
  if (dmy) return `${dmy[3]}-${dmy[2].padStart(2,'0')}-${dmy[1].padStart(2,'0')}`;
  if (/^\d{4}-\d{2}-\d{2}/.test(s)) return s.slice(0,10);
  return null;
}

// ── Styles ──────────────────────────────────────────────────────────────────
const ppeStyles = {
  page: { padding: 24 },
  tabs: { display: 'flex', gap: 2, marginBottom: 20, background: 'white', border: '1px solid #E2E8F0', borderRadius: 8, padding: 4, width: 'fit-content', boxShadow: '0 1px 3px rgba(0,0,0,0.05)' },
  tab: { padding: '7px 18px', borderRadius: 6, fontSize: 13, fontWeight: 500, cursor: 'pointer', border: 'none', background: 'transparent', color: '#64748B', fontFamily: "'DM Sans', sans-serif", transition: 'all 150ms' },
  tabActive: { background: '#0B1F3A', color: 'white', fontWeight: 600 },

  toolbar: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 20, flexWrap: 'wrap' },
  searchWrap: { position: 'relative', flex: 1, maxWidth: 300 },
  searchInput: { width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 12px 0 36px', fontFamily: "'DM Sans', sans-serif", fontSize: 13, color: '#334155', outline: 'none', background: 'white' },
  searchIcon: { position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', color: '#94A3B8', pointerEvents: 'none' },
  select: { height: 36, padding: '0 28px 0 12px', border: '1px solid #CBD5E1', borderRadius: 6, background: 'white', fontSize: 13, fontWeight: 500, color: '#475569', cursor: 'pointer', fontFamily: "'DM Sans', sans-serif", outline: 'none', appearance: 'none', backgroundImage: 'url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'12\' height=\'12\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'%2364748B\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-linejoin=\'round\'%3e%3cpolyline points=\'6 9 12 15 18 9\'%3e%3c/polyline%3e%3c/svg%3e")', backgroundRepeat: 'no-repeat', backgroundPosition: 'right 8px center' },
  toolbarBtn: { height: 36, padding: '0 14px', border: '1px solid #CBD5E1', borderRadius: 6, background: 'white', fontSize: 13, fontWeight: 600, color: '#475569', cursor: 'pointer', fontFamily: "'DM Sans', sans-serif", display: 'flex', alignItems: 'center', gap: 6 },
  toolbarBtnPrimary: { background: '#0D9488', color: 'white', border: 'none' },
  toolbarBtnIssue: { background: '#0B1F3A', color: 'white', border: 'none' },
  toolbarBtnDisabled: { color: '#CBD5E1', cursor: 'not-allowed' },

  card: { background: 'white', border: '1px solid #E2E8F0', borderRadius: 8, overflow: 'hidden', boxShadow: '0 1px 3px rgba(0,0,0,0.06)', marginBottom: 20 },
  cardHeader: { padding: '14px 16px', borderBottom: '1px solid #F1F5F9', display: 'flex', alignItems: 'center', justifyContent: 'space-between' },
  cardTitle: { fontSize: 14, fontWeight: 600, color: '#0F172A', fontFamily: "'Helvetica', Arial, sans-serif" },
  tableHead: { display: 'grid', gridTemplateColumns: '160px 2.5fr 1.4fr 1.6fr 100px 80px', gap: 8, padding: '10px 16px', background: '#F8FAFC', borderBottom: '1px solid #E2E8F0' },
  tableRow: { display: 'grid', gridTemplateColumns: '160px 2.5fr 1.4fr 1.6fr 100px 80px', gap: 8, padding: '11px 16px', borderBottom: '1px solid #F1F5F9', cursor: 'pointer', transition: 'background 150ms', alignItems: 'center' },
  thCell: { fontSize: 11, fontWeight: 600, letterSpacing: '0.07em', textTransform: 'uppercase', color: '#94A3B8' },
  ppeName: { fontSize: 13, fontWeight: 500, color: '#0F172A' },
  ppeMono: { fontSize: 11, fontFamily: "'JetBrains Mono', monospace", color: '#64748B' },
  ppeCategory: { fontSize: 11, color: '#94A3B8', marginTop: 1 },
  sizeChip: { display: 'inline-block', padding: '1px 6px', borderRadius: 3, background: '#F1F5F9', color: '#475569', fontSize: 10, fontWeight: 600, marginLeft: 6 },

  stockBar: { height: 5, borderRadius: 3, background: '#E2E8F0', overflow: 'hidden', marginTop: 4 },
  stockFill: { height: '100%', borderRadius: 3 },
  badge: { display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 7px', borderRadius: 4, fontSize: 10, fontWeight: 700, letterSpacing: '0.05em', textTransform: 'uppercase' },
  rowActions: { display: 'flex', gap: 4, alignItems: 'center' },
  iconBtn: { width: 28, height: 28, borderRadius: 5, border: '1px solid #E2E8F0', background: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: '#64748B', transition: 'all 150ms' },

  pagination: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px 16px', borderTop: '1px solid #F1F5F9' },
  pageInfo: { fontSize: 12, color: '#64748B' },
  pageButtons: { display: 'flex', gap: 4 },
  pageBtn: { minWidth: 30, height: 30, borderRadius: 5, border: '1px solid #E2E8F0', background: 'white', fontSize: 12, color: '#475569', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '0 8px', fontFamily: "'DM Sans', sans-serif" },
  pageBtnActive: { background: '#0D9488', color: 'white', border: '1px solid #0D9488' },
  pageBtnDisabled: { color: '#CBD5E1', cursor: 'not-allowed' },

  emptyState: { padding: 40, textAlign: 'center' },
  emptyIcon: { width: 48, height: 48, borderRadius: 12, background: '#F1F5F9', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginBottom: 12 },
  emptyTitle: { fontSize: 14, fontWeight: 600, color: '#334155', marginBottom: 4 },
  emptySub: { fontSize: 12, color: '#94A3B8' },

  issuanceRow: { padding: '10px 16px', borderBottom: '1px solid #F1F5F9' },
  issuanceName: { fontSize: 13, fontWeight: 600, color: '#0F172A' },
  issuanceMeta: { fontSize: 11, color: '#94A3B8', lineHeight: 1.7, marginTop: 1 },
  issuanceItems: { fontSize: 12, color: '#475569', marginTop: 2 },
  deptChip: { display: 'inline-flex', padding: '1px 7px', borderRadius: 3, background: '#EFF6FF', color: '#2563EB', fontSize: 10, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', marginLeft: 4 },

  // Modal
  overlay: { position: 'fixed', inset: 0, background: 'rgba(11,31,58,0.45)', zIndex: 9000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20 },
  modal: { background: 'white', borderRadius: 12, width: '100%', maxWidth: 640, maxHeight: '90vh', display: 'flex', flexDirection: 'column', boxShadow: '0 16px 48px rgba(0,0,0,0.18)' },
  modalHeader: { padding: '18px 24px', borderBottom: '1px solid #E2E8F0', display: 'flex', alignItems: 'center', justifyContent: 'space-between' },
  modalTitle: { fontFamily: "'Helvetica',Arial,sans-serif", fontSize: 16, fontWeight: 700, color: '#0F172A' },
  modalClose: { width: 30, height: 30, borderRadius: 6, border: 'none', background: '#F1F5F9', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#64748B' },
  modalBody: { padding: '20px 24px', overflowY: 'auto', flex: 1 },
  modalFooter: { padding: '14px 24px', borderTop: '1px solid #E2E8F0', display: 'flex', gap: 10, justifyContent: 'flex-end', background: '#F8FAFC' },
  field: { marginBottom: 14 },
  fieldRow: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 },
  fieldRow3: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 },
  label: { fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 5 },
  required: { color: '#DC2626', marginLeft: 2 },
  input: { width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 10px', fontFamily: "'DM Sans',sans-serif", fontSize: 13, color: '#0F172A', outline: 'none', background: 'white', boxSizing: 'border-box' },
  textarea: { width: '100%', minHeight: 60, border: '1px solid #CBD5E1', borderRadius: 6, padding: '8px 10px', fontFamily: "'DM Sans',sans-serif", fontSize: 13, color: '#0F172A', outline: 'none', background: 'white', resize: 'vertical', boxSizing: 'border-box' },
  selectInput: { width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 28px 0 10px', fontFamily: "'DM Sans',sans-serif", fontSize: 13, color: '#0F172A', outline: 'none', background: 'white', appearance: 'none', backgroundImage: 'url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'12\' height=\'12\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'%2364748B\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-linejoin=\'round\'%3e%3cpolyline points=\'6 9 12 15 18 9\'%3e%3c/polyline%3e%3c/svg%3e")', backgroundRepeat: 'no-repeat', backgroundPosition: 'right 8px center', boxSizing: 'border-box' },
  fileWrap: { display: 'flex', alignItems: 'center', gap: 10 },
  fileBtn: { height: 36, padding: '0 14px', border: '1px dashed #CBD5E1', borderRadius: 6, background: 'white', fontSize: 13, fontWeight: 500, color: '#0D9488', cursor: 'pointer', fontFamily: "'DM Sans',sans-serif" },
  fileName: { fontSize: 12, color: '#64748B' },
  btnPrimary: { height: 38, padding: '0 18px', border: 'none', borderRadius: 6, background: '#0D9488', fontSize: 13, fontWeight: 700, color: 'white', cursor: 'pointer', fontFamily: "'DM Sans',sans-serif" },
  btnPrimaryDisabled: { background: '#CBD5E1', cursor: 'not-allowed' },
  btnSecondary: { height: 38, padding: '0 18px', border: '1px solid #CBD5E1', borderRadius: 6, background: 'white', fontSize: 13, fontWeight: 600, color: '#64748B', cursor: 'pointer', fontFamily: "'DM Sans',sans-serif" },
  btnDanger: { height: 38, padding: '0 18px', border: 'none', borderRadius: 6, background: '#DC2626', fontSize: 13, fontWeight: 700, color: 'white', cursor: 'pointer', fontFamily: "'DM Sans',sans-serif" },
  errorBox: { background: '#FFF5F5', border: '1px solid #FECACA', borderRadius: 6, padding: '8px 12px', fontSize: 12, color: '#DC2626', marginBottom: 12 },
  infoBox: { background: '#F0FDFA', border: '1px solid #99F6E4', borderRadius: 6, padding: '8px 12px', fontSize: 12, color: '#0F766E', marginBottom: 12 },
  // Analytics (kept for that tab)
  periodBar: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 20, flexWrap: 'wrap' },
  periodBtn: { padding: '5px 14px', borderRadius: 6, fontSize: 12, fontWeight: 500, cursor: 'pointer', border: '1px solid #E2E8F0', background: 'white', color: '#475569', fontFamily: "'DM Sans', sans-serif", transition: 'all 150ms' },
  periodBtnActive: { background: '#0B1F3A', color: 'white', border: '1px solid #0B1F3A' },
  analyticsGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16, marginBottom: 20 },
  kpiCard: { background: 'white', border: '1px solid #E2E8F0', borderRadius: 8, padding: '14px 16px', boxShadow: '0 1px 3px rgba(0,0,0,0.05)' },
  kpiVal: { fontFamily: "'Helvetica', Arial, sans-serif", fontSize: 28, fontWeight: 700, lineHeight: 1, marginBottom: 3 },
  kpiLabel: { fontSize: 11, color: '#64748B' },
  kpiDelta: { fontSize: 11, fontWeight: 600, marginTop: 4 },
  analyticsTable: { background: 'white', border: '1px solid #E2E8F0', borderRadius: 8, overflow: 'hidden', boxShadow: '0 1px 3px rgba(0,0,0,0.05)', marginBottom: 20 },
  atHead: { display: 'grid', gridTemplateColumns: '2fr 80px 80px 80px 80px 90px 90px', gap: 8, padding: '9px 16px', background: '#F8FAFC', borderBottom: '1px solid #E2E8F0' },
  atRow: { display: 'grid', gridTemplateColumns: '2fr 80px 80px 80px 80px 90px 90px', gap: 8, padding: '10px 16px', borderBottom: '1px solid #F1F5F9', alignItems: 'center', transition: 'background 150ms' },
  effBar: { height: 8, borderRadius: 4, background: '#F1F5F9', overflow: 'hidden' },
  effFill: { height: '100%', borderRadius: 4 },
};

const statusBadgeMap = {
  ok:       { bg: '#F0FDF4', color: '#16A34A', label: 'OK' },
  low:      { bg: '#FFFBEB', color: '#D97706', label: 'LOW' },
  critical: { bg: '#FFF5F5', color: '#DC2626', label: 'CRITICAL' },
};

function StockStatus({ balance, min, status }) {
  // balance can exceed min*2; cap visual at min*2
  const cap = Math.max(min * 2, 1);
  const pct = Math.min(100, (balance / cap) * 100);
  const s = statusBadgeMap[status] || statusBadgeMap.ok;
  const color = s.color;
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
        <span style={{ fontSize: 13, fontWeight: 600, color }}>{balance}</span>
        <span style={{ fontSize: 11, color: '#94A3B8' }}>/ min {min}</span>
      </div>
      <div style={ppeStyles.stockBar}>
        <div style={{ ...ppeStyles.stockFill, width: `${pct}%`, background: color }}/>
      </div>
    </div>
  );
}

function PPEBadge({ status }) {
  const s = statusBadgeMap[status] || statusBadgeMap.ok;
  return <span style={{ ...ppeStyles.badge, background: s.bg, color: s.color }}>{s.label}</span>;
}

// ── Reorder PPE Modal (sends quotation email via Resend) ────────────────────
function ReorderPPEModal({ item, user, onClose }) {
  const suggestedQty = Math.max((item.min_stock || 10) * 3 - (item.balance || 0), 10);
  const [form, setForm] = React.useState({
    recipient: '',
    qty: suggestedQty,
    remarks: '',
  });
  const [sending, setSending] = React.useState(false);
  const [sent, setSent]       = React.useState(false);
  const [error, setError]     = React.useState('');
  const [savedSuppliers, setSavedSuppliers] = React.useState([]);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  // Load saved PPE suppliers + fallback to account_settings.ppe_supplier_email
  React.useEffect(() => {
    (async () => {
      try {
        const sb = window.supabaseClient;
        const { data: vendors } = await sb.from('vendors').select('*').eq('type', 'ppe_supplier').order('is_default', { ascending: false });
        const list = vendors || [];
        setSavedSuppliers(list);
        const def = list.find(v => v.is_default);
        if (def) {
          set('recipient', def.email);
        } else {
          const { data: settings } = await sb.from('account_settings').select('ppe_supplier_email').eq('user_id', user.id).maybeSingle();
          if (settings?.ppe_supplier_email) set('recipient', settings.ppe_supplier_email);
        }
      } catch {}
    })();
  }, [user]);

  const pickSupplier = (id) => {
    if (!id) return;
    const s = savedSuppliers.find(v => v.id === id);
    if (s) set('recipient', s.email);
  };

  const handleSend = async () => {
    if (!form.recipient) { setError('Recipient email is required.'); return; }
    setSending(true); setError('');
    try {
      const sb = window.supabaseClient;
      const subject = `[AegisComply] PPE Reorder Request — ${item.name}${item.size ? ` [${item.size}]` : ''}`;
      const statusBadgeColor = item.status === 'critical' ? '#DC2626' : item.status === 'low' ? '#D97706' : '#16A34A';
      const html = `
        <div style="font-family: 'DM Sans', Arial, sans-serif; max-width: 600px; color: #0F172A;">
          <h2 style="color: #0B1F3A; margin: 0 0 8px;">PPE Reorder Request</h2>
          <p style="color: #64748B; margin: 0 0 18px;">From <strong>${user?.company || 'AegisComply user'}</strong></p>

          <table cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; background: #F8FAFC; border-radius: 6px;">
            <tr><td style="color: #94A3B8; font-size: 12px;">Item</td><td style="font-weight: 600;">${item.name}${item.size ? ` [${item.size}]` : ''}</td></tr>
            <tr><td style="color: #94A3B8; font-size: 12px;">Item Code (SKU)</td><td style="font-family: monospace;">${item.item_code || '—'}</td></tr>
            <tr><td style="color: #94A3B8; font-size: 12px;">Brand / Model</td><td>${item.brand_model || '—'}</td></tr>
            <tr><td style="color: #94A3B8; font-size: 12px;">Standard / Cert.</td><td>${item.standard_cert || '—'}</td></tr>
            <tr><td style="color: #94A3B8; font-size: 12px;">Category</td><td>${item.category || '—'}</td></tr>
            <tr><td style="color: #94A3B8; font-size: 12px;">Current Balance</td><td><strong style="color: ${statusBadgeColor};">${item.balance || 0} ${item.unit || 'pcs'}</strong></td></tr>
            <tr><td style="color: #94A3B8; font-size: 12px;">Min Stock Level</td><td>${item.min_stock || 0} ${item.unit || 'pcs'}</td></tr>
            <tr><td style="color: #94A3B8; font-size: 12px;">Status</td><td><strong style="color: ${statusBadgeColor};">${(item.status || '').toUpperCase()}</strong></td></tr>
          </table>

          <h3 style="color: #0B1F3A; margin: 18px 0 8px;">Order Request</h3>
          <table cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%;">
            <tr><td style="color: #94A3B8; font-size: 12px; width: 140px;">Quantity Required</td><td><strong style="font-size: 16px; color: #0D9488;">${form.qty} ${item.unit || 'pcs'}</strong></td></tr>
            <tr><td style="color: #94A3B8; font-size: 12px;">Remarks</td><td>${form.remarks || '—'}</td></tr>
          </table>

          <p style="margin: 18px 0 8px; color: #475569;">Please send your quotation including unit price, lead time, and delivery terms to <strong>${user?.email || 'us'}</strong>.</p>

          <p style="color: #94A3B8; font-size: 11px; margin-top: 24px; border-top: 1px solid #E2E8F0; padding-top: 12px;">
            Sent automatically from AegisComply by ${user?.name || 'admin'} · ${user?.email || ''}<br/>
            ${new Date().toLocaleString('en-MY')}
          </p>
        </div>
      `;

      const { error: fnErr } = await sb.functions.invoke('send-email', {
        body: { to: form.recipient, subject, html, replyTo: user?.email },
      });
      if (fnErr) throw fnErr;

      // Log quotation in DB
      await sb.from('quotation_log').insert({
        user_id:      user.id,
        type:         'ppe',
        item_name:    `${item.name}${item.size ? ` [${item.size}]` : ''}`,
        sent_to:      form.recipient,
        cc_dev:       false,
        details:      { item_code: item.item_code, qty: form.qty, remarks: form.remarks, current_balance: item.balance, min_stock: item.min_stock },
        status:       'sent',
      });

      // Update inventory's last_ordered fields
      await sb.from('ppe_inventory').update({
        last_ordered:   new Date().toISOString(),
        last_order_qty: Number(form.qty) || 0,
      }).eq('id', item.id);

      setSent(true);
    } catch (err) {
      console.error('[Reorder] error:', err);
      setError(err.message || 'Failed to send reorder email.');
    } finally {
      setSending(false);
    }
  };

  return (
    <div style={ppeStyles.overlay} onClick={sending ? undefined : onClose}>
      <div style={{ ...ppeStyles.modal, maxWidth: 480 }} onClick={e => e.stopPropagation()}>
        <div style={ppeStyles.modalHeader}>
          <div>
            <div style={ppeStyles.modalTitle}>Reorder PPE</div>
            <div style={{ fontSize: 12, color: '#64748B', marginTop: 3 }}>Sends quotation request to your supplier</div>
          </div>
          <button style={ppeStyles.modalClose} onClick={onClose} disabled={sending}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
          </button>
        </div>
        <div style={ppeStyles.modalBody}>
          {sent ? (
            <div style={{ textAlign: 'center', padding: '20px 0' }}>
              <div style={{ width: 56, height: 56, borderRadius: '50%', background: '#F0FDF4', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 14px' }}>
                <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#16A34A" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
              </div>
              <div style={{ fontSize: 15, fontWeight: 700, color: '#0F172A', marginBottom: 6 }}>Quotation email sent ✓</div>
              <div style={{ fontSize: 12, color: '#64748B' }}>Sent to <strong>{form.recipient}</strong> · Replies go to {user?.email}</div>
            </div>
          ) : (
            <>
              {error && <div style={ppeStyles.errorBox}>{error}</div>}
              <div style={{ background: item.status === 'critical' ? '#FFF5F5' : '#FFFBEB', border: `1px solid ${item.status === 'critical' ? '#FECACA' : '#FDE68A'}`, borderRadius: 7, padding: '10px 12px', fontSize: 12, color: item.status === 'critical' ? '#991B1B' : '#92400E', marginBottom: 14, lineHeight: 1.6 }}>
                <strong>{item.name}{item.size ? ` [${item.size}]` : ''}</strong><br/>
                Current: <strong>{item.balance || 0}</strong> {item.unit || 'pcs'} · Min: <strong>{item.min_stock || 0}</strong> · <strong>{(item.status || '').toUpperCase()}</strong>
              </div>

              {savedSuppliers.length > 0 && (
                <div style={ppeStyles.field}>
                  <label style={ppeStyles.label}>Saved Supplier (optional)</label>
                  <select style={ppeStyles.selectInput} value={savedSuppliers.find(s => s.email === form.recipient)?.id || ''} onChange={e => pickSupplier(e.target.value)}>
                    <option value="">— Pick from saved suppliers —</option>
                    {savedSuppliers.map(s => (
                      <option key={s.id} value={s.id}>
                        {s.name}{s.is_default ? ' (default)' : ''}{s.specialty ? ` · ${s.specialty}` : ''}
                      </option>
                    ))}
                  </select>
                </div>
              )}
              <div style={ppeStyles.field}>
                <label style={ppeStyles.label}>Send to (supplier email)<span style={ppeStyles.required}>*</span></label>
                <input style={ppeStyles.input} type="email" placeholder="supplier@company.com" value={form.recipient} onChange={e => set('recipient', e.target.value)}/>
                {savedSuppliers.length === 0 && <div style={{ fontSize: 11, color: '#94A3B8', marginTop: 4 }}>💡 Save suppliers in Settings → Labs & Suppliers for quick reuse.</div>}
              </div>

              <div style={ppeStyles.field}>
                <label style={ppeStyles.label}>Quantity to Order<span style={ppeStyles.required}>*</span></label>
                <input type="number" min="1" style={ppeStyles.input} value={form.qty} onChange={e => set('qty', parseInt(e.target.value) || 0)}/>
                <div style={{ fontSize: 11, color: '#94A3B8', marginTop: 4 }}>Suggested: {suggestedQty} {item.unit || 'pcs'} (3× minimum minus current balance)</div>
              </div>

              <div style={ppeStyles.field}>
                <label style={ppeStyles.label}>Remarks</label>
                <textarea style={ppeStyles.textarea} placeholder="Brand preference, urgency, delivery requirements…" value={form.remarks} onChange={e => set('remarks', e.target.value)}/>
              </div>

              <div style={{ fontSize: 11, color: '#94A3B8', lineHeight: 1.6 }}>
                💡 While in Resend test mode, only delivers to <strong>{user?.email}</strong>. After domain verification, sends to any address.
              </div>
            </>
          )}
        </div>
        <div style={ppeStyles.modalFooter}>
          <button style={ppeStyles.btnSecondary} onClick={onClose} disabled={sending}>{sent ? 'Close' : 'Cancel'}</button>
          {!sent && (
            <button
              style={{ ...ppeStyles.btnPrimary, ...((!form.recipient || !form.qty || sending) ? ppeStyles.btnPrimaryDisabled : {}) }}
              onClick={handleSend}
              disabled={!form.recipient || !form.qty || sending}
            >
              {sending ? 'Sending…' : 'Send Quotation Request'}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Delete Confirm Modal ────────────────────────────────────────────────────
function DeletePPEModal({ ppe, onConfirm, onCancel, busy }) {
  return (
    <div style={ppeStyles.overlay} onClick={!busy ? onCancel : undefined}>
      <div style={{ ...ppeStyles.modal, maxWidth: 440 }} onClick={e => e.stopPropagation()}>
        <div style={ppeStyles.modalHeader}>
          <div style={ppeStyles.modalTitle}>Delete PPE Item?</div>
        </div>
        <div style={ppeStyles.modalBody}>
          <div style={{ fontSize: 13, color: '#475569', lineHeight: 1.6 }}>
            Are you sure you want to delete <strong>{ppe.name}</strong> (<span style={ppeStyles.ppeMono}>{ppe.item_code || '—'}</span>)?
            <br/><br/>
            This action cannot be undone. Existing issuance log entries will keep the item name but lose the link.
          </div>
        </div>
        <div style={ppeStyles.modalFooter}>
          <button style={ppeStyles.btnSecondary} onClick={onCancel} disabled={busy}>Cancel</button>
          <button style={ppeStyles.btnDanger} onClick={onConfirm} disabled={busy}>
            {busy ? 'Deleting…' : 'Delete'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ── PPE Add/Edit Modal ──────────────────────────────────────────────────────
function PPEFormModal({ initial, onSave, onClose, user }) {
  const isEdit = !!initial?.id;
  const empty = {
    category: 'GLOVES', name: '', brand_model: '', item_code: '', size: '',
    standard_cert: '', min_stock: 10, stock: 0, issued: 0, unit: 'pcs',
    issue_date: '', expiry_date: '', condition: 'Good', remark: '',
  };
  const [form, setForm] = React.useState(initial ? { ...empty, ...initial } : empty);
  const [error, setError] = React.useState('');
  const [saving, setSaving] = React.useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const valid = form.name.trim() && form.category && form.min_stock >= 0 && form.stock >= 0;
  const balance = (Number(form.stock) || 0) - (Number(form.issued) || 0);

  const handleSubmit = async () => {
    setError('');
    if (!valid) { setError('Name, Category, and stock values are required.'); return; }
    setSaving(true);
    try {
      const sb = window.supabaseClient;
      const payload = {
        ...form,
        user_id: user.id,
        min_stock: Number(form.min_stock) || 0,
        stock:     Number(form.stock) || 0,
        issued:    Number(form.issued) || 0,
        issue_date:  form.issue_date  || null,
        expiry_date: form.expiry_date || null,
        status:    computePPEStatus(balance, Number(form.min_stock) || 0),
      };
      // Strip empty strings to null
      Object.keys(payload).forEach(k => { if (payload[k] === '') payload[k] = null; });
      // Don't try to set 'balance' (generated column)
      delete payload.balance;

      if (isEdit) {
        delete payload.id; delete payload.created_at; delete payload.updated_at;
        const { error: upErr } = await sb.from('ppe_inventory').update(payload).eq('id', initial.id);
        if (upErr) throw upErr;
      } else {
        const { error: insErr } = await sb.from('ppe_inventory').insert(payload);
        if (insErr) throw insErr;
      }
      setSaving(false);
      onSave();
    } catch (err) {
      console.error('[PPE] Save error:', err);
      setError(err.message || 'Save failed.');
      setSaving(false);
    }
  };

  return (
    <div style={ppeStyles.overlay} onClick={onClose}>
      <div style={ppeStyles.modal} onClick={e => e.stopPropagation()}>
        <div style={ppeStyles.modalHeader}>
          <div style={ppeStyles.modalTitle}>{isEdit ? 'Edit PPE Item' : 'Add PPE Item'}</div>
          <button style={ppeStyles.modalClose} onClick={onClose}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
          </button>
        </div>
        <div style={ppeStyles.modalBody}>
          {error && <div style={ppeStyles.errorBox}>{error}</div>}

          <div style={ppeStyles.fieldRow}>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Category<span style={ppeStyles.required}>*</span></label>
              <select style={ppeStyles.selectInput} value={form.category} onChange={e => set('category', e.target.value)}>
                {PPE_CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}
              </select>
            </div>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Item Code (SKU)</label>
              <input style={{ ...ppeStyles.input, fontFamily: "'JetBrains Mono', monospace", fontSize: 12 }} placeholder="GLV-NIT-S" value={form.item_code || ''} onChange={e => set('item_code', e.target.value)}/>
            </div>
          </div>

          <div style={ppeStyles.field}>
            <label style={ppeStyles.label}>Product Name<span style={ppeStyles.required}>*</span></label>
            <input style={ppeStyles.input} placeholder="e.g. Nitrile Disposable Gloves (Powder-Free)" value={form.name} onChange={e => set('name', e.target.value)}/>
          </div>

          <div style={ppeStyles.fieldRow}>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Brand / Model</label>
              <input style={ppeStyles.input} placeholder="e.g. Ansell TouchNTuff" value={form.brand_model || ''} onChange={e => set('brand_model', e.target.value)}/>
            </div>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Size</label>
              <input style={ppeStyles.input} placeholder="S / M / L / XL / UK 8 / Universal" value={form.size || ''} onChange={e => set('size', e.target.value)}/>
            </div>
          </div>

          <div style={ppeStyles.field}>
            <label style={ppeStyles.label}>Standard / Certification</label>
            <input style={ppeStyles.input} placeholder="e.g. EN 374, EN ISO 20345" value={form.standard_cert || ''} onChange={e => set('standard_cert', e.target.value)}/>
          </div>

          <div style={ppeStyles.fieldRow3}>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Min Stock</label>
              <input type="number" min="0" style={ppeStyles.input} value={form.min_stock} onChange={e => set('min_stock', e.target.value)}/>
            </div>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Total Stock</label>
              <input type="number" min="0" style={ppeStyles.input} value={form.stock} onChange={e => set('stock', e.target.value)}/>
            </div>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Already Issued</label>
              <input type="number" min="0" style={ppeStyles.input} value={form.issued} onChange={e => set('issued', e.target.value)}/>
            </div>
          </div>

          <div style={{ ...ppeStyles.infoBox, marginBottom: 14 }}>
            Balance: <strong>{balance}</strong> {form.unit} · Status will be: <strong>{computePPEStatus(balance, Number(form.min_stock) || 0).toUpperCase()}</strong>
          </div>

          <div style={ppeStyles.fieldRow3}>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Unit</label>
              <select style={ppeStyles.selectInput} value={form.unit} onChange={e => set('unit', e.target.value)}>
                {PPE_UNITS.map(u => <option key={u} value={u}>{u}</option>)}
              </select>
            </div>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Condition</label>
              <select style={ppeStyles.selectInput} value={form.condition || 'Good'} onChange={e => set('condition', e.target.value)}>
                {PPE_CONDITIONS.map(c => <option key={c} value={c}>{c}</option>)}
              </select>
            </div>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Stock Received</label>
              <input type="date" style={ppeStyles.input} value={form.issue_date || ''} onChange={e => set('issue_date', e.target.value)}/>
            </div>
          </div>

          <div style={ppeStyles.fieldRow}>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Expiry / Replace Date</label>
              <input type="date" style={ppeStyles.input} value={form.expiry_date || ''} onChange={e => set('expiry_date', e.target.value)}/>
            </div>
            <div style={ppeStyles.field}>
              <label style={ppeStyles.label}>Last Order Qty</label>
              <input type="number" min="0" style={ppeStyles.input} value={form.last_order_qty || 0} onChange={e => set('last_order_qty', e.target.value)}/>
            </div>
          </div>

          <div style={ppeStyles.field}>
            <label style={ppeStyles.label}>Remark</label>
            <textarea style={ppeStyles.textarea} placeholder="Usage notes, allocation details…" value={form.remark || ''} onChange={e => set('remark', e.target.value)}/>
          </div>
        </div>
        <div style={ppeStyles.modalFooter}>
          <button style={ppeStyles.btnSecondary} onClick={onClose} disabled={saving}>Cancel</button>
          <button
            style={{ ...ppeStyles.btnPrimary, ...((!valid || saving) ? ppeStyles.btnPrimaryDisabled : {}) }}
            onClick={handleSubmit}
            disabled={!valid || saving}
          >
            {saving ? 'Saving…' : (isEdit ? 'Save Changes' : 'Add PPE Item')}
          </button>
        </div>
      </div>
    </div>
  );
}

// ── Issue PPE Modal (real Supabase-backed) ──────────────────────────────────
function IssuePPEModal({ inventory, onClose, onIssued, user }) {
  const [form, setForm] = React.useState({ ppe_item_id: '', emp_id: '', emp_name: '', department: '', qty: 1, remarks: '', contact: '' });
  const [error, setError] = React.useState('');
  const [saving, setSaving] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const selected = inventory.find(p => p.id === form.ppe_item_id);
  const balance = selected ? selected.balance : 0;
  const qty = Number(form.qty) || 0;
  const valid = form.ppe_item_id && form.emp_id && form.emp_name && form.department && qty > 0 && qty <= balance;

  const handleSubmit = async () => {
    setError('');
    if (!valid) {
      if (qty > balance) setError(`Only ${balance} ${selected?.unit || 'units'} available.`);
      else               setError('Please fill in all required fields.');
      return;
    }
    setSaving(true);
    try {
      const sb = window.supabaseClient;

      // 1. Insert issuance row
      const { error: insErr } = await sb.from('ppe_issuance').insert({
        user_id:        user.id,
        issued_at:      new Date().toISOString(),
        item_code:      selected.item_code || null,
        ppe_item_id:    selected.id,
        ppe_item_name:  selected.name,
        size:           selected.size || null,
        qty:            qty,
        emp_name:       form.emp_name.trim(),
        emp_id:         form.emp_id.trim(),
        department:     form.department,
        contact:        form.contact || null,
        returned:       false,
        issued_by:      user.name || user.email,
        remarks:        form.remarks || null,
      });
      if (insErr) throw insErr;

      // 2. Update inventory — increment 'issued', recompute status
      const newIssued  = (selected.issued || 0) + qty;
      const newBalance = (selected.stock || 0) - newIssued;
      const newStatus  = computePPEStatus(newBalance, selected.min_stock || 0);
      const { error: upErr } = await sb.from('ppe_inventory').update({
        issued: newIssued, status: newStatus,
      }).eq('id', selected.id);
      if (upErr) console.warn('[PPE Issue] inventory update failed:', upErr); // issuance still recorded

      setDone(true);
      setSaving(false);
      // brief delay so user sees success, then close + refresh
      setTimeout(() => { onIssued(); }, 1200);
    } catch (err) {
      console.error('[PPE Issue] error:', err);
      setError(err.message || 'Issuance failed.');
      setSaving(false);
    }
  };

  return (
    <div style={ppeStyles.overlay} onClick={!saving ? onClose : undefined}>
      <div style={ppeStyles.modal} onClick={e => e.stopPropagation()}>
        <div style={ppeStyles.modalHeader}>
          <div style={ppeStyles.modalTitle}>Issue PPE to Employee</div>
          <button style={ppeStyles.modalClose} onClick={onClose} disabled={saving}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
          </button>
        </div>
        <div style={ppeStyles.modalBody}>
          {done ? (
            <div style={{ textAlign: 'center', padding: '20px 0' }}>
              <div style={{ width: 56, height: 56, borderRadius: '50%', background: '#F0FDF4', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 14px' }}>
                <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#16A34A" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
              </div>
              <div style={{ fontSize: 15, fontWeight: 700, color: '#0F172A', marginBottom: 6 }}>PPE Issued Successfully</div>
              <div style={{ fontSize: 12, color: '#64748B' }}>Issuance recorded · Inventory updated</div>
            </div>
          ) : (
            <>
              {error && <div style={ppeStyles.errorBox}>{error}</div>}

              <div style={ppeStyles.field}>
                <label style={ppeStyles.label}>PPE Item<span style={ppeStyles.required}>*</span></label>
                <select style={ppeStyles.selectInput} value={form.ppe_item_id} onChange={e => set('ppe_item_id', e.target.value)}>
                  <option value="">— Select PPE item —</option>
                  {inventory.map(p => (
                    <option key={p.id} value={p.id} disabled={p.balance <= 0}>
                      {p.name}{p.size ? ` [${p.size}]` : ''} ({p.balance} {p.unit || 'pcs'} available)
                    </option>
                  ))}
                </select>
              </div>

              <div style={ppeStyles.fieldRow}>
                <div style={ppeStyles.field}>
                  <label style={ppeStyles.label}>Employee ID<span style={ppeStyles.required}>*</span></label>
                  <input style={{ ...ppeStyles.input, fontFamily: "'JetBrains Mono', monospace", fontSize: 12 }} placeholder="EMP-0042" value={form.emp_id} onChange={e => set('emp_id', e.target.value)}/>
                </div>
                <div style={ppeStyles.field}>
                  <label style={ppeStyles.label}>Department<span style={ppeStyles.required}>*</span></label>
                  <select style={ppeStyles.selectInput} value={form.department} onChange={e => set('department', e.target.value)}>
                    <option value="">— Select —</option>
                    {DEPARTMENTS.map(d => <option key={d} value={d}>{d}</option>)}
                  </select>
                </div>
              </div>

              <div style={ppeStyles.field}>
                <label style={ppeStyles.label}>Employee Name<span style={ppeStyles.required}>*</span></label>
                <input style={ppeStyles.input} placeholder="Full name as per company ID" value={form.emp_name} onChange={e => set('emp_name', e.target.value)}/>
              </div>

              <div style={ppeStyles.fieldRow}>
                <div style={ppeStyles.field}>
                  <label style={ppeStyles.label}>Quantity<span style={ppeStyles.required}>*</span></label>
                  <input type="number" min="1" max={balance || 99999} style={ppeStyles.input} value={form.qty} onChange={e => set('qty', e.target.value)}/>
                  {selected && <div style={{ fontSize: 11, color: balance <= 0 ? '#DC2626' : '#94A3B8', marginTop: 4 }}>{balance} {selected.unit || 'pcs'} available</div>}
                </div>
                <div style={ppeStyles.field}>
                  <label style={ppeStyles.label}>Contact (optional)</label>
                  <input style={ppeStyles.input} placeholder="Phone or WhatsApp" value={form.contact} onChange={e => set('contact', e.target.value)}/>
                </div>
              </div>

              <div style={ppeStyles.field}>
                <label style={ppeStyles.label}>Remarks</label>
                <textarea style={ppeStyles.textarea} placeholder="Reason for issuance, replacement notes…" value={form.remarks} onChange={e => set('remarks', e.target.value)}/>
              </div>

              <div style={{ fontSize: 11, color: '#94A3B8' }}>
                Issued by: <strong style={{ color: '#334155' }}>{user.name || user.email}</strong> &nbsp;·&nbsp; {fmtDateTime_PPE(new Date())}
              </div>
            </>
          )}
        </div>
        {!done && (
          <div style={ppeStyles.modalFooter}>
            <button style={ppeStyles.btnSecondary} onClick={onClose} disabled={saving}>Cancel</button>
            <button
              style={{ ...ppeStyles.btnPrimary, ...((!valid || saving) ? ppeStyles.btnPrimaryDisabled : {}) }}
              onClick={handleSubmit}
              disabled={!valid || saving}
            >
              {saving ? 'Issuing…' : 'Confirm Issuance'}
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

// ── PPE Import Excel Modal ──────────────────────────────────────────────────
function PPEImportModal({ user, onClose, onImported }) {
  const [file, setFile] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [result, setResult] = React.useState(null);
  const [error, setError] = React.useState('');

  const handleFile = (e) => {
    const f = e.target.files?.[0];
    if (!f) return;
    if (!/\.(xlsx|xls)$/i.test(f.name)) { setError('Please choose an .xlsx or .xls file.'); return; }
    setFile(f); setError(''); setResult(null);
  };

  const runImport = async () => {
    if (!file) return;
    setBusy(true); setError(''); setResult(null);
    try {
      if (typeof window.XLSX === 'undefined') throw new Error('Excel library not loaded.');
      const buf = await file.arrayBuffer();
      const wb  = window.XLSX.read(buf, { type: 'array' });
      // Prefer the "PPE Stock Register" sheet; fallback to first sheet
      const sheetName = wb.SheetNames.find(n => /ppe.*stock|stock.*register/i.test(n)) || wb.SheetNames[0];
      const ws  = wb.Sheets[sheetName];
      const rows = window.XLSX.utils.sheet_to_json(ws, { header: 1, raw: false, defval: '' });

      // Find header row (look for "Product Name" or "Item Code")
      let headerIdx = -1;
      for (let i = 0; i < Math.min(10, rows.length); i++) {
        const cells = rows[i].map(c => String(c || '').toLowerCase());
        if (cells.some(c => c.includes('product name') || c.includes('item code'))) {
          headerIdx = i; break;
        }
      }
      if (headerIdx === -1) throw new Error('Could not find header row. Expected columns like "Product Name", "Item Code", "Min Stock".');

      const header = rows[headerIdx].map(c => String(c || '').trim().toLowerCase().replace(/\n/g, ' '));
      const col = (...keys) => {
        for (const k of keys) {
          const idx = header.findIndex(h => h.includes(k));
          if (idx !== -1) return idx;
        }
        return -1;
      };
      const c = {
        category: col('category'),
        name:     col('product name', 'product / sku', 'sku'),
        brand:    col('brand', 'model'),
        code:     col('item code', 'sku'),
        size:     col('size'),
        cert:     col('standard', 'cert.'),
        min:      col('min stock'),
        stock:    col('total stock'),
        issued:   col('issued'),
        unit:     col('unit'),
        recv:     col('issue date'),
        exp:      col('expiry', 'replace date'),
        cond:     col('condition'),
        remark:   col('remark', 'note'),
      };
      if (c.name === -1) throw new Error('Missing required column: "Product Name".');

      const records = [];
      for (let i = headerIdx + 1; i < rows.length; i++) {
        const r = rows[i];
        const name = r[c.name];
        if (!name) continue;
        // Skip section headers like "▶  GLOVES"
        if (String(r[c.category] || '').includes('▶') || String(name).includes('▶')) continue;

        const min   = Number(r[c.min] || 10);
        const stock = Number(r[c.stock] || 0);
        const issued= Number(r[c.issued] || 0);

        records.push({
          user_id:       user.id,
          category:      c.category !== -1 && r[c.category] ? String(r[c.category]).trim() : 'OTHER',
          name:          String(name).trim(),
          brand_model:   c.brand !== -1 && r[c.brand] ? String(r[c.brand]).trim() : null,
          item_code:     c.code  !== -1 && r[c.code]  ? String(r[c.code]).trim()  : null,
          size:          c.size  !== -1 && r[c.size]  ? String(r[c.size]).trim()  : null,
          standard_cert: c.cert  !== -1 && r[c.cert]  ? String(r[c.cert]).trim()  : null,
          min_stock:     min,
          stock:         stock,
          issued:        issued,
          unit:          c.unit  !== -1 && r[c.unit]  ? String(r[c.unit]).trim()  : 'pcs',
          issue_date:    parseExcelDate_PPE(r[c.recv]),
          expiry_date:   parseExcelDate_PPE(r[c.exp]),
          condition:     c.cond  !== -1 && r[c.cond]  ? String(r[c.cond]).trim()  : 'Good',
          remark:        c.remark!== -1 && r[c.remark]? String(r[c.remark]).trim(): null,
          status:        computePPEStatus(stock - issued, min),
        });
      }
      if (records.length === 0) throw new Error('No valid data rows found in the file.');

      // Skip duplicates by item_code (where present)
      const sb = window.supabaseClient;
      const codes = records.map(r => r.item_code).filter(Boolean);
      const { data: existing } = codes.length
        ? await sb.from('ppe_inventory').select('item_code').in('item_code', codes)
        : { data: [] };
      const existingCodes = new Set((existing || []).map(e => e.item_code));
      const toInsert = records.filter(r => !r.item_code || !existingCodes.has(r.item_code));
      const skipped  = records.length - toInsert.length;

      if (toInsert.length === 0) {
        setResult({ inserted: 0, skipped, total: records.length });
        setBusy(false);
        return;
      }

      let inserted = 0;
      for (let i = 0; i < toInsert.length; i += 100) {
        const batch = toInsert.slice(i, i + 100);
        const { error: insErr } = await sb.from('ppe_inventory').insert(batch);
        if (insErr) throw insErr;
        inserted += batch.length;
      }
      setResult({ inserted, skipped, total: records.length });
      onImported?.();
    } catch (err) {
      console.error('[PPE Import] error:', err);
      setError(err.message || 'Import failed.');
    } finally {
      setBusy(false);
    }
  };

  return (
    <div style={ppeStyles.overlay} onClick={busy ? undefined : onClose}>
      <div style={{ ...ppeStyles.modal, maxWidth: 520 }} onClick={e => e.stopPropagation()}>
        <div style={ppeStyles.modalHeader}>
          <div style={ppeStyles.modalTitle}>Import PPE Inventory from Excel</div>
          <button style={ppeStyles.modalClose} onClick={onClose} disabled={busy}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
          </button>
        </div>
        <div style={ppeStyles.modalBody}>
          {error && <div style={ppeStyles.errorBox}>{error}</div>}
          {result && (
            <div style={ppeStyles.infoBox}>
              <strong>Import complete.</strong><br/>
              ✓ Inserted: {result.inserted}<br/>
              ⊝ Skipped (duplicate item code): {result.skipped}<br/>
              Total rows read: {result.total}
            </div>
          )}
          {!result && (
            <>
              <div style={{ fontSize: 13, color: '#475569', marginBottom: 14, lineHeight: 1.6 }}>
                Upload an Excel file with PPE inventory data. Expected columns:
                <ul style={{ margin: '8px 0 0 18px', padding: 0, fontSize: 12, color: '#64748B', lineHeight: 1.8 }}>
                  <li><strong>Required:</strong> Product Name</li>
                  <li><strong>Optional:</strong> Category, Brand / Model, Item Code, Size, Standard / Cert., Min Stock, Total Stock, Issued, Unit, Issue Date, Expiry / Replace Date, Condition, Remark</li>
                </ul>
                <div style={{ marginTop: 10, fontSize: 12, color: '#94A3B8' }}>
                  Dates in DD/MM/YYYY format. Duplicate Item Codes are skipped. Status is auto-computed from balance vs min stock.
                </div>
              </div>
              <div style={ppeStyles.field}>
                <label style={ppeStyles.label}>Excel File (.xlsx)</label>
                <div style={ppeStyles.fileWrap}>
                  <label style={ppeStyles.fileBtn}>
                    {file ? 'Change file…' : 'Choose Excel…'}
                    <input type="file" accept=".xlsx,.xls" style={{ display: 'none' }} onChange={handleFile}/>
                  </label>
                  <span style={ppeStyles.fileName}>{file ? file.name : 'No file selected'}</span>
                </div>
              </div>
            </>
          )}
        </div>
        <div style={ppeStyles.modalFooter}>
          {result ? (
            <button style={ppeStyles.btnPrimary} onClick={onClose}>Done</button>
          ) : (
            <>
              <button style={ppeStyles.btnSecondary} onClick={onClose} disabled={busy}>Cancel</button>
              <button
                style={{ ...ppeStyles.btnPrimary, ...((!file || busy) ? ppeStyles.btnPrimaryDisabled : {}) }}
                onClick={runImport}
                disabled={!file || busy}
              >
                {busy ? 'Importing…' : 'Import Now'}
              </button>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Analytics Tab (real data from Supabase) ─────────────────────────────────
function periodStart(period) {
  const now = new Date();
  switch (period) {
    case 'This Month':    return new Date(now.getFullYear(), now.getMonth(), 1);
    case 'Last 3 Months': return new Date(now.getFullYear(), now.getMonth() - 3, now.getDate());
    case 'Last 6 Months': return new Date(now.getFullYear(), now.getMonth() - 6, now.getDate());
    case 'This Year':     return new Date(now.getFullYear(), 0, 1);
    case 'All Time':      return new Date('2000-01-01');
    default:              return new Date(now.getFullYear(), now.getMonth(), 1);
  }
}

function HealthBadge({ pct }) {
  const color = pct >= 100 ? '#16A34A' : pct >= 50 ? '#D97706' : '#DC2626';
  const bg    = pct >= 100 ? '#F0FDF4' : pct >= 50 ? '#FFFBEB' : '#FFF5F5';
  const label = pct >= 100 ? 'HEALTHY' : pct >= 50 ? 'WATCH' : 'LOW';
  return <span style={{ ...ppeStyles.badge, background: bg, color, fontSize: 11, padding: '3px 8px' }}>{label}</span>;
}

function PPEAnalytics({ user }) {
  const PERIODS = ['This Month', 'Last 3 Months', 'Last 6 Months', 'This Year', 'All Time'];
  const [period, setPeriod]     = React.useState('All Time');
  const [inventory, setInventory] = React.useState([]);
  const [issuances, setIssuances] = React.useState([]);
  const [loading, setLoading]     = React.useState(false);
  const [error, setError]         = React.useState('');
  const [hovered, setHovered]     = React.useState(null);

  const load = React.useCallback(async () => {
    setLoading(true); setError('');
    try {
      const sb = window.supabaseClient;
      const startDate = periodStart(period).toISOString();
      const [{ data: inv, error: invErr }, { data: iss, error: issErr }] = await Promise.all([
        sb.from('ppe_inventory').select('*'),
        sb.from('ppe_issuance').select('ppe_item_id, ppe_item_name, qty, issued_at').gte('issued_at', startDate),
      ]);
      if (invErr) throw invErr;
      if (issErr) throw issErr;
      setInventory(inv || []);
      setIssuances(iss || []);
    } catch (err) {
      console.error('[PPE Analytics] error:', err);
      setError(err.message || 'Failed to load analytics.');
    } finally {
      setLoading(false);
    }
  }, [period]);

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

  // Realtime — refresh on inventory or issuance changes
  React.useEffect(() => {
    if (!user) return;
    const sb = window.supabaseClient;
    if (!sb) return;
    const ch = sb.channel(`analytics-watcher-${user.id}`)
      .on('postgres_changes', { event: '*', schema: 'public', table: 'ppe_inventory', filter: `user_id=eq.${user.id}` }, () => load())
      .on('postgres_changes', { event: '*', schema: 'public', table: 'ppe_issuance', filter: `user_id=eq.${user.id}` }, () => load())
      .subscribe();
    return () => { sb.removeChannel(ch); };
  }, [user, load]);

  // ── Aggregate per item: timesIssued, unitsIssued ─────────────────────────
  const perItem = React.useMemo(() => {
    const map = new Map();
    for (const iss of issuances) {
      const key = iss.ppe_item_id || iss.ppe_item_name;
      const cur = map.get(key) || { id: iss.ppe_item_id, name: iss.ppe_item_name, times: 0, units: 0 };
      cur.times += 1;
      cur.units += iss.qty || 0;
      map.set(key, cur);
    }
    // Enrich with current inventory data
    const invByIdName = new Map();
    inventory.forEach(p => { invByIdName.set(p.id, p); });
    const rows = [];
    for (const [, agg] of map) {
      const inv = invByIdName.get(agg.id);
      const balance = inv?.balance ?? 0;
      const minStock = inv?.min_stock ?? 0;
      const coverage = minStock > 0 ? Math.round((balance / minStock) * 100) : 100;
      rows.push({
        ...agg,
        balance,
        minStock,
        coverage,
        status: inv?.status || 'ok',
        unit:   inv?.unit || 'pcs',
        size:   inv?.size || '',
      });
    }
    // Sort by units issued desc, then top 15
    rows.sort((a, b) => b.units - a.units);
    return rows.slice(0, 15);
  }, [inventory, issuances]);

  const totalUnits      = issuances.reduce((s, i) => s + (i.qty || 0), 0);
  const totalIssuances  = issuances.length;
  const lowStockCount   = inventory.filter(p => p.status === 'low' || p.status === 'critical').length;
  const criticalCount   = inventory.filter(p => p.status === 'critical').length;

  return (
    <div>
      <div style={ppeStyles.periodBar}>
        <span style={{ fontSize: 12, fontWeight: 600, color: '#64748B', marginRight: 4 }}>Period:</span>
        {PERIODS.map(p => (
          <button key={p} style={{ ...ppeStyles.periodBtn, ...(period === p ? ppeStyles.periodBtnActive : {}) }} onClick={() => setPeriod(p)}>{p}</button>
        ))}
        <span style={{ marginLeft: 'auto', fontSize: 11, color: '#94A3B8' }}>
          Since {periodStart(period).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })}
        </span>
      </div>

      {error && <div style={ppeStyles.errorBox}>{error}</div>}

      {/* KPI cards */}
      <div style={ppeStyles.analyticsGrid}>
        <div style={ppeStyles.kpiCard}>
          <div style={{ ...ppeStyles.kpiVal, color: '#0B1F3A' }}>{totalUnits}</div>
          <div style={ppeStyles.kpiLabel}>Total units issued</div>
          <div style={{ ...ppeStyles.kpiDelta, color: '#64748B' }}>{period}</div>
        </div>
        <div style={ppeStyles.kpiCard}>
          <div style={{ ...ppeStyles.kpiVal, color: '#0D9488' }}>{totalIssuances}</div>
          <div style={ppeStyles.kpiLabel}>Issuance transactions</div>
          <div style={{ ...ppeStyles.kpiDelta, color: '#64748B' }}>{period}</div>
        </div>
        <div style={ppeStyles.kpiCard}>
          <div style={{ ...ppeStyles.kpiVal, color: criticalCount > 0 ? '#DC2626' : lowStockCount > 0 ? '#D97706' : '#16A34A' }}>{lowStockCount}</div>
          <div style={ppeStyles.kpiLabel}>Items below min stock</div>
          <div style={{ ...ppeStyles.kpiDelta, color: criticalCount > 0 ? '#DC2626' : '#64748B' }}>
            {criticalCount > 0 ? `${criticalCount} critical` : 'Inventory snapshot · now'}
          </div>
        </div>
      </div>

      {/* Top items table */}
      <div style={ppeStyles.analyticsTable}>
        <div style={{ padding: '12px 16px', borderBottom: '1px solid #F1F5F9', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <span style={{ fontSize: 13, fontWeight: 600, color: '#0F172A', fontFamily: "'Helvetica', Arial, sans-serif" }}>
            Top Issued PPE — {period}
          </span>
          <span style={{ fontSize: 11, color: '#94A3B8' }}>{perItem.length} items shown</span>
        </div>
        <div style={ppeStyles.atHead}>
          <div style={ppeStyles.thCell}>PPE Item</div>
          <div style={ppeStyles.thCell}>Issuances</div>
          <div style={ppeStyles.thCell}>Units Used</div>
          <div style={ppeStyles.thCell}>Current</div>
          <div style={ppeStyles.thCell}>Min</div>
          <div style={ppeStyles.thCell}>Coverage</div>
          <div style={ppeStyles.thCell}>Stock Bar</div>
        </div>
        {loading && perItem.length === 0 && (
          <div style={{ padding: 30, textAlign: 'center', color: '#94A3B8', fontSize: 13 }}>Loading…</div>
        )}
        {!loading && perItem.length === 0 && (
          <div style={{ padding: 30, textAlign: 'center', color: '#94A3B8', fontSize: 13 }}>
            No PPE issuances in this period yet. Issue some PPE in the Inventory tab to see activity.
          </div>
        )}
        {perItem.map((r, i) => {
          const cap = Math.max((r.minStock || 0) * 2, 1);
          const pct = Math.min(100, ((r.balance || 0) / cap) * 100);
          const color = r.status === 'critical' ? '#DC2626' : r.status === 'low' ? '#D97706' : '#16A34A';
          return (
            <div key={i} style={{ ...ppeStyles.atRow, background: hovered === i ? '#F8FAFC' : 'white' }} onMouseEnter={() => setHovered(i)} onMouseLeave={() => setHovered(null)}>
              <div style={{ fontSize: 13, fontWeight: 500, color: '#0F172A' }}>
                {r.name}{r.size ? <span style={ppeStyles.sizeChip}>{r.size}</span> : null}
              </div>
              <div style={{ fontSize: 13, color: '#475569' }}>{r.times}</div>
              <div style={{ fontSize: 13, color: '#0B1F3A', fontWeight: 600 }}>{r.units} <span style={{ fontWeight: 400, color: '#94A3B8', fontSize: 11 }}>{r.unit}</span></div>
              <div style={{ fontSize: 13, fontWeight: 600, color }}>{r.balance}</div>
              <div style={{ fontSize: 13, color: '#94A3B8' }}>{r.minStock}</div>
              <HealthBadge pct={r.coverage} />
              <div>
                <div style={{ ...ppeStyles.effBar, marginBottom: 3 }}>
                  <div style={{ ...ppeStyles.effFill, width: `${pct}%`, background: color }}/>
                </div>
                <div style={{ fontSize: 10, color: '#94A3B8' }}>{r.balance} of min × 2 ({(r.minStock || 0) * 2})</div>
              </div>
            </div>
          );
        })}
      </div>

      {/* Health Guide */}
      <div style={{ background: 'white', border: '1px solid #E2E8F0', borderRadius: 8, padding: '14px 16px', boxShadow: '0 1px 3px rgba(0,0,0,0.05)' }}>
        <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: '#94A3B8', marginBottom: 10 }}>Stock Coverage Guide</div>
        <div style={{ display: 'flex', gap: 24, flexWrap: 'wrap' }}>
          {[
            { range: '≥ 100%',  label: 'Healthy',  desc: 'Current balance meets or exceeds min stock',     color: '#16A34A', bg: '#F0FDF4' },
            { range: '50–99%',  label: 'Watch',    desc: 'Below min stock — order soon',                   color: '#D97706', bg: '#FFFBEB' },
            { range: '< 50%',   label: 'Low',      desc: 'Critical — order immediately',                    color: '#DC2626', bg: '#FFF5F5' },
          ].map((g, i) => (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <span style={{ ...ppeStyles.badge, background: g.bg, color: g.color, fontSize: 11 }}>{g.range}</span>
              <div>
                <div style={{ fontSize: 12, fontWeight: 600, color: g.color }}>{g.label}</div>
                <div style={{ fontSize: 11, color: '#64748B' }}>{g.desc}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ── Inventory Tab (real Supabase CRUD) ──────────────────────────────────────
function InventoryTab({ user, isFrozen }) {
  const [items, setItems]               = React.useState([]);
  const [totalCount, setTotalCount]     = React.useState(0);
  const [loading, setLoading]           = React.useState(false);
  const [error, setError]               = React.useState('');
  const [search, setSearch]             = React.useState('');
  const [categoryFilter, setCategoryFilter] = React.useState('all');
  const [statusFilter, setStatusFilter] = React.useState('all');
  const [page, setPage]                 = React.useState(0);
  const [hovered, setHovered]           = React.useState(null);
  const [sort, setSort]                 = React.useState({ field: 'category', dir: 'asc' });

  const [editing, setEditing]   = React.useState(null);
  const [deleting, setDeleting] = React.useState(null);
  const [deleteBusy, setDeleteBusy] = React.useState(false);
  const [showIssue, setShowIssue]   = React.useState(false);
  const [showImport, setShowImport] = React.useState(false);
  const [exporting, setExporting]   = React.useState(false);
  const [reordering, setReordering] = React.useState(null);

  const [issuances, setIssuances]   = React.useState([]);

  // ── Fetch PPE inventory list (paginated, filtered) ────────────────────────
  const fetchInventory = React.useCallback(async () => {
    setLoading(true); setError('');
    try {
      const sb = window.supabaseClient;
      let q = sb.from('ppe_inventory').select('*', { count: 'exact' });
      if (categoryFilter !== 'all') q = q.eq('category', categoryFilter);
      if (statusFilter !== 'all')   q = q.eq('status', statusFilter);
      if (search.trim()) {
        const t = search.trim();
        q = q.or(`name.ilike.%${t}%,item_code.ilike.%${t}%,brand_model.ilike.%${t}%`);
      }
      const from = page * PPE_PAGE_SIZE;
      const to   = from + PPE_PAGE_SIZE - 1;
      q = q.order(sort.field, { ascending: sort.dir === 'asc', nullsFirst: false }).range(from, to);
      const { data, error: qErr, count } = await q;
      if (qErr) throw qErr;
      setItems(data || []);
      setTotalCount(count || 0);
    } catch (err) {
      console.error('[PPE Inventory] fetch error:', err);
      setError(err.message || 'Failed to load PPE inventory.');
    } finally {
      setLoading(false);
    }
  }, [search, categoryFilter, statusFilter, page, sort]);

  React.useEffect(() => { fetchInventory(); }, [fetchInventory]);
  React.useEffect(() => { setPage(0); }, [search, categoryFilter, statusFilter, sort]);

  // ── Fetch recent issuances ────────────────────────────────────────────────
  const fetchIssuances = React.useCallback(async () => {
    try {
      const sb = window.supabaseClient;
      const { data, error: qErr } = await sb.from('ppe_issuance')
        .select('*').order('issued_at', { ascending: false }).limit(ISSUANCE_LIMIT);
      if (qErr) throw qErr;
      setIssuances(data || []);
    } catch (err) {
      console.error('[PPE Issuance] fetch error:', err);
    }
  }, []);
  React.useEffect(() => { fetchIssuances(); }, [fetchIssuances]);

  // ── Realtime: live update when inventory or issuance changes ─────────────
  React.useEffect(() => {
    if (!user) return;
    const sb = window.supabaseClient;
    if (!sb) return;
    const ch = sb.channel(`ppe-watcher-${user.id}`)
      .on('postgres_changes',
        { event: '*', schema: 'public', table: 'ppe_inventory', filter: `user_id=eq.${user.id}` },
        () => { fetchInventory(); }
      )
      .on('postgres_changes',
        { event: '*', schema: 'public', table: 'ppe_issuance', filter: `user_id=eq.${user.id}` },
        () => { fetchIssuances(); }
      )
      .subscribe();
    return () => { sb.removeChannel(ch); };
  }, [user, fetchInventory, fetchIssuances]);

  // ── Delete ────────────────────────────────────────────────────────────────
  const handleDelete = async () => {
    if (!deleting) return;
    setDeleteBusy(true);
    try {
      const sb = window.supabaseClient;
      const { error: delErr } = await sb.from('ppe_inventory').delete().eq('id', deleting.id);
      if (delErr) throw delErr;
      setDeleting(null);
      fetchInventory();
    } catch (err) {
      console.error('[PPE Delete] error:', err);
      alert('Delete failed: ' + err.message);
    } finally {
      setDeleteBusy(false);
    }
  };

  // ── Export ────────────────────────────────────────────────────────────────
  const handleExport = async () => {
    if (typeof window.XLSX === 'undefined') { alert('Excel library not loaded. Refresh the page.'); return; }
    setExporting(true);
    try {
      const sb = window.supabaseClient;
      let q = sb.from('ppe_inventory').select('*').order('category').order('name');
      if (categoryFilter !== 'all') q = q.eq('category', categoryFilter);
      if (statusFilter !== 'all')   q = q.eq('status', statusFilter);
      if (search.trim()) {
        const t = search.trim();
        q = q.or(`name.ilike.%${t}%,item_code.ilike.%${t}%,brand_model.ilike.%${t}%`);
      }
      const { data, error: expErr } = await q;
      if (expErr) throw expErr;
      if (!data || data.length === 0) { alert('No PPE to export with current filters.'); return; }
      const rows = data.map((p, i) => ({
        'No.':                     i + 1,
        'Category':                p.category || '',
        'Product Name / SKU':      p.name,
        'Brand / Model':           p.brand_model || '',
        'Item Code':               p.item_code || '',
        'Size':                    p.size || '',
        'Standard / Cert.':        p.standard_cert || '',
        'Min Stock':               p.min_stock || 0,
        'Total Stock':             p.stock || 0,
        'Issued':                  p.issued || 0,
        'Balance':                 p.balance || 0,
        'Unit':                    p.unit || 'pcs',
        'Issue Date':              isoToDMY_PPE(p.issue_date),
        'Expiry / Replace Date':   isoToDMY_PPE(p.expiry_date),
        'Condition':               p.condition || '',
        'Remark':                  p.remark || '',
      }));
      const ws = window.XLSX.utils.json_to_sheet(rows);
      const wb = window.XLSX.utils.book_new();
      window.XLSX.utils.book_append_sheet(wb, ws, 'PPE Stock Register');
      const today = new Date().toISOString().slice(0, 10);
      window.XLSX.writeFile(wb, `AegisComply_PPE_${today}.xlsx`);
    } catch (err) {
      console.error('[PPE Export] error:', err);
      alert('Export failed: ' + err.message);
    } finally {
      setExporting(false);
    }
  };

  const totalPages = Math.max(1, Math.ceil(totalCount / PPE_PAGE_SIZE));
  const showingFrom = totalCount === 0 ? 0 : page * PPE_PAGE_SIZE + 1;
  const showingTo   = Math.min((page + 1) * PPE_PAGE_SIZE, totalCount);

  return (
    <div>
      {/* Toolbar */}
      <div style={ppeStyles.toolbar}>
        <div style={ppeStyles.searchWrap}>
          <svg style={ppeStyles.searchIcon} width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
          <input style={ppeStyles.searchInput} placeholder="Search name, code, brand…" value={search} onChange={e => setSearch(e.target.value)}/>
        </div>
        <select style={ppeStyles.select} value={categoryFilter} onChange={e => setCategoryFilter(e.target.value)}>
          <option value="all">All Categories</option>
          {PPE_CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}
        </select>
        <select style={ppeStyles.select} value={statusFilter} onChange={e => setStatusFilter(e.target.value)}>
          <option value="all">All Statuses</option>
          {PPE_STATUS_OPTIONS.map(s => <option key={s.value} value={s.value}>{s.label}</option>)}
        </select>
        <button
          style={{ ...ppeStyles.toolbarBtn, marginLeft: 'auto', ...(isFrozen ? ppeStyles.toolbarBtnDisabled : {}) }}
          onClick={() => !isFrozen && setShowImport(true)}
          disabled={isFrozen}
        >
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
          Import
        </button>
        <button
          style={{ ...ppeStyles.toolbarBtn, ...(exporting ? ppeStyles.toolbarBtnDisabled : {}) }}
          onClick={handleExport}
          disabled={exporting}
        >
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
          {exporting ? 'Exporting…' : 'Export'}
        </button>
        <button
          style={ppeStyles.toolbarBtn}
          onClick={async () => {
            try {
              const sb = window.supabaseClient;
              const [{ data: inv }, { data: iss }] = await Promise.all([
                sb.from('ppe_inventory').select('*').order('category').order('name'),
                sb.from('ppe_issuance').select('*').order('issued_at', { ascending: false }),
              ]);
              await window.AegisPDF.exportPPEAudit(user, inv || [], iss || []);
            } catch (err) {
              alert('PDF export failed: ' + err.message);
            }
          }}
          title="Export audit-ready PDF"
        >
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
          Audit PDF
        </button>
        <button
          style={{ ...ppeStyles.toolbarBtn, ...ppeStyles.toolbarBtnIssue, ...(isFrozen ? ppeStyles.toolbarBtnDisabled : {}) }}
          onClick={() => !isFrozen && setShowIssue(true)}
          disabled={isFrozen}
        >
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
          Issue PPE
        </button>
        <button
          style={{ ...ppeStyles.toolbarBtn, ...ppeStyles.toolbarBtnPrimary, ...(isFrozen ? ppeStyles.toolbarBtnDisabled : {}) }}
          onClick={() => !isFrozen && setEditing('new')}
          disabled={isFrozen}
        >
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
          Add PPE
        </button>
      </div>

      {error && <div style={ppeStyles.errorBox}>{error}</div>}

      {/* Inventory Table */}
      <div style={ppeStyles.card}>
        <div style={ppeStyles.tableHead}>
          <SortHeaderPPE label="Item Code"    field="item_code"   sort={sort} setSort={setSort} style={ppeStyles.thCell}/>
          <SortHeaderPPE label="Product Name" field="name"        sort={sort} setSort={setSort} style={ppeStyles.thCell}/>
          <SortHeaderPPE label="Brand"        field="brand_model" sort={sort} setSort={setSort} style={ppeStyles.thCell}/>
          <SortHeaderPPE label="Stock"        field="balance"     sort={sort} setSort={setSort} style={ppeStyles.thCell}/>
          <SortHeaderPPE label="Status"       field="status"      sort={sort} setSort={setSort} style={ppeStyles.thCell}/>
          <div style={ppeStyles.thCell}></div>
        </div>

        {loading && items.length === 0 ? (
          <div style={ppeStyles.emptyState}><div style={ppeStyles.emptyTitle}>Loading PPE…</div></div>
        ) : items.length === 0 ? (
          <div style={ppeStyles.emptyState}>
            <div style={ppeStyles.emptyIcon}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#94A3B8" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M20 7l-9-5-9 5v10l9 5 9-5z"/></svg>
            </div>
            <div style={ppeStyles.emptyTitle}>No PPE items</div>
            <div style={ppeStyles.emptySub}>
              {search || categoryFilter !== 'all' || statusFilter !== 'all'
                ? 'No results match your filters. Try clearing them.'
                : 'Click "Add PPE" or "Import" to get started.'}
            </div>
          </div>
        ) : (
          items.map((p, i) => (
            <div
              key={p.id}
              style={{ ...ppeStyles.tableRow, background: hovered === i ? '#F8FAFC' : 'white' }}
              onMouseEnter={() => setHovered(i)} onMouseLeave={() => setHovered(null)}
              onClick={() => !isFrozen && setEditing(p)}
            >
              <div style={ppeStyles.ppeMono}>{p.item_code || '—'}</div>
              <div>
                <div style={ppeStyles.ppeName}>
                  {p.name}
                  {p.size && <span style={ppeStyles.sizeChip}>{p.size}</span>}
                </div>
                <div style={ppeStyles.ppeCategory}>{p.category}{p.standard_cert ? ` · ${p.standard_cert}` : ''}</div>
              </div>
              <div style={{ fontSize: 12, color: '#475569' }}>{p.brand_model || '—'}</div>
              <StockStatus balance={p.balance || 0} min={p.min_stock || 0} status={p.status} />
              <PPEBadge status={p.status} />
              <div style={ppeStyles.rowActions} onClick={e => e.stopPropagation()}>
                {(p.status === 'low' || p.status === 'critical') && (
                  <button
                    style={{ ...ppeStyles.iconBtn, color: p.status === 'critical' ? '#DC2626' : '#D97706', borderColor: p.status === 'critical' ? '#FECACA' : '#FDE68A' }}
                    title={`Reorder — ${p.status}`}
                    onClick={() => !isFrozen && setReordering(p)}
                    disabled={isFrozen}
                  >
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
                  </button>
                )}
                <button style={ppeStyles.iconBtn} title="Edit" onClick={() => !isFrozen && setEditing(p)} disabled={isFrozen}>
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
                </button>
                <button style={{ ...ppeStyles.iconBtn, color: '#DC2626' }} title="Delete" onClick={() => !isFrozen && setDeleting(p)} disabled={isFrozen}>
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-2 14a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2L5 6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
                </button>
              </div>
            </div>
          ))
        )}

        <div style={ppeStyles.pagination}>
          <span style={ppeStyles.pageInfo}>
            {totalCount === 0 ? 'No PPE items' : `Showing ${showingFrom}–${showingTo} of ${totalCount}`}
          </span>
          <div style={ppeStyles.pageButtons}>
            <button style={{ ...ppeStyles.pageBtn, ...(page === 0 ? ppeStyles.pageBtnDisabled : {}) }} onClick={() => page > 0 && setPage(p => p - 1)} disabled={page === 0}>‹ Prev</button>
            <span style={{ ...ppeStyles.pageBtn, ...ppeStyles.pageBtnActive }}>{page + 1} / {totalPages}</span>
            <button style={{ ...ppeStyles.pageBtn, ...(page + 1 >= totalPages ? ppeStyles.pageBtnDisabled : {}) }} onClick={() => page + 1 < totalPages && setPage(p => p + 1)} disabled={page + 1 >= totalPages}>Next ›</button>
          </div>
        </div>
      </div>

      {/* Recent Issuances */}
      <div style={ppeStyles.card}>
        <div style={ppeStyles.cardHeader}>
          <span style={ppeStyles.cardTitle}>Recent Issuances</span>
          <span style={{ fontSize: 11, color: '#94A3B8' }}>{issuances.length} most recent</span>
        </div>
        {issuances.length === 0 ? (
          <div style={ppeStyles.emptyState}>
            <div style={ppeStyles.emptyTitle}>No issuances yet</div>
            <div style={ppeStyles.emptySub}>Click "Issue PPE" to record the first issuance.</div>
          </div>
        ) : issuances.map((log) => (
          <div key={log.id} style={ppeStyles.issuanceRow}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 2 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <span style={ppeStyles.issuanceName}>{log.emp_name}</span>
                <span style={ppeStyles.deptChip}>{log.department}</span>
              </div>
              <span style={{ fontSize: 11, color: '#94A3B8' }}>{fmtDateTime_PPE(log.issued_at)}</span>
            </div>
            <div style={ppeStyles.issuanceMeta}>
              <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, background: '#F1F5F9', padding: '1px 5px', borderRadius: 3, color: '#64748B' }}>{log.emp_id}</span>
              &nbsp;·&nbsp; Issued by {log.issued_by || '—'} &nbsp;·&nbsp; Qty: <strong>{log.qty}</strong>
            </div>
            <div style={ppeStyles.issuanceItems}>
              {log.ppe_item_name}{log.size ? ` [${log.size}]` : ''} × {log.qty}
            </div>
          </div>
        ))}
      </div>

      {/* Modals */}
      {editing && (
        <PPEFormModal
          initial={editing === 'new' ? null : editing}
          user={user}
          onClose={() => setEditing(null)}
          onSave={() => { setEditing(null); fetchInventory(); }}
        />
      )}
      {deleting && (
        <DeletePPEModal
          ppe={deleting}
          busy={deleteBusy}
          onCancel={() => !deleteBusy && setDeleting(null)}
          onConfirm={handleDelete}
        />
      )}
      {showIssue && (
        <IssuePPEModal
          inventory={items.filter(p => (p.balance || 0) > 0)}
          user={user}
          onClose={() => setShowIssue(false)}
          onIssued={() => { setShowIssue(false); fetchInventory(); fetchIssuances(); }}
        />
      )}
      {showImport && (
        <PPEImportModal
          user={user}
          onClose={() => setShowImport(false)}
          onImported={() => fetchInventory()}
        />
      )}
      {reordering && (
        <ReorderPPEModal
          item={reordering}
          user={user}
          onClose={() => setReordering(null)}
        />
      )}
    </div>
  );
}

// ── Main PPE Screen ─────────────────────────────────────────────────────────
function PPEScreen({ devEmail, user, isFrozen }) {
  const [tab, setTab] = React.useState('inventory');
  return (
    <div style={ppeStyles.page}>
      <div style={ppeStyles.tabs}>
        {[['inventory', 'Inventory & Issuance'], ['analytics', 'Analytics & Efficiency'], ['qr', 'QR Issuance']].map(([id, label]) => (
          <button key={id} style={{ ...ppeStyles.tab, ...(tab === id ? ppeStyles.tabActive : {}) }} onClick={() => setTab(id)}>{label}</button>
        ))}
      </div>
      {tab === 'inventory' && <InventoryTab user={user} isFrozen={isFrozen} />}
      {tab === 'analytics' && <PPEAnalytics user={user} />}
      {tab === 'qr' && <PPEQRTab user={user} isFrozen={isFrozen} />}
    </div>
  );
}

Object.assign(window, { PPEScreen });
