/* ============================================================
   ELECTROMED — Quotations (multi-line · convert & split)
   All data from API: customers, users, doctors, companies, products.
   Draft → Sent → Accepted → Converted (or Expired)
   ============================================================ */
const DATA = window.DATA;

const ROUTE_KIND = { Sale: 'info', Rental: 'warn', Service: 'ok' };
const ROUTE_ICON = { Sale: Icons.sales, Rental: Icons.rental, Service: Icons.wrench };

function lineFromProduct(p, fulfilment) {
  const rental = fulfilment === 'Rental';
  const rate = rental
    ? parseFloat(p.rent_rate || p.rentRate || p.unit_price || p.price || p.rate || 0)
    : parseFloat(p.unit_price || p.price || p.rate || 0);
  return {
    sku:        p.sku || '',
    type:       p.item_type || p.type || 'Machine',
    desc:       p.name || '',
    fulfilment,
    qty:        1,
    rate,
    serialReq:  !!(p.serial_required || p.serial_req || p.serialReq),
    warranty:   p.warranty_months ? `${p.warranty_months} months` : (p.warranty || '—'),
    ...(rental ? { plan: 'Monthly', deposit: 50000 } : {}),
  };
}

function emptyLine(type, products) {
  const t = type || 'Machine';
  const first = products.find(p => (p.item_type || p.type) === t);
  if (!first) return { type: t, desc: '', fulfilment: DATA.fulfilmentByType[t]?.[0] || 'Sale', qty: 1, rate: 0 };
  return lineFromProduct(first, DATA.fulfilmentByType[t]?.[0] || 'Sale');
}

function MixCells({ q }) {
  const mix   = DATA.quoteMix(q);
  const order = ['Machine', 'Accessory', 'Spare Part', 'Consumable', 'Service'];
  const parts = order.filter(t => mix[t]).map(t => `${mix[t]} ${t.toLowerCase()}${mix[t] > 1 && t !== 'Spare Part' ? 's' : ''}`);
  const head  = parts.slice(0, 2).join(' · ');
  const more  = parts.length > 2 ? ` +${parts.length - 2}` : '';
  return <><div style={{ fontWeight: 600 }}>{head || '—'}</div><div className="tiny muted">{(q.items || []).length} line items{more}</div></>;
}

function RouteBadges({ q }) {
  const routes = [...new Set((q.items || []).map(it => it.fulfilment))].filter(Boolean);
  return <div className="row" style={{ gap: 5, flexWrap: 'wrap' }}>{routes.map(r => <Badge key={r} kind={ROUTE_KIND[r] || 'idle'}>{r}</Badge>)}</div>;
}

/* ── Main list ─────────────────────────────────────────────────── */
function Quotations({ branch }) {
  const { PKR } = DATA;
  const [tab, setTab]     = useState('All');
  const [q, setQ]         = useState('');
  const [sel, setSel]     = useState(null);
  const [neu, setNeu]     = useState(false);

  const bf = branch !== 'All' ? { branch_id: branch } : {};
  const { data: quotes, refetch } = useQuotations(bf);
  const { data: companies }       = useCompanies();

  const filtered = quotes.filter(x =>
    (tab === 'All' || x.status === tab) &&
    (!q || (x.no || '').toLowerCase().includes(q.toLowerCase()) || (x.cust || '').toLowerCase().includes(q.toLowerCase()))
  );

  const pipeline = quotes.filter(x => ['Sent', 'Accepted'].includes(x.status)).reduce((s, x) => s + DATA.quoteTotal(x), 0);
  const accepted  = quotes.filter(x => x.status === 'Accepted').length;
  const converted = quotes.filter(x => x.status === 'Converted').length;
  const open      = quotes.filter(x => ['Draft', 'Sent'].includes(x.status)).length;

  return (
    <div>
      <div className="grid" style={{ gridTemplateColumns: 'repeat(4,1fr)', marginBottom: 20 }}>
        <StatCard icon={<Icons.receipt size={18} />} label="Open Quotations" value={open}               sub="draft + sent" />
        <StatCard icon={<Icons.chart   size={18} />} label="Quote Pipeline"  value={PKR(Math.round(pipeline))} accent />
        <StatCard icon={<Icons.check   size={18} />} label="Accepted"        value={accepted}           sub="ready to convert" />
        <StatCard icon={<Icons.swap    size={18} />} label="Converted"       value={converted}          sub="became orders" />
      </div>

      <div className="card">
        <div className="card-pad row" style={{ justifyContent: 'space-between', gap: 14, flexWrap: 'wrap', paddingBottom: 14 }}>
          <Tabs tabs={['All', 'Draft', 'Sent', 'Accepted', 'Converted', 'Expired']} value={tab} onChange={setTab} />
          <div className="row" style={{ gap: 10 }}>
            <SearchBox value={q} onChange={setQ} placeholder="Quote or customer…" w={220} />
            {window.can('quotations','create') && <Btn variant="primary" icon={<Icons.plus size={16} stroke={2.6} />} onClick={() => setNeu(true)}>New Quotation</Btn>}
          </div>
        </div>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl">
            <thead><tr><th>Quote</th><th>Customer</th><th>Items</th><th>Routes</th><th>Tax</th><th>Total</th><th>Valid Till</th><th>Status</th></tr></thead>
            <tbody>
              {filtered.map(x => (
                <tr key={x.id || x.no} style={{ cursor: 'pointer' }} onClick={() => setSel(x)}>
                  <td className="mono" style={{ fontWeight: 700 }}>{x.no}</td>
                  <td style={{ fontWeight: 600 }}>{x.cust}</td>
                  <td><MixCells q={x} /></td>
                  <td><RouteBadges q={x} /></td>
                  <td><Badge kind={x.gst ? 'info' : 'idle'}>{x.gst ? 'GST' : 'Non-GST'}</Badge></td>
                  <td className="mono" style={{ fontWeight: 700 }}>{PKR(DATA.quoteTotal(x))}</td>
                  <td className="tiny muted">{x.validity}</td>
                  <td><Badge kind={window.statusKind(x.status)}>{x.status}</Badge></td>
                </tr>
              ))}
              {!filtered.length && <tr><td colSpan="8" className="muted tiny" style={{ padding: 14 }}>No quotations match.</td></tr>}
            </tbody>
          </table>
        </div>
        {!filtered.length && !quotes.length && <div className="ph-img" style={{ height: 110, margin: 18 }}>no quotations yet</div>}
      </div>

      {sel && <QuoteDetail x={sel} companies={companies} onClose={() => setSel(null)} refetch={refetch} />}
      {neu && <NewQuote companies={companies} branch={branch} onClose={() => setNeu(false)} refetch={refetch} />}
    </div>
  );
}

/* ── Quotation detail + split preview ─────────────────────────── */
function QuoteDetail({ x, companies, onClose, refetch }) {
  const { PKR } = DATA;
  const [convert, setConvert] = useState(false);
  const [confirmDel, setConfirmDel] = useState(false);
  const docRef = useRef(null);

  const co  = companies.find(c => c.id === (x.company_id || x.company)) || companies[0] || {};
  const sub = DATA.quoteSubtotal(x);
  const tax = DATA.quoteTax(x);
  const orders     = DATA.splitQuote({ ...x, company: x.company_id || x.company });
  const canConvert = ['Accepted', 'Sent'].includes(x.status);
  const canDelete  = ['Draft', 'Expired'].includes(x.status);

  if (confirmDel) return (
    <ConfirmDeleteModal
      title="Delete Quotation?"
      body={<>Permanently remove <strong>{x.no}</strong> for {x.cust}? This cannot be undone.</>}
      onCancel={() => setConfirmDel(false)}
      onConfirm={async () => {
        await api.deleteQuotation(x.id);
        window.toast('Quotation deleted', 'ok');
        refetch?.();
        onClose();
      }}
    />
  );

  return (
    <Modal wide title={`Quotation ${x.no}`} sub={`${x.cust} · valid till ${x.validity}`} onClose={onClose}
      foot={<>
        {canDelete && window.can('quotations','delete') && (
          <Btn variant="danger" icon={<Icons.trash size={15} />} onClick={() => setConfirmDel(true)}>Delete</Btn>
        )}
        <Btn variant="ghost" icon={<Icons.download size={16} />} onClick={() => window.printDocument(docRef.current)}>Download PDF</Btn>
        <Btn variant="ghost" icon={<Icons.print    size={16} />} onClick={() => window.printDocument(docRef.current)}>Print</Btn>
        <WaSendBtn docType="Estimate" docId={x.id} />
        {x.status === 'Draft' && <Btn variant="dark" icon={<Icons.bell size={16} />}>Send to Customer</Btn>}
        {canConvert && <Btn variant="primary" icon={<Icons.swap size={16} />} onClick={() => setConvert(true)}>
          Convert &amp; Split → {orders.length} order{orders.length > 1 ? 's' : ''}
        </Btn>}
      </>}>
      <div ref={docRef} style={{ border: '1px solid var(--line)', borderRadius: 14, overflow: 'hidden' }}>
        <div style={{ padding: '16px 20px', background: co.color || 'var(--forest)', color: '#fff', display: 'flex', justifyContent: 'space-between' }}>
          <div>
            <div style={{ fontWeight: 800, fontSize: 15 }}>{co.name || 'Electromed'}</div>
            <div className="tiny" style={{ color: 'rgba(255,255,255,.7)', marginTop: 2 }}>{co.letterhead || co.addr || ''}</div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <div style={{ fontWeight: 800, fontSize: 16, letterSpacing: '.04em' }}>QUOTATION</div>
            <div className="tiny mono" style={{ color: 'rgba(255,255,255,.8)', marginTop: 3 }}>{x.no} · {x.date}</div>
          </div>
        </div>
        <div style={{ padding: '14px 20px', borderBottom: '1px solid var(--line)', display: 'flex', justifyContent: 'space-between', gap: 14, flexWrap: 'wrap' }}>
          <div>
            <div className="tiny muted" style={{ fontWeight: 700, marginBottom: 3 }}>PREPARED FOR</div>
            <div style={{ fontWeight: 700 }}>{x.cust}</div>
            <div className="tiny muted">Salesperson · {x.rep}{x.doctor && x.doctor !== '—' && ` · Ref. ${x.doctor}`}</div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <div className="tiny muted" style={{ fontWeight: 700, marginBottom: 3 }}>TAX TREATMENT</div>
            <Badge kind={x.gst ? 'info' : 'idle'}>{x.gst ? `GST @ ${co.gstRate || 17}%` : 'Non-GST'}</Badge>
          </div>
        </div>

        <table className="tbl" style={{ fontSize: 13 }}>
          <thead><tr>
            <th>Description</th><th>Type</th><th>Route</th>
            <th style={{ textAlign: 'right' }}>Qty</th><th style={{ textAlign: 'right' }}>Unit</th><th style={{ textAlign: 'right' }}>Amount</th>
          </tr></thead>
          <tbody>
            {(x.items || []).map((it, i) => (
              <tr key={i}>
                <td style={{ fontWeight: 600 }}>{it.desc}
                  {it.fulfilment === 'Rental' && <div className="tiny muted">{it.plan} rental · deposit {PKR(it.deposit)}</div>}
                  {it.serialReq && it.fulfilment === 'Sale' && <div className="tiny muted">serialised · {it.warranty}</div>}
                </td>
                <td className="tiny muted">{it.type}</td>
                <td><Badge kind={ROUTE_KIND[it.fulfilment] || 'idle'}>{it.fulfilment}</Badge></td>
                <td className="mono" style={{ textAlign: 'right' }}>{it.qty}</td>
                <td className="mono" style={{ textAlign: 'right' }}>{PKR(it.rate)}{it.fulfilment === 'Rental' && <span className="tiny muted">/{it.plan === 'Daily' ? 'day' : it.plan === 'Weekly' ? 'wk' : 'mo'}</span>}</td>
                <td className="mono" style={{ textAlign: 'right', fontWeight: 700 }}>{PKR(DATA.lineAmount(it))}</td>
              </tr>
            ))}
          </tbody>
        </table>

        <div style={{ padding: '12px 20px', display: 'flex', justifyContent: 'flex-end' }}>
          <div style={{ width: 260 }}>
            <div className="row" style={{ justifyContent: 'space-between', padding: '5px 0' }}><span className="muted tiny">Subtotal</span><span className="mono">{PKR(sub)}</span></div>
            {tax > 0 && <div className="row" style={{ justifyContent: 'space-between', padding: '5px 0' }}><span className="muted tiny">GST @ {co.gstRate || 17}%</span><span className="mono">{PKR(tax)}</span></div>}
            <div className="row" style={{ justifyContent: 'space-between', padding: '9px 0 0', borderTop: '1px solid var(--line)', marginTop: 5 }}>
              <span style={{ fontWeight: 800 }}>Total</span>
              <span className="mono" style={{ fontWeight: 800, fontSize: 16 }}>{PKR(sub + tax)}</span>
            </div>
          </div>
        </div>
        <div className="tiny muted" style={{ padding: '10px 20px', borderTop: '1px solid var(--line)' }}>
          Quotation valid until {x.validity}. Rental rates shown per period; deposits refundable on return. {x.gst ? `Prices inclusive of ${co.gstRate || 17}% GST.` : 'Non-GST quotation.'}
        </div>
      </div>

      <div style={{ marginTop: 18 }}>
        <div className="row" style={{ gap: 8, marginBottom: 10, alignItems: 'baseline', justifyContent: 'space-between' }}>
          <div className="row" style={{ gap: 8 }}>
            <Icons.swap size={17} style={{ color: 'var(--lime-700)' }} />
            <span style={{ fontWeight: 800, fontSize: 14 }}>On conversion this splits into {orders.length} order{orders.length > 1 ? 's' : ''}</span>
          </div>
          <span className="tiny muted">grouped by route · entity · tax</span>
        </div>
        <div className="grid" style={{ gridTemplateColumns: orders.length > 1 ? '1fr 1fr' : '1fr', gap: 10 }}>
          {orders.map((o, i) => <OrderCard key={i} o={o} companies={companies} preview />)}
        </div>
      </div>

      {convert && <ConvertSplit x={x} orders={orders} companies={companies} onClose={() => setConvert(false)} refetch={refetch} />}
    </Modal>
  );
}

/* ── Single order card (preview + post-convert) ─────────────────── */
function OrderCard({ o, companies, preview, generated }) {
  const { PKR } = DATA;
  const RIcon = ROUTE_ICON[o.kind] || Icons.sales;
  const co    = (companies || []).find(c => c.id === o.company) || {};
  return (
    <div style={{ border: '1px solid var(--line)', borderRadius: 13, overflow: 'hidden', background: 'var(--surface)' }}>
      <div className="row" style={{ justifyContent: 'space-between', padding: '10px 13px', background: 'var(--surface-2)', borderBottom: '1px solid var(--line)' }}>
        <div className="row" style={{ gap: 9 }}>
          <span style={{ width: 30, height: 30, borderRadius: 9, display: 'grid', placeItems: 'center', background: '#fff', border: '1px solid var(--line)', color: `var(--${ROUTE_KIND[o.kind] || 'idle'})` }}><RIcon size={16} /></span>
          <div>
            <div style={{ fontWeight: 800, fontSize: 13 }}>{o.label}</div>
            <div className="tiny mono muted">{generated ? o.no : 'on convert'}</div>
          </div>
        </div>
        <Badge kind={ROUTE_KIND[o.kind] || 'idle'}>{o.kind}</Badge>
      </div>
      <div style={{ padding: '9px 13px' }}>
        {(o.lines || []).map((it, i) => (
          <div key={i} className="row" style={{ justifyContent: 'space-between', padding: '3px 0', gap: 10 }}>
            <span className="tiny" style={{ fontWeight: 600 }}>{it.qty}× {it.desc}</span>
            <span className="tiny mono muted">{PKR(DATA.lineAmount(it))}</span>
          </div>
        ))}
        {o.kind === 'Rental' && o.deposit != null && <div className="row" style={{ justifyContent: 'space-between', padding: '3px 0' }}><span className="tiny muted">{o.plan} · security deposit</span><span className="tiny mono">{PKR(o.deposit)}</span></div>}
      </div>
      <div className="row" style={{ justifyContent: 'space-between', padding: '8px 13px', borderTop: '1px solid var(--line)' }}>
        <span className="tiny muted">{co.short || co.name || o.company} · {o.gst ? `GST ${o.gstRate}%` : 'Non-GST'}</span>
        <span className="mono" style={{ fontWeight: 800 }}>{PKR(o.total)}</span>
      </div>
    </div>
  );
}

/* ── Convert & split confirmation ──────────────────────────────── */
function ConvertSplit({ x, orders, companies, onClose, refetch }) {
  const { PKR } = DATA;
  const [done, setDone]   = useState(false);
  const [saving, setSaving] = useState(false);
  const [err, setErr]     = useState('');
  const grand   = orders.reduce((s, o) => s + o.total, 0);
  const byKind  = (k) => orders.filter(o => o.kind === k).length;

  const doConvert = async () => {
    setSaving(true); setErr('');
    try {
      await api.convertQuotation(x.id);
      setDone(true);
      refetch?.();
    } catch (e) {
      setErr(e.message || 'Conversion failed');
    } finally {
      setSaving(false);
    }
  };

  return (
    <Modal wide title={done ? 'Orders generated' : 'Convert & Split'} sub={done ? `${x.no} converted` : `${x.no} → ${orders.length} operational orders`} onClose={onClose}
      foot={done
        ? <Btn variant="primary" icon={<Icons.check size={16} />} onClick={onClose}>Done</Btn>
        : <><Btn variant="ghost" onClick={onClose}>Cancel</Btn><Btn variant="primary" icon={<Icons.swap size={16} />} disabled={saving} onClick={doConvert}>Generate {orders.length} order{orders.length > 1 ? 's' : ''}</Btn></>}>
      {err && <div className="err-banner" style={{ marginBottom: 12, padding: '8px 12px', background: 'var(--bad-bg)', color: 'var(--bad)', borderRadius: 8, fontSize: 13 }}>{err}</div>}
      {!done && (
        <>
          <div className="row" style={{ gap: 8, padding: '11px 14px', background: 'var(--lime-soft)', borderRadius: 12, marginBottom: 16 }}>
            <Icons.spark size={18} style={{ color: 'var(--lime-700)', flexShrink: 0 }} />
            <div className="tiny" style={{ fontWeight: 600 }}>
              Items are grouped by fulfilment route, then by billing entity &amp; tax treatment.
              Sale lines merge into invoices; rented machines on the same billing cycle share one agreement; each service books separately.
            </div>
          </div>
          <div className="row" style={{ gap: 8, marginBottom: 14, flexWrap: 'wrap' }}>
            {['Sale', 'Rental', 'Service'].filter(k => byKind(k)).map(k => (
              <Badge key={k} kind={ROUTE_KIND[k]}>{byKind(k)} {k}{byKind(k) > 1 ? ' orders' : ' order'}</Badge>
            ))}
          </div>
          <div className="grid" style={{ gridTemplateColumns: orders.length > 1 ? '1fr 1fr' : '1fr', gap: 10 }}>
            {orders.map((o, i) => <OrderCard key={i} o={o} companies={companies} generated />)}
          </div>
          <div className="row" style={{ justifyContent: 'space-between', padding: '12px 14px', marginTop: 14, background: 'var(--surface-2)', borderRadius: 12 }}>
            <span style={{ fontWeight: 700 }}>Combined value</span>
            <span className="mono" style={{ fontWeight: 800, fontSize: 16 }}>{PKR(grand)}</span>
          </div>
        </>
      )}
      {done && (
        <div>
          <div style={{ textAlign: 'center', padding: '4px 0 16px' }}>
            <div style={{ width: 60, height: 60, borderRadius: 50, background: 'var(--lime-soft)', display: 'grid', placeItems: 'center', margin: '0 auto 12px' }}><Icons.check size={32} stroke={2.6} style={{ color: 'var(--lime-700)' }} /></div>
            <div style={{ fontWeight: 800, fontSize: 18 }}>{orders.length} order{orders.length > 1 ? 's' : ''} created from {x.no}</div>
            <div className="tiny muted" style={{ marginTop: 4 }}>Quotation marked <b>Converted</b> · inventory reserved · {x.cust} notified.</div>
          </div>
          <div style={{ display: 'grid', gap: 8 }}>
            {orders.map((o, i) => {
              const RIcon = ROUTE_ICON[o.kind] || Icons.sales;
              return (
                <div key={i} className="row" style={{ justifyContent: 'space-between', padding: '11px 14px', border: '1px solid var(--line)', borderRadius: 12 }}>
                  <div className="row" style={{ gap: 10 }}>
                    <span style={{ width: 30, height: 30, borderRadius: 9, display: 'grid', placeItems: 'center', background: 'var(--surface-2)', color: `var(--${ROUTE_KIND[o.kind] || 'idle'})` }}><RIcon size={16} /></span>
                    <div><div style={{ fontWeight: 700, fontSize: 13.5 }} className="mono">{o.no}</div><div className="tiny muted">{o.label} · {(o.lines || []).length} line{(o.lines || []).length > 1 ? 's' : ''}</div></div>
                  </div>
                  <span className="mono" style={{ fontWeight: 700 }}>{PKR(o.total)}</span>
                </div>
              );
            })}
          </div>
          <div className="row" style={{ gap: 8, justifyContent: 'center', flexWrap: 'wrap', marginTop: 16 }}>
            <Badge kind="ok"><Icons.bell size={12} />SMS sent</Badge>
            <Badge kind="info">Email quotation</Badge>
            <Badge kind="warn">WhatsApp</Badge>
          </div>
        </div>
      )}
    </Modal>
  );
}

/* ── New Quotation — line-item builder ─────────────────────────── */
function NewQuote({ companies, branch = 'All', onClose, refetch }) {
  const { PKR } = DATA;
  const bf = branch !== 'All' ? { branch_id: branch } : {};
  const { data: customers } = useCustomers(bf);
  const { data: users }     = useUsers();
  const { data: doctors }   = useDoctors();
  const { data: products }  = useProducts(bf);

  const [custId,    setCustId]    = useState('');
  const [userId,    setUserId]    = useState('');
  const [doctorName, setDoctor]   = useState('—');
  const [companyId, setCompany]   = useState('');
  const [gst,       setGst]       = useState(true);
  const [validity,  setValidity]  = useState(() => {
    const d = new Date(); d.setDate(d.getDate() + 30); return d.toISOString().slice(0, 10);
  });
  const [items,  setItems]  = useState([]);
  const [saving, setSaving] = useState(false);
  const [err,    setErr]    = useState('');

  React.useEffect(() => { if (customers.length && !custId)    setCustId(customers[0].id); },    [customers.length]);
  React.useEffect(() => { if (users.length    && !userId)     setUserId(users[0].id); },         [users.length]);
  React.useEffect(() => { if (companies.length && !companyId) setCompany(companies[0].id); },    [companies.length]);
  React.useEffect(() => {
    if (products.length && !items.length) {
      const first = products.find(p => (p.item_type || p.type) === 'Machine') || products[0];
      if (first) setItems([lineFromProduct(first, 'Sale')]);
    }
  }, [products.length]);

  const patch      = (ix, p) => setItems(arr => arr.map((it, i) => i === ix ? { ...it, ...p } : it));
  const setType    = (ix, type) => {
    const first = products.find(p => (p.item_type || p.type) === type);
    if (first) patch(ix, lineFromProduct(first, DATA.fulfilmentByType[type]?.[0] || 'Sale'));
    else patch(ix, { type, fulfilment: DATA.fulfilmentByType[type]?.[0] || 'Sale' });
  };
  const setProduct = (ix, name) => {
    const p = products.find(x => x.name === name);
    if (!p) return;
    const cur = items[ix]?.fulfilment;
    const t   = p.item_type || p.type || 'Machine';
    const ful = DATA.fulfilmentByType[t]?.includes(cur) ? cur : (DATA.fulfilmentByType[t]?.[0] || 'Sale');
    patch(ix, lineFromProduct(p, ful));
  };
  const setFul     = (ix, ful) => {
    const p = products.find(x => x.name === items[ix]?.desc);
    if (p) patch(ix, lineFromProduct(p, ful));
    else   patch(ix, { fulfilment: ful });
  };
  const remove     = (ix) => setItems(arr => arr.filter((_, i) => i !== ix));
  const add        = () => {
    const first = products.find(p => (p.item_type || p.type) === 'Machine') || products[0];
    if (first) setItems(arr => [...arr, lineFromProduct(first, 'Sale')]);
  };

  const draft  = { items, company: companyId, gst };
  const sub    = DATA.quoteSubtotal(draft);
  const tax    = DATA.quoteTax(draft);
  const orders = DATA.splitQuote(draft);

  const save = async (status) => {
    if (!custId) { setErr('Select a customer first'); return; }
    if (!items.length) { setErr('Add at least one line item'); return; }
    setSaving(true); setErr('');
    try {
      const selCust = customers.find(c => c.id === custId) || null;
      const selUser = users.find(u => u.id === userId) || null;
      const selCo   = companies.find(c => c.id === companyId) || null;
      await api.createQuotation({
        customer_id:   custId,
        customer_name: selCust ? selCust.name : '',
        rep:           selUser ? selUser.name : null,
        doctor:        doctorName !== '—' ? doctorName : null,
        company:       selCo ? selCo.name : null,
        gst:           gst ? 1 : 0,
        validity,
        status,
        subtotal:      Math.round(sub),
        tax_amount:    Math.round(tax),
        total:         Math.round(sub + tax),
        branch_id:     branch !== 'All' ? branch : null,
        items: items.map(it => ({
          type:            it.type || 'Machine',
          fulfilment:      it.fulfilment || 'Sale',
          description:     it.desc || it.name || '',
          category:        it.type || null,
          quantity:        Number(it.qty) || 1,
          rate:            Number(it.rate) || 0,
          plan:            it.plan || null,
          deposit:         Number(it.deposit) || 0,
          warranty:        it.warranty && it.warranty !== '—' ? it.warranty : null,
          serial_required: it.serialReq ? 1 : 0,
        })),
      });
      window.toast('Quotation saved', 'ok');
      refetch?.();
      onClose();
    } catch (e) {
      setErr(e.message || 'Save failed');
    } finally {
      setSaving(false);
    }
  };

  const selCust = customers.find(c => c.id === custId) || null;
  const selUser = users.find(u => u.id === userId)     || null;
  const selCo   = companies.find(c => c.id === companyId) || null;

  return (
    <Modal wide title="New Quotation" sub="Add every item the customer asked for — one quote, split into orders at conversion" onClose={onClose}
      foot={<>
        <Btn variant="ghost" onClick={onClose}>Cancel</Btn>
        <Btn variant="dark" disabled={saving} onClick={() => save('Draft')}>Save Draft</Btn>
        <Btn variant="primary" icon={<Icons.check size={16} />} disabled={saving} onClick={() => save('Sent')}>Save &amp; Send</Btn>
      </>}>
      {err && <div style={{ padding: '8px 12px', background: 'var(--bad-bg)', color: 'var(--bad)', borderRadius: 8, fontSize: 13, marginBottom: 12 }}>{err}</div>}

      <div className="grid" style={{ gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 8 }}>
        <label className="fld"><span>Customer</span>
          <select className="input-block" value={custId} onChange={e => setCustId(e.target.value)}>
            {!customers.length && <option value="">Loading…</option>}
            {customers.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
          </select>
        </label>
        <label className="fld"><span>Referring Doctor</span>
          <select className="input-block" value={doctorName} onChange={e => setDoctor(e.target.value)}>
            <option value="—">—</option>
            {doctors.map(d => <option key={d.id} value={d.name}>{d.name}</option>)}
          </select>
        </label>
      </div>
      <div className="grid" style={{ gridTemplateColumns: '1fr 1fr 1fr', gap: 12, marginBottom: 18 }}>
        <label className="fld"><span>Salesperson</span>
          <select className="input-block" value={userId} onChange={e => setUserId(e.target.value)}>
            {!users.length && <option value="">Loading…</option>}
            {users.map(u => <option key={u.id} value={u.id}>{u.name}</option>)}
          </select>
        </label>
        <label className="fld"><span>Billing Entity</span>
          <select className="input-block" value={companyId} onChange={e => setCompany(e.target.value)}>
            {!companies.length && <option value="">Loading…</option>}
            {companies.map(c => <option key={c.id} value={c.id}>{c.short || c.name}</option>)}
          </select>
        </label>
        <label className="fld"><span>Valid Till</span>
          <input type="date" className="input-block" value={validity} onChange={e => setValidity(e.target.value)} />
        </label>
      </div>

      <label className="fld" style={{ marginBottom: 16 }}><span>Default Tax Treatment</span>
        <div className="tabs" style={{ width: '100%', display: 'flex' }}>
          {[[`GST ${selCo?.gstRate || 17}%`, true], ['Non-GST', false]].map(([t, v]) => (
            <button key={t} className={cls('tab', gst === v && 'active')} style={{ flex: 1 }} onClick={() => setGst(v)}>{t}</button>
          ))}
        </div>
      </label>

      <div className="row" style={{ justifyContent: 'space-between', marginBottom: 10 }}>
        <span style={{ fontWeight: 800, fontSize: 14 }}>Line Items</span>
        <span className="tiny muted">{items.length} item{items.length > 1 ? 's' : ''}</span>
      </div>

      {!products.length
        ? <div className="tiny muted" style={{ padding: 14 }}>Loading products…</div>
        : <div style={{ display: 'grid', gap: 10 }}>
            {items.map((it, ix) => (
              <LineRow key={ix} it={it} ix={ix} products={products}
                onType={setType} onProduct={setProduct} onFul={setFul} onPatch={patch} onRemove={remove} canRemove={items.length > 1} />
            ))}
          </div>
      }
      <button className="btn btn-ghost btn-sm" style={{ marginTop: 10, border: '1px dashed var(--line-2)', width: '100%', justifyContent: 'center', padding: 10 }} onClick={add} disabled={!products.length}>
        <Icons.plus size={15} stroke={2.5} />Add line item
      </button>

      <div style={{ marginTop: 18, padding: 14, background: 'var(--surface-2)', borderRadius: 14 }}>
        <div className="row" style={{ justifyContent: 'space-between', padding: '4px 0' }}><span className="tiny muted">Subtotal</span><span className="mono" style={{ fontWeight: 600 }}>{PKR(sub)}</span></div>
        {tax > 0 && <div className="row" style={{ justifyContent: 'space-between', padding: '4px 0' }}><span className="tiny muted">GST</span><span className="mono" style={{ fontWeight: 600 }}>{PKR(tax)}</span></div>}
        <div className="row" style={{ justifyContent: 'space-between', padding: '8px 0 0', borderTop: '1px solid var(--line)', marginTop: 5 }}>
          <span style={{ fontWeight: 800 }}>Total</span>
          <span className="mono" style={{ fontWeight: 800, fontSize: 16 }}>{PKR(sub + tax)}</span>
        </div>
        {orders.length > 0 && (
          <div className="row" style={{ gap: 8, marginTop: 12, paddingTop: 12, borderTop: '1px solid var(--line)', flexWrap: 'wrap' }}>
            <Icons.swap size={15} style={{ color: 'var(--lime-700)' }} />
            <span className="tiny" style={{ fontWeight: 700 }}>Converts to {orders.length} order{orders.length > 1 ? 's' : ''}:</span>
            {orders.map((o, i) => <Badge key={i} kind={ROUTE_KIND[o.kind]}>{o.label}</Badge>)}
          </div>
        )}
      </div>
    </Modal>
  );
}

/* ── Editable line-item row ─────────────────────────────────────── */
function LineRow({ it, ix, products = [], onType, onProduct, onFul, onPatch, onRemove, canRemove }) {
  const { PKR } = DATA;
  const type     = it.type || 'Machine';
  const byType   = products.filter(p => (p.item_type || p.type) === type);
  const fulOpts  = DATA.fulfilmentByType[type] || ['Sale'];
  const rental   = it.fulfilment === 'Rental';

  return (
    <div style={{ border: '1px solid var(--line)', borderRadius: 13, padding: 12, background: 'var(--surface)' }}>
      <div className="row" style={{ gap: 8, alignItems: 'flex-start' }}>
        <select className="input-block" style={{ width: 128, flexShrink: 0, fontWeight: 600 }} value={type} onChange={e => onType(ix, e.target.value)}>
          {DATA.itemTypes.map(t => <option key={t}>{t}</option>)}
        </select>
        <select className="input-block" style={{ flex: 1, minWidth: 0 }} value={it.desc} onChange={e => onProduct(ix, e.target.value)}>
          {byType.length === 0 && <option value={it.desc}>{it.desc || 'No products'}</option>}
          {byType.map(p => <option key={p.id} value={p.name}>{p.name}</option>)}
        </select>
        <div className="mono" style={{ fontWeight: 800, fontSize: 14, whiteSpace: 'nowrap', paddingTop: 9, minWidth: 92, textAlign: 'right' }}>{PKR(DATA.lineAmount(it))}</div>
        <button className="btn-icon" style={{ color: 'var(--ink-3)', flexShrink: 0 }} disabled={!canRemove} onClick={() => onRemove(ix)}><Icons.x size={17} /></button>
      </div>
      <div className="row" style={{ gap: 8, marginTop: 8, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <span className="tiny muted" style={{ fontWeight: 700 }}>Route</span>
          <div className="tabs" style={{ display: 'flex' }}>
            {fulOpts.map(f => <button key={f} className={cls('tab', it.fulfilment === f && 'active')} style={{ fontSize: 12 }} onClick={() => onFul(ix, f)}>{f}</button>)}
          </div>
        </div>
        <label style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <span className="tiny muted" style={{ fontWeight: 700 }}>Qty</span>
          <input className="input-block mono" style={{ width: 62, padding: '7px 9px' }} value={it.qty} onChange={e => onPatch(ix, { qty: Math.max(1, parseInt(e.target.value) || 1) })} />
        </label>
        <label style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <span className="tiny muted" style={{ fontWeight: 700 }}>{rental ? 'Rate/period' : 'Unit rate'}</span>
          <input className="input-block mono" style={{ width: 104, padding: '7px 9px' }} value={it.rate} onChange={e => onPatch(ix, { rate: Math.max(0, parseInt(e.target.value.replace(/\D/g, '')) || 0) })} />
        </label>
        {it.serialReq && it.fulfilment === 'Sale' && <Badge kind="idle">serial + warranty</Badge>}
      </div>
      {rental && (
        <div className="row" style={{ gap: 8, marginTop: 8, padding: '9px 11px', background: 'var(--warn-bg)', borderRadius: 10, flexWrap: 'wrap' }}>
          <Icons.rental size={15} style={{ color: 'var(--warn)' }} />
          <label style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span className="tiny" style={{ fontWeight: 700, color: 'var(--warn)' }}>Plan</span>
            <div className="tabs" style={{ display: 'flex' }}>
              {['Daily', 'Weekly', 'Monthly'].map(p => <button key={p} className={cls('tab', it.plan === p && 'active')} style={{ fontSize: 12 }} onClick={() => onPatch(ix, { plan: p })}>{p}</button>)}
            </div>
          </label>
          <label style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span className="tiny" style={{ fontWeight: 700, color: 'var(--warn)' }}>Deposit</span>
            <input className="input-block mono" style={{ width: 104, padding: '7px 9px' }} value={it.deposit} onChange={e => onPatch(ix, { deposit: Math.max(0, parseInt(e.target.value.replace(/\D/g, '')) || 0) })} />
          </label>
          <span className="tiny muted" style={{ alignSelf: 'center' }}>→ becomes its own rental agreement</span>
        </div>
      )}
    </div>
  );
}

window.Quotations = Quotations;
Object.assign(window, { LineRow, lineFromProduct, emptyLine, OrderCard, ROUTE_KIND, ROUTE_ICON });
