// CalibrationRFQTab.jsx — AegisComply FR-03C
// Client-side "blast a Request-for-Quote to up to 3 labs" tab. Lives
// inside CalibrationScreen. Reads/writes public.rfq_requests +
// public.rfq_quotes (migration 15).
//
// Flow shipped here:
//   1. Client fills the create form, picks up to 3 registered labs
//      filtered by category, hits Send.
//   2. One rfq_requests row + one rfq_quotes row per picked lab are
//      inserted. Each lab that has a contact_email gets a heads-up
//      email via the existing send-email edge function.
//   3. RFQ list shows client's RFQs (open / awarded / expired /
//      cancelled) with status pills + counts of pending / submitted /
//      declined quotes.
//   4. Detail modal shows lab-by-lab quote status. Award action is
//      deferred to FR-03E — this tab only ships blast + track.
//   5. On tab load, any open RFQ whose deadline has passed is flipped
//      to 'expired' (client-side sweep — cheap, idempotent).

const RFQ_STATUS_META = {
  open:      { label: 'Open',      bg: '#F0FDFA', color: '#0D9488', dot: '#14B8A6' },
  awarded:   { label: 'Awarded',   bg: '#EFF6FF', color: '#1D4ED8', dot: '#2563EB' },
  expired:   { label: 'Expired',   bg: '#FEF3C7', color: '#92400E', dot: '#D97706' },
  cancelled: { label: 'Cancelled', bg: '#F1F5F9', color: '#475569', dot: '#94A3B8' },
  closed:    { label: 'Closed',    bg: '#F1F5F9', color: '#475569', dot: '#94A3B8' },
};

const QUOTE_STATUS_META = {
  pending:      { label: 'Awaiting response', bg: '#FEF3C7', color: '#92400E' },
  submitted:    { label: 'Quote received',    bg: '#F0FDF4', color: '#166534' },
  declined:     { label: 'Declined',          bg: '#FEE2E2', color: '#B91C1C' },
  selected:     { label: 'Selected',          bg: '#EFF6FF', color: '#1D4ED8' },
  not_selected: { label: 'Not selected',      bg: '#F1F5F9', color: '#475569' },
};

const RFQ_CATEGORY_FALLBACK = [
  'Pressure', 'Temperature', 'Electrical', 'Dimensional', 'Mass',
  'Flow', 'Torque', 'Vibration', 'Humidity', 'Time & Frequency',
];

const rfqFmtDate = (d) => {
  if (!d) return '—';
  try { return new Date(d).toLocaleString('en-MY', { dateStyle: 'medium', timeStyle: 'short' }); }
  catch (_) { return String(d); }
};

const rfqFmtMoney = (v, ccy = 'MYR') => {
  if (v === null || v === undefined || v === '') return '—';
  try { return new Intl.NumberFormat('en-MY', { style: 'currency', currency: ccy, maximumFractionDigits: 2 }).format(Number(v)); }
  catch (_) { return `${ccy} ${Number(v).toFixed(2)}`; }
};

// ============================================================
// Main tab
// ============================================================
function CalibrationRFQTab({ user, isFrozen }) {
  const [rfqs, setRfqs]         = React.useState([]);
  const [quotesByRfq, setQuotesByRfq] = React.useState({});   // rfq_id -> quote rows
  const [labs, setLabs]         = React.useState([]);
  const [loading, setLoading]   = React.useState(true);
  const [unavailable, setUnavailable] = React.useState(false);
  const [error, setError]       = React.useState('');
  const [msg, setMsg]           = React.useState('');
  const [createOpen, setCreateOpen] = React.useState(false);
  const [detailFor, setDetailFor]   = React.useState(null);
  const [statusFilter, setStatusFilter] = React.useState('all');

  // Load all client RFQs + their quote rows in one pass
  const load = React.useCallback(async () => {
    if (!user) return;
    setLoading(true); setError('');
    try {
      const sb = window.supabaseClient;

      // 1. Fetch open + closed RFQs (RLS ensures only own)
      const { data: rows, error: rErr } = await sb
        .from('rfq_requests')
        .select('*')
        .order('created_at', { ascending: false })
        .limit(200);
      if (rErr) {
        if (/relation .* does not exist|rfq_requests/i.test(rErr.message || '')) {
          setUnavailable(true);
          return;
        }
        throw rErr;
      }
      setRfqs(rows || []);

      // 2. Auto-expire — any open RFQ with a past deadline gets flipped
      const now = new Date();
      const toExpire = (rows || []).filter(r =>
        r.status === 'open' && r.deadline && new Date(r.deadline) < now
      );
      if (toExpire.length > 0) {
        const ids = toExpire.map(r => r.id);
        const { error: eErr } = await sb.from('rfq_requests').update({ status: 'expired' }).in('id', ids);
        if (!eErr) {
          setRfqs(rs => rs.map(r => ids.includes(r.id) ? { ...r, status: 'expired' } : r));
        }
      }

      // 3. Fetch quote stubs for all these RFQs
      const rfqIds = (rows || []).map(r => r.id);
      if (rfqIds.length > 0) {
        const { data: qs, error: qErr } = await sb
          .from('rfq_quotes')
          .select('*, lab:lab_id(id, name, accreditation_number)')
          .in('rfq_id', rfqIds);
        if (qErr) throw qErr;
        const byRfq = {};
        (qs || []).forEach(q => { (byRfq[q.rfq_id] = byRfq[q.rfq_id] || []).push(q); });
        setQuotesByRfq(byRfq);
      } else {
        setQuotesByRfq({});
      }

      // 4. Active labs for the create modal picker
      const { data: labRows } = await sb
        .from('labs')
        .select('id, name, accreditation_number, calibration_categories, default_lead_time_days, contact_email')
        .eq('active', true)
        .order('name');
      setLabs(labRows || []);
    } catch (err) {
      console.error('[RFQ] load error:', err);
      setError(err.message || 'Failed to load RFQs.');
    } finally {
      setLoading(false);
    }
  }, [user]);

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

  // Realtime — refresh when quote status changes
  React.useEffect(() => {
    if (!user) return;
    const sb = window.supabaseClient;
    if (!sb || !sb.channel) return;
    let ch;
    try {
      ch = sb.channel('rfq-watch-' + user.id)
        .on('postgres_changes', { event: '*', schema: 'public', table: 'rfq_requests', filter: `client_id=eq.${user.id}` }, () => load())
        .on('postgres_changes', { event: '*', schema: 'public', table: 'rfq_quotes' }, () => load())
        .subscribe();
    } catch (_) {}
    return () => { try { if (ch) sb.removeChannel(ch); } catch (_) {} };
  }, [user, load]);

  const handleCancel = async (rfq) => {
    if (!confirm(`Cancel RFQ for "${rfq.instrument_name}"?\n\nLabs already awarded will not be notified from this action.`)) return;
    try {
      const sb = window.supabaseClient;
      const { error: uErr } = await sb.from('rfq_requests').update({ status: 'cancelled' }).eq('id', rfq.id);
      if (uErr) throw uErr;
      setMsg('RFQ cancelled.');
      await load();
    } catch (err) { setError(err.message || 'Cancel failed.'); }
  };

  const handleReopen = async (rfq) => {
    if (!confirm(`Reopen RFQ for "${rfq.instrument_name}"?\n\nExisting labs stay invited. To swap labs, cancel and create a fresh RFQ.`)) return;
    try {
      const sb = window.supabaseClient;
      // Extend deadline by 7 days from now (or clear it)
      const newDeadline = rfq.deadline
        ? new Date(Date.now() + 7 * 24 * 3600 * 1000).toISOString()
        : null;
      const { error: uErr } = await sb.from('rfq_requests').update({
        status: 'open',
        deadline: newDeadline,
      }).eq('id', rfq.id);
      if (uErr) throw uErr;
      setMsg('RFQ reopened. Pending quote rows are still active.');
      await load();
    } catch (err) { setError(err.message || 'Reopen failed.'); }
  };

  const filteredRfqs = React.useMemo(() => {
    if (statusFilter === 'all') return rfqs;
    return rfqs.filter(r => r.status === statusFilter);
  }, [rfqs, statusFilter]);

  if (unavailable) {
    return (
      <div style={{ padding: 32, background: 'white', border: '1px solid #E2E8F0', borderRadius: 10, textAlign: 'center' }}>
        <div style={{ fontSize: 15, fontWeight: 700, color: '#0F172A', marginBottom: 8 }}>RFQ feature is offline</div>
        <div style={{ fontSize: 13, color: '#64748B', maxWidth: 460, margin: '0 auto', lineHeight: 1.6 }}>
          Table <code style={{ background: '#F1F5F9', padding: '1px 6px', borderRadius: 4, fontSize: 12 }}>rfq_requests</code> not found.
          Run <strong>supabase/15_fr03a_dual_portal_foundation.sql</strong> in the Supabase SQL Editor, then reload.
        </div>
      </div>
    );
  }

  const counts = {
    all:       rfqs.length,
    open:      rfqs.filter(r => r.status === 'open').length,
    awarded:   rfqs.filter(r => r.status === 'awarded').length,
    expired:   rfqs.filter(r => r.status === 'expired').length,
    cancelled: rfqs.filter(r => r.status === 'cancelled' || r.status === 'closed').length,
  };

  return (
    <>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, marginBottom: 14, flexWrap: 'wrap' }}>
        <div>
          <div style={{ fontFamily: "'Helvetica',Arial,sans-serif", fontSize: 16, fontWeight: 700, color: '#0F172A' }}>Request for Quote (RFQ)</div>
          <div style={{ fontSize: 12, color: '#64748B', marginTop: 2 }}>Blast a calibration request to up to 3 registered labs, compare their quotes, then award the job.</div>
        </div>
        <button
          onClick={() => setCreateOpen(true)}
          disabled={isFrozen || labs.length === 0}
          style={{ height: 36, padding: '0 16px', border: 'none', borderRadius: 6, background: (isFrozen || labs.length === 0) ? '#CBD5E1' : '#0D9488', fontSize: 13, fontWeight: 600, color: 'white', cursor: (isFrozen || labs.length === 0) ? 'not-allowed' : 'pointer', display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: "'DM Sans', sans-serif" }}
          title={labs.length === 0 ? 'No active labs are registered yet. Ask the admin to register a lab first.' : ''}
        >
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
          Blast RFQ
        </button>
      </div>

      {msg   && <div style={{ background: '#F0FDF4', border: '1px solid #BBF7D0', borderRadius: 6, padding: '8px 12px', fontSize: 12, color: '#166534', marginBottom: 12 }}>{msg}</div>}
      {error && <div style={{ background: '#FFF5F5', border: '1px solid #FECACA', borderRadius: 6, padding: '10px 14px', fontSize: 12, color: '#B91C1C', marginBottom: 12 }}>{error}</div>}

      {labs.length === 0 && !loading && (
        <div style={{ background: '#FFFBEB', border: '1px solid #FDE68A', borderRadius: 8, padding: '12px 16px', fontSize: 12, color: '#92400E', marginBottom: 12 }}>
          No registered labs available yet. Once your admin registers at least one lab, you'll be able to blast RFQs to it.
        </div>
      )}

      {/* Filter pills */}
      <div style={{ display: 'flex', gap: 6, marginBottom: 14, flexWrap: 'wrap' }}>
        {[
          ['all',       'All'],
          ['open',      'Open'],
          ['awarded',   'Awarded'],
          ['expired',   'Expired'],
          ['cancelled', 'Cancelled'],
        ].map(([id, label]) => (
          <button key={id} onClick={() => setStatusFilter(id)}
            style={{ height: 28, padding: '0 12px', borderRadius: 14, fontSize: 11, fontWeight: 600, cursor: 'pointer', border: '1px solid ' + (statusFilter === id ? '#0B1F3A' : '#E2E8F0'), background: statusFilter === id ? '#0B1F3A' : 'white', color: statusFilter === id ? 'white' : '#64748B', fontFamily: "'DM Sans', sans-serif" }}>
            {label} <span style={{ opacity: 0.7, marginLeft: 4 }}>({counts[id] || 0})</span>
          </button>
        ))}
      </div>

      {/* List */}
      {loading ? (
        <div style={{ padding: 40, textAlign: 'center', color: '#94A3B8', fontSize: 13 }}>Loading RFQs…</div>
      ) : filteredRfqs.length === 0 ? (
        <div style={{ padding: 40, textAlign: 'center', color: '#94A3B8', fontSize: 13, background: 'white', border: '1px dashed #E2E8F0', borderRadius: 10 }}>
          {rfqs.length === 0 ? 'No RFQs yet. Click Blast RFQ to send your first request.' : 'No RFQs match this filter.'}
        </div>
      ) : (
        <div style={{ display: 'grid', gap: 10 }}>
          {filteredRfqs.map(r => (
            <RFQRow
              key={r.id}
              rfq={r}
              quotes={quotesByRfq[r.id] || []}
              onOpen={() => setDetailFor(r)}
              onCancel={() => handleCancel(r)}
              onReopen={() => handleReopen(r)}
            />
          ))}
        </div>
      )}

      {createOpen && (
        <RFQCreateModal
          user={user}
          labs={labs}
          onClose={() => setCreateOpen(false)}
          onCreated={(created) => { setCreateOpen(false); setMsg(`RFQ blasted to ${created} lab${created === 1 ? '' : 's'}.`); load(); }}
        />
      )}

      {detailFor && (
        <RFQDetailModal
          rfq={detailFor}
          quotes={quotesByRfq[detailFor.id] || []}
          user={user}
          onClose={() => setDetailFor(null)}
          onCancel={() => { handleCancel(detailFor); setDetailFor(null); }}
          onReopen={() => { handleReopen(detailFor); setDetailFor(null); }}
        />
      )}
    </>
  );
}

// ─── Single RFQ row card ─────────────────────────────────────
function RFQRow({ rfq, quotes, onOpen, onCancel, onReopen }) {
  const meta = RFQ_STATUS_META[rfq.status] || RFQ_STATUS_META.open;
  const pending    = quotes.filter(q => q.status === 'pending').length;
  const submitted  = quotes.filter(q => q.status === 'submitted').length;
  const declined   = quotes.filter(q => q.status === 'declined').length;
  const deadlineOverdue = rfq.deadline && new Date(rfq.deadline) < new Date();

  return (
    <div style={{ background: 'white', border: '1px solid #E2E8F0', borderRadius: 10, padding: 14, boxShadow: '0 1px 3px rgba(0,0,0,0.03)' }}>
      <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', justifyContent: 'space-between', flexWrap: 'wrap' }}>
        <div style={{ minWidth: 0, flex: 1, cursor: 'pointer' }} onClick={onOpen}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4, flexWrap: 'wrap' }}>
            <div style={{ fontSize: 14, fontWeight: 700, color: '#0F172A' }}>{rfq.instrument_name}</div>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: meta.bg, color: meta.color, fontSize: 10, fontWeight: 700, padding: '2px 8px', borderRadius: 10, textTransform: 'uppercase', letterSpacing: '0.04em' }}>
              <span style={{ width: 6, height: 6, borderRadius: '50%', background: meta.dot }}/>
              {meta.label}
            </span>
            {rfq.tag_number && <span style={{ fontSize: 10, color: '#94A3B8', fontFamily: "'JetBrains Mono',monospace" }}>#{rfq.tag_number}</span>}
          </div>
          <div style={{ fontSize: 11, color: '#64748B', marginBottom: 6 }}>
            {rfq.category} · Qty {rfq.quantity || 1}
            {rfq.preferred_schedule ? ` · target: ${rfq.preferred_schedule}` : ''}
            {rfq.deadline ? ` · deadline: ${rfqFmtDate(rfq.deadline)}${deadlineOverdue ? ' (past)' : ''}` : ' · no deadline'}
          </div>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            <RfqCountChip count={pending}   label="Awaiting"  color="#92400E" bg="#FEF3C7" />
            <RfqCountChip count={submitted} label="Quoted"    color="#166534" bg="#F0FDF4" />
            <RfqCountChip count={declined}  label="Declined"  color="#B91C1C" bg="#FEE2E2" />
            {quotes.length > 0 && <span style={{ fontSize: 10, color: '#94A3B8', alignSelf: 'center' }}>({quotes.length} lab{quotes.length === 1 ? '' : 's'} invited)</span>}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          <button onClick={onOpen} style={{ height: 28, padding: '0 12px', borderRadius: 5, border: '1px solid #CBD5E1', background: 'white', fontSize: 11, color: '#334155', cursor: 'pointer', fontWeight: 600, fontFamily: "'DM Sans',sans-serif" }}>View</button>
          {rfq.status === 'open' && (
            <button onClick={onCancel} style={{ height: 28, padding: '0 12px', borderRadius: 5, border: '1px solid #FECACA', background: '#FFF5F5', fontSize: 11, color: '#B91C1C', cursor: 'pointer', fontWeight: 600, fontFamily: "'DM Sans',sans-serif" }}>Cancel</button>
          )}
          {(rfq.status === 'expired' || rfq.status === 'cancelled') && (
            <button onClick={onReopen} style={{ height: 28, padding: '0 12px', borderRadius: 5, border: '1px solid #99F6E4', background: '#F0FDFA', fontSize: 11, color: '#0F766E', cursor: 'pointer', fontWeight: 600, fontFamily: "'DM Sans',sans-serif" }}>Reopen</button>
          )}
        </div>
      </div>
    </div>
  );
}

function RfqCountChip({ count, label, color, bg }) {
  if (!count) return null;
  return (
    <span style={{ background: bg, color, fontSize: 10, fontWeight: 700, padding: '2px 8px', borderRadius: 10 }}>
      {count} {label}
    </span>
  );
}

// ============================================================
// Create RFQ modal — the "blast" form
// ============================================================
function RFQCreateModal({ user, labs, onClose, onCreated }) {
  const [equipmentOptions, setEquipmentOptions] = React.useState([]);
  const [equipmentId, setEquipmentId] = React.useState('');
  const [instrumentName, setInstrumentName] = React.useState('');
  const [tagNumber, setTagNumber] = React.useState('');
  const [category, setCategory] = React.useState('');
  const [quantity, setQuantity] = React.useState(1);
  const [preferredSchedule, setPreferredSchedule] = React.useState('');
  const [remarks, setRemarks] = React.useState('');
  const [deadline, setDeadline] = React.useState('');            // datetime-local string
  const [pickedLabIds, setPickedLabIds] = React.useState([]);
  const [sending, setSending] = React.useState(false);
  const [error, setError] = React.useState('');

  // Load client profile (for company name) + equipment list once
  const [companyName, setCompanyName] = React.useState('');
  React.useEffect(() => {
    (async () => {
      const sb = window.supabaseClient;
      try {
        const { data: prof } = await sb.from('profiles').select('company_name, display_name').eq('id', user.id).maybeSingle();
        setCompanyName(prof?.company_name || prof?.display_name || user?.email || '');
      } catch (_) {}
      try {
        const { data: eq } = await sb.from('equipment').select('id, name, tag_number, category, brand_model').order('name').limit(500);
        setEquipmentOptions(eq || []);
      } catch (_) { setEquipmentOptions([]); }
    })();
  }, [user]);

  // When equipment is picked, autofill instrument / category / tag
  React.useEffect(() => {
    if (!equipmentId) return;
    const eq = equipmentOptions.find(e => e.id === equipmentId);
    if (!eq) return;
    if (!instrumentName) setInstrumentName(eq.name || '');
    if (!tagNumber && eq.tag_number) setTagNumber(eq.tag_number);
    if (!category && eq.category) setCategory(eq.category);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [equipmentId]);

  // Categories = union of all lab-registered categories, plus fallbacks
  const availableCategories = React.useMemo(() => {
    const set = new Set(RFQ_CATEGORY_FALLBACK);
    labs.forEach(l => (l.calibration_categories || []).forEach(c => set.add(c)));
    return Array.from(set).sort();
  }, [labs]);

  // Filter labs by picked category
  const eligibleLabs = React.useMemo(() => {
    if (!category) return [];
    return labs.filter(l => (l.calibration_categories || []).includes(category));
  }, [labs, category]);

  React.useEffect(() => {
    // Remove picked labs that no longer match the category
    setPickedLabIds(ids => ids.filter(id => eligibleLabs.some(l => l.id === id)));
  }, [eligibleLabs]);

  const toggleLab = (id) => {
    setPickedLabIds(ids => {
      if (ids.includes(id)) return ids.filter(x => x !== id);
      if (ids.length >= 3) return ids;
      return [...ids, id];
    });
  };

  const canSend = instrumentName.trim() && category && pickedLabIds.length > 0;

  const handleSend = async () => {
    if (!canSend) return;
    setSending(true); setError('');
    try {
      const sb = window.supabaseClient;

      const payload = {
        client_id:           user.id,
        equipment_id:        equipmentId || null,
        category,
        instrument_name:     instrumentName.trim(),
        tag_number:          tagNumber.trim() || null,
        client_company_name: companyName || null,
        quantity:            Number(quantity) || 1,
        preferred_schedule:  preferredSchedule.trim() || null,
        remarks:             remarks.trim() || null,
        deadline:            deadline ? new Date(deadline).toISOString() : null,
        status:              'open',
      };

      const { data: created, error: iErr } = await sb.from('rfq_requests').insert(payload).select().single();
      if (iErr) throw iErr;

      // Insert one pending quote row per picked lab
      const stubs = pickedLabIds.map(lab_id => ({ rfq_id: created.id, lab_id, status: 'pending' }));
      const { error: qErr } = await sb.from('rfq_quotes').insert(stubs);
      if (qErr) throw qErr;

      // Best-effort: email each lab that has a contact_email
      const pickedLabs = labs.filter(l => pickedLabIds.includes(l.id));
      const emailPromises = pickedLabs
        .filter(l => l.contact_email)
        .map(l => {
          const subject = `New RFQ — ${instrumentName} (${category})`;
          const deadlineTxt = deadline
            ? new Date(deadline).toLocaleString('en-MY', { dateStyle: 'medium', timeStyle: 'short' })
            : 'No deadline set';
          const html = `
            <div style="font-family: Arial, sans-serif; max-width: 560px; margin: 0 auto; padding: 24px; color: #0F172A;">
              <div style="font-size: 20px; font-weight: 700; margin-bottom: 4px;">New RFQ from ${companyName || 'a client'}</div>
              <div style="font-size: 13px; color: #64748B; margin-bottom: 16px;">Please log in to AegisComply to submit your quote or decline.</div>
              <table style="width:100%; font-size: 13px; border-collapse: collapse;">
                <tr><td style="padding:6px 0; color:#64748B;">Instrument</td><td style="padding:6px 0; font-weight:600;">${instrumentName}</td></tr>
                ${tagNumber ? `<tr><td style="padding:6px 0; color:#64748B;">Tag #</td><td style="padding:6px 0; font-weight:600;">${tagNumber}</td></tr>` : ''}
                <tr><td style="padding:6px 0; color:#64748B;">Category</td><td style="padding:6px 0; font-weight:600;">${category}</td></tr>
                <tr><td style="padding:6px 0; color:#64748B;">Quantity</td><td style="padding:6px 0; font-weight:600;">${payload.quantity}</td></tr>
                ${preferredSchedule ? `<tr><td style="padding:6px 0; color:#64748B;">Preferred schedule</td><td style="padding:6px 0; font-weight:600;">${preferredSchedule}</td></tr>` : ''}
                <tr><td style="padding:6px 0; color:#64748B;">Deadline</td><td style="padding:6px 0; font-weight:600;">${deadlineTxt}</td></tr>
                ${remarks ? `<tr><td style="padding:6px 0; color:#64748B; vertical-align:top;">Remarks</td><td style="padding:6px 0; font-weight:400;">${remarks.replace(/\n/g, '<br>')}</td></tr>` : ''}
              </table>
              <div style="margin-top: 20px; padding: 14px; background: #F0FDFA; border: 1px solid #99F6E4; border-radius: 8px; font-size: 12px; color: #0F766E;">
                Log in at <a href="${typeof window !== 'undefined' ? window.location.origin : 'https://aegiscomply.app'}" style="color:#0F766E; font-weight:600;">AegisComply</a> to respond. Your quote must be submitted before the deadline.
              </div>
              <div style="margin-top: 20px; font-size: 11px; color: #94A3B8;">RFQ ID: ${created.id}</div>
            </div>`;
          return window.aegisInvokeFunction('send-email', {
            to:      l.contact_email,
            subject,
            html,
            replyTo: user?.email,
          }).catch(err => console.warn('[RFQ] email to ' + l.contact_email + ' failed:', err));
        });
      // Fire and (mostly) forget — don't block success on email delivery
      Promise.all(emailPromises).catch(() => {});

      onCreated(pickedLabIds.length);
    } catch (err) {
      console.error('[RFQ] create error:', err);
      setError(err.message || 'Failed to blast RFQ.');
    } finally {
      setSending(false);
    }
  };

  // Minimum datetime-local value = now
  const nowLocal = React.useMemo(() => {
    const d = new Date(Date.now() + 5 * 60 * 1000);   // +5 min buffer
    const pad = n => String(n).padStart(2, '0');
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
  }, []);

  return (
    <div style={calStyles.overlay} onClick={sending ? undefined : onClose}>
      <div style={{ ...calStyles.modal, maxWidth: 640 }} onClick={e => e.stopPropagation()}>
        <div style={calStyles.modalHeader}>
          <div>
            <div style={calStyles.modalTitle}>Blast RFQ</div>
            <div style={calStyles.modalSub}>Send a calibration request to up to 3 registered labs at once</div>
          </div>
          <button style={calStyles.modalClose} onClick={onClose} disabled={sending}>✕</button>
        </div>
        <div style={{ padding: 20, overflowY: 'auto', flex: 1 }}>
          {error && <div style={{ background: '#FFF5F5', border: '1px solid #FECACA', borderRadius: 6, padding: '10px 12px', fontSize: 12, color: '#B91C1C', marginBottom: 12 }}>{error}</div>}

          {/* Section 1: Instrument */}
          <div style={{ fontSize: 11, fontWeight: 700, color: '#94A3B8', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 10 }}>1. Instrument</div>

          {equipmentOptions.length > 0 && (
            <div style={{ marginBottom: 12 }}>
              <label style={{ fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 4 }}>Pick from your equipment (optional)</label>
              <select value={equipmentId} onChange={e => setEquipmentId(e.target.value)}
                style={{ width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 12px', fontSize: 13, background: 'white', color: '#0F172A', outline: 'none' }}>
                <option value="">— Type instrument manually —</option>
                {equipmentOptions.map(e => <option key={e.id} value={e.id}>{e.name}{e.tag_number ? ` (#${e.tag_number})` : ''}{e.category ? ` — ${e.category}` : ''}</option>)}
              </select>
            </div>
          )}

          <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 10, marginBottom: 12 }}>
            <div>
              <label style={{ fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 4 }}>Instrument name *</label>
              <input value={instrumentName} onChange={e => setInstrumentName(e.target.value)} placeholder="e.g. Fluke 754 Documenting Process Calibrator"
                style={{ width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 12px', fontSize: 13, background: 'white', color: '#0F172A', outline: 'none' }} />
            </div>
            <div>
              <label style={{ fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 4 }}>Tag #</label>
              <input value={tagNumber} onChange={e => setTagNumber(e.target.value)} placeholder="e.g. FLK-001"
                style={{ width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 12px', fontSize: 13, background: 'white', color: '#0F172A', outline: 'none' }} />
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 10, marginBottom: 16 }}>
            <div>
              <label style={{ fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 4 }}>Category *</label>
              <select value={category} onChange={e => setCategory(e.target.value)}
                style={{ width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 12px', fontSize: 13, background: 'white', color: '#0F172A', outline: 'none' }}>
                <option value="">— Pick a category —</option>
                {availableCategories.map(c => <option key={c} value={c}>{c}</option>)}
              </select>
            </div>
            <div>
              <label style={{ fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 4 }}>Quantity</label>
              <input type="number" min="1" value={quantity} onChange={e => setQuantity(e.target.value)}
                style={{ width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 12px', fontSize: 13, background: 'white', color: '#0F172A', outline: 'none' }} />
            </div>
          </div>

          {/* Section 2: Schedule */}
          <div style={{ fontSize: 11, fontWeight: 700, color: '#94A3B8', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 10 }}>2. Timeframe</div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 12 }}>
            <div>
              <label style={{ fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 4 }}>Preferred schedule</label>
              <input value={preferredSchedule} onChange={e => setPreferredSchedule(e.target.value)} placeholder="e.g. Q3 2026 / mid-August"
                style={{ width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 12px', fontSize: 13, background: 'white', color: '#0F172A', outline: 'none' }} />
              <div style={{ fontSize: 10, color: '#94A3B8', marginTop: 3 }}>Flexible timeframe. Fixed date is negotiated after award.</div>
            </div>
            <div>
              <label style={{ fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 4 }}>Response deadline</label>
              <input type="datetime-local" min={nowLocal} value={deadline} onChange={e => setDeadline(e.target.value)}
                style={{ width: '100%', height: 36, border: '1px solid #CBD5E1', borderRadius: 6, padding: '0 12px', fontSize: 13, background: 'white', color: '#0F172A', outline: 'none' }} />
              <div style={{ fontSize: 10, color: '#94A3B8', marginTop: 3 }}>Optional. After this, labs can no longer submit.</div>
            </div>
          </div>

          <div style={{ marginBottom: 16 }}>
            <label style={{ fontSize: 12, fontWeight: 600, color: '#334155', display: 'block', marginBottom: 4 }}>Remarks</label>
            <textarea rows={2} value={remarks} onChange={e => setRemarks(e.target.value)} placeholder="Anything the lab needs to know — accreditation requirements, existing cal history, …"
              style={{ width: '100%', border: '1px solid #CBD5E1', borderRadius: 6, padding: 10, fontSize: 13, background: 'white', color: '#0F172A', outline: 'none', resize: 'vertical', fontFamily: "'DM Sans',sans-serif" }} />
          </div>

          {/* Section 3: Pick labs */}
          <div style={{ fontSize: 11, fontWeight: 700, color: '#94A3B8', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 10 }}>
            3. Pick labs ({pickedLabIds.length} / 3)
          </div>

          {!category ? (
            <div style={{ padding: 20, background: '#F8FAFC', border: '1px dashed #CBD5E1', borderRadius: 8, fontSize: 12, color: '#94A3B8', textAlign: 'center' }}>
              Pick a category above to see eligible labs.
            </div>
          ) : eligibleLabs.length === 0 ? (
            <div style={{ padding: 16, background: '#FFFBEB', border: '1px solid #FDE68A', borderRadius: 8, fontSize: 12, color: '#92400E' }}>
              No active labs registered for <strong>{category}</strong> yet. Ask your admin to register a lab that covers this category.
            </div>
          ) : (
            <div style={{ display: 'grid', gap: 6 }}>
              {eligibleLabs.map(l => {
                const on = pickedLabIds.includes(l.id);
                const atLimit = !on && pickedLabIds.length >= 3;
                return (
                  <button key={l.id} type="button" onClick={() => toggleLab(l.id)} disabled={atLimit}
                    style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', border: '1px solid ' + (on ? '#0D9488' : '#E2E8F0'), borderRadius: 8, background: on ? '#F0FDFA' : (atLimit ? '#F8FAFC' : 'white'), cursor: atLimit ? 'not-allowed' : 'pointer', textAlign: 'left', fontFamily: "'DM Sans',sans-serif", opacity: atLimit ? 0.5 : 1 }}>
                    <div style={{ width: 18, height: 18, borderRadius: 4, border: '2px solid ' + (on ? '#0D9488' : '#CBD5E1'), background: on ? '#0D9488' : 'white', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                      {on && <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="4" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>}
                    </div>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 13, fontWeight: 600, color: '#0F172A' }}>{l.name}</div>
                      <div style={{ fontSize: 11, color: '#64748B' }}>
                        {l.accreditation_number ? `${l.accreditation_number} · ` : ''}Lead time: {l.default_lead_time_days}d
                        {l.contact_email ? ` · ${l.contact_email}` : ''}
                      </div>
                    </div>
                  </button>
                );
              })}
            </div>
          )}
        </div>
        <div style={{ padding: '14px 20px', borderTop: '1px solid #E2E8F0', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <button onClick={onClose} disabled={sending}
            style={{ height: 34, padding: '0 14px', border: '1px solid #CBD5E1', borderRadius: 6, background: 'white', fontSize: 13, color: '#334155', cursor: 'pointer', fontFamily: "'DM Sans',sans-serif" }}>Cancel</button>
          <button onClick={handleSend} disabled={!canSend || sending}
            style={{ height: 34, padding: '0 18px', border: 'none', borderRadius: 6, background: (!canSend || sending) ? '#CBD5E1' : '#0D9488', fontSize: 13, fontWeight: 700, color: 'white', cursor: (!canSend || sending) ? 'not-allowed' : 'pointer', fontFamily: "'DM Sans',sans-serif" }}>
            {sending ? 'Blasting…' : `Send to ${pickedLabIds.length || 0} lab${pickedLabIds.length === 1 ? '' : 's'}`}
          </button>
        </div>
      </div>
    </div>
  );
}

// ============================================================
// Detail modal — lab-by-lab quote status. Award action is FR-03E.
// ============================================================
function RFQDetailModal({ rfq, quotes, user, onClose, onCancel, onReopen }) {
  const meta = RFQ_STATUS_META[rfq.status] || RFQ_STATUS_META.open;
  const deadlineOverdue = rfq.deadline && new Date(rfq.deadline) < new Date();

  return (
    <div style={calStyles.overlay} onClick={onClose}>
      <div style={{ ...calStyles.modal, maxWidth: 640 }} onClick={e => e.stopPropagation()}>
        <div style={calStyles.modalHeader}>
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div style={calStyles.modalTitle}>{rfq.instrument_name}</div>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: meta.bg, color: meta.color, fontSize: 10, fontWeight: 700, padding: '2px 8px', borderRadius: 10, textTransform: 'uppercase', letterSpacing: '0.04em' }}>
                <span style={{ width: 6, height: 6, borderRadius: '50%', background: meta.dot }}/>
                {meta.label}
              </span>
            </div>
            <div style={calStyles.modalSub}>RFQ blasted on {rfqFmtDate(rfq.created_at)}</div>
          </div>
          <button style={calStyles.modalClose} onClick={onClose}>✕</button>
        </div>
        <div style={{ padding: 20, overflowY: 'auto', flex: 1 }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 10, marginBottom: 16 }}>
            <InfoCell label="Category"   value={rfq.category} />
            <InfoCell label="Quantity"   value={rfq.quantity || 1} />
            <InfoCell label="Tag #"      value={rfq.tag_number || '—'} mono />
            <InfoCell label="Preferred"  value={rfq.preferred_schedule || '—'} />
            <InfoCell label="Deadline"   value={rfq.deadline ? rfqFmtDate(rfq.deadline) + (deadlineOverdue ? ' (past)' : '') : 'No deadline'} />
            <InfoCell label="RFQ ID"     value={rfq.id.slice(0, 8) + '…'} mono />
          </div>
          {rfq.remarks && (
            <div style={{ marginBottom: 16, padding: 12, background: '#F8FAFC', border: '1px solid #E2E8F0', borderRadius: 8 }}>
              <div style={{ fontSize: 10, fontWeight: 700, color: '#94A3B8', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 4 }}>Remarks</div>
              <div style={{ fontSize: 12, color: '#334155', whiteSpace: 'pre-wrap' }}>{rfq.remarks}</div>
            </div>
          )}

          <div style={{ fontSize: 11, fontWeight: 700, color: '#94A3B8', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 10 }}>
            Labs invited ({quotes.length})
          </div>

          {quotes.length === 0 ? (
            <div style={{ padding: 24, textAlign: 'center', color: '#94A3B8', fontSize: 12, border: '1px dashed #E2E8F0', borderRadius: 8 }}>
              No quotes on this RFQ yet.
            </div>
          ) : (
            <div style={{ display: 'grid', gap: 8 }}>
              {quotes.map(q => {
                const qm = QUOTE_STATUS_META[q.status] || QUOTE_STATUS_META.pending;
                return (
                  <div key={q.id} style={{ border: '1px solid #E2E8F0', borderRadius: 8, padding: 12, background: 'white' }}>
                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, marginBottom: 6, flexWrap: 'wrap' }}>
                      <div style={{ fontSize: 13, fontWeight: 700, color: '#0F172A' }}>{q.lab?.name || 'Lab'}</div>
                      <span style={{ background: qm.bg, color: qm.color, fontSize: 10, fontWeight: 700, padding: '2px 8px', borderRadius: 10, textTransform: 'uppercase', letterSpacing: '0.04em' }}>{qm.label}</span>
                    </div>
                    {q.lab?.accreditation_number && (
                      <div style={{ fontSize: 11, color: '#64748B', marginBottom: 6 }}>Accreditation: <strong>{q.lab.accreditation_number}</strong></div>
                    )}
                    {q.status === 'submitted' && (
                      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, marginTop: 4 }}>
                        <InfoCell label="Price"       value={rfqFmtMoney(q.price, q.currency)} />
                        <InfoCell label="Lead time"   value={q.turnaround_days ? `${q.turnaround_days} days` : '—'} />
                        <InfoCell label="Submitted"   value={q.submitted_at ? rfqFmtDate(q.submitted_at) : '—'} />
                      </div>
                    )}
                    {q.remarks && (
                      <div style={{ marginTop: 6, fontSize: 12, color: '#475569', whiteSpace: 'pre-wrap' }}>{q.remarks}</div>
                    )}
                    {q.decline_reason && (
                      <div style={{ marginTop: 6, fontSize: 12, color: '#B91C1C' }}>Decline reason: {q.decline_reason}</div>
                    )}
                  </div>
                );
              })}
            </div>
          )}

          {rfq.status === 'open' && quotes.some(q => q.status === 'submitted') && (
            <div style={{ marginTop: 16, padding: 12, background: '#EFF6FF', border: '1px solid #BFDBFE', borderRadius: 8, fontSize: 12, color: '#1E3A8A' }}>
              📌 Comparison view + award action will be enabled in FR-03E.
            </div>
          )}
        </div>
        <div style={{ padding: '14px 20px', borderTop: '1px solid #E2E8F0', display: 'flex', justifyContent: 'space-between', gap: 8, flexWrap: 'wrap' }}>
          <div>
            {rfq.status === 'open' && (
              <button onClick={onCancel} style={{ height: 34, padding: '0 14px', border: '1px solid #FECACA', borderRadius: 6, background: '#FFF5F5', fontSize: 12, color: '#B91C1C', cursor: 'pointer', fontWeight: 600, fontFamily: "'DM Sans',sans-serif" }}>Cancel RFQ</button>
            )}
            {(rfq.status === 'expired' || rfq.status === 'cancelled') && (
              <button onClick={onReopen} style={{ height: 34, padding: '0 14px', border: '1px solid #99F6E4', borderRadius: 6, background: '#F0FDFA', fontSize: 12, color: '#0F766E', cursor: 'pointer', fontWeight: 600, fontFamily: "'DM Sans',sans-serif" }}>Reopen RFQ</button>
            )}
          </div>
          <button onClick={onClose} style={{ height: 34, padding: '0 14px', border: '1px solid #CBD5E1', borderRadius: 6, background: 'white', fontSize: 13, color: '#334155', cursor: 'pointer', fontFamily: "'DM Sans',sans-serif" }}>Close</button>
        </div>
      </div>
    </div>
  );
}

function InfoCell({ label, value, mono }) {
  return (
    <div style={{ background: '#F8FAFC', border: '1px solid #E2E8F0', borderRadius: 6, padding: '8px 10px' }}>
      <div style={{ fontSize: 10, fontWeight: 700, color: '#94A3B8', letterSpacing: '0.06em', textTransform: 'uppercase' }}>{label}</div>
      <div style={{ fontSize: 12, fontWeight: 600, color: '#0F172A', marginTop: 2, fontFamily: mono ? "'JetBrains Mono',monospace" : "'DM Sans',sans-serif" }}>{value}</div>
    </div>
  );
}

Object.assign(window, { CalibrationRFQTab });
