// Catalog + Customers views

const CatalogView = ({ tweaks, onNew }) => {
  const [products, setProducts] = React.useState(PRODUCTS || []);
  const [selectedCat, setSelectedCat] = React.useState('all');

  React.useEffect(() => {
    window.apiFetch('/api/products')
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d) { window.PRODUCTS = d; setProducts(d); } })
      .catch(() => {});
  }, []);

  const liveProducts = products.filter(p => !tweaks.hiddenProducts?.includes(p.id) && (p.status || 'live') === 'live');

  // Build category list from live products only (preserving PRODUCT_CATEGORIES order)
  const allCats = (window.PRODUCT_CATEGORIES || []).filter(c => liveProducts.some(p => p.category === c.name));
  // Fallback: derive categories directly from products if PRODUCT_CATEGORIES is empty
  const cats = allCats.length > 0 ? allCats : [...new Set(liveProducts.map(p => p.category))].map(n => ({ id: n, name: n }));

  const visible = selectedCat === 'all' ? liveProducts : liveProducts.filter(p => p.category === (cats.find(c => c.id === selectedCat)?.name || selectedCat));

  return (
    <>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 14 }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: 6 }}>Solutions · Catalog</div>
          <h1 style={{ fontSize: 22, fontWeight: 500, letterSpacing: '-0.01em', margin: 0 }}>Product catalog</h1>
          <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4 }}>
            <span className="num">{visible.length}</span> products · <span className="num">{visible.reduce((s, p) => s + p.packages.length, 0)}</span> packages พร้อมสั่งซื้อ
          </div>
        </div>
        <Button variant="primary" icon="plus" onClick={() => onNew()}>Quick order</Button>
      </div>

      {/* Category filter chips */}
      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 16 }}>
        {[{ id: 'all', name: 'ทั้งหมด' }, ...cats].map(cat => {
          const active = selectedCat === cat.id;
          // Find a product color for the category accent
          const catProduct = cat.id !== 'all' ? liveProducts.find(p => p.category === cat.name) : null;
          const accentColor = catProduct?.color || 'var(--brand)';
          return (
            <button key={cat.id} onClick={() => setSelectedCat(cat.id)} style={{
              padding: '5px 14px',
              border: `1px solid ${active ? accentColor : 'var(--line)'}`,
              borderRadius: 20,
              background: active ? accentColor + '14' : 'var(--panel)',
              color: active ? accentColor : 'var(--ink-2)',
              fontSize: 12, fontWeight: active ? 600 : 400,
              fontFamily: 'Kanit, sans-serif',
              cursor: 'pointer',
              display: 'inline-flex', alignItems: 'center', gap: 6,
              transition: 'all 120ms',
            }}
            onMouseEnter={e => { if (!active) { e.currentTarget.style.background = 'var(--bg-2)'; e.currentTarget.style.borderColor = 'var(--line-2)'; } }}
            onMouseLeave={e => { if (!active) { e.currentTarget.style.background = 'var(--panel)'; e.currentTarget.style.borderColor = 'var(--line)'; } }}>
              {catProduct && (
                <span style={{ width: 7, height: 7, borderRadius: '50%', background: accentColor, flexShrink: 0 }}/>
              )}
              {cat.name}
              <span className="num" style={{ fontSize: 10, color: active ? accentColor : 'var(--ink-4)', fontWeight: 400 }}>
                {cat.id === 'all' ? liveProducts.length : liveProducts.filter(p => p.category === cat.name).length}
              </span>
            </button>
          );
        })}
      </div>

      {visible.length === 0 && (
        <div style={{ padding: '48px 0', textAlign: 'center', color: 'var(--ink-4)', fontSize: 13 }}>
          ไม่มีสินค้าในหมวดหมู่นี้
        </div>
      )}

      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        {visible.map(product => (
          <div key={product.id} style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4, overflow: 'hidden' }}>
            <div style={{ padding: '16px 18px', borderBottom: '1px solid var(--line)', display: 'flex', alignItems: 'center', gap: 14 }}>
              <ProductGlyph productId={product.id} size={44}/>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <h3 style={{ fontSize: 15, fontWeight: 600, letterSpacing: '-0.01em', margin: 0 }}>{product.name}</h3>
                  <span style={{
                    fontSize: 10, padding: '2px 6px', background: product.color + '14', color: product.color,
                    borderRadius: 2, fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.06em',
                  }}>{product.category}</span>
                </div>
                <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>{product.nameTh}</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <div className="eyebrow" style={{ fontSize: 9.5 }}>Provisioning SLA</div>
                <div className="num" style={{ fontSize: 18, fontWeight: 500 }}>{product.slaDays}<span style={{ fontSize: 11, color: 'var(--ink-3)', marginLeft: 3 }}>วันทำการ</span></div>
              </div>
            </div>

            <div style={{ display: 'grid', gridTemplateColumns: `repeat(${product.packages.length}, 1fr)`, gap: 0 }}>
              {product.packages.map((pkg, i) => (
                <div key={pkg.id} style={{
                  padding: '14px 18px',
                  borderRight: i < product.packages.length - 1 ? '1px solid var(--line-2)' : 'none',
                  display: 'flex', flexDirection: 'column',
                }}>
                  <div style={{ fontWeight: 500, fontSize: 13 }}>{pkg.name}</div>
                  <div className="num" style={{ marginTop: 6, fontSize: 18, fontWeight: 500, letterSpacing: '-0.02em' }}>
                    ฿{pkg.price.toLocaleString()}
                    <span style={{ fontSize: 11, color: 'var(--ink-3)', marginLeft: 3, fontWeight: 400 }}>/{product.unit}/mo</span>
                  </div>
                  <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px solid var(--line-2)', flex: 1 }}>
                    {pkg.highlights.map((h, j) => (
                      <div key={j} style={{ display: 'flex', alignItems: 'flex-start', gap: 6, fontSize: 11, color: 'var(--ink-2)', padding: '3px 0' }}>
                        <Icon name="check" size={10} color={product.color}/>
                        <span>{h}</span>
                      </div>
                    ))}
                  </div>
                  {/* สมัคร button */}
                  <button
                    onClick={() => onNew({ productId: product.id, packageId: pkg.id, qty: pkg.seats || 1 })}
                    style={{
                      marginTop: 14,
                      width: '100%', padding: '7px 0',
                      background: product.color + '14',
                      border: `1px solid ${product.color}40`,
                      borderRadius: 3,
                      color: product.color, fontWeight: 600, fontSize: 12,
                      fontFamily: 'Kanit, sans-serif', cursor: 'pointer',
                      display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5,
                      transition: 'background 120ms, border-color 120ms',
                    }}
                    onMouseEnter={e => { e.currentTarget.style.background = product.color + '28'; e.currentTarget.style.borderColor = product.color + '80'; }}
                    onMouseLeave={e => { e.currentTarget.style.background = product.color + '14'; e.currentTarget.style.borderColor = product.color + '40'; }}>
                    <Icon name="plus" size={11} color={product.color}/>
                    สมัคร
                  </button>
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </>
  );
};

// ─── Company edit modal ───────────────────────────────────────────────────────

const COMPANY_SECTORS = ['Manufacturing','Retail','Banking','Logistics','Hospitality','Healthcare','Agriculture','Trading','Technology','Energy','Other'];
const COMPANY_SIZES   = ['1–49','50–199','200–499','500–999','1,000+'];

const CompanyFormModal = ({ company, onSave, onClose }) => {
  const [form, setForm] = React.useState({
    name:     company.name     || '',
    taxId:    company.taxId    || '',
    sector:   company.sector   || '',
    size:     company.size     || '',
    province: company.province || '',
  });
  const [saving, setSaving] = React.useState(false);
  const [err, setErr]       = React.useState(null);

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSave = async () => {
    if (!form.name.trim()) { setErr('กรุณาระบุชื่อบริษัท'); return; }
    setSaving(true); setErr(null);
    try {
      const r    = await window.apiFetch(`/api/companies/${company.id}`, { method: 'PATCH', body: JSON.stringify(form) });
      const data = await r.json();
      if (!r.ok) { setErr(data.error || 'เกิดข้อผิดพลาด'); return; }
      onSave(data);
    } catch (e) { setErr('Network error'); }
    finally { setSaving(false); }
  };

  const textInp = (label, key, placeholder = '') => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
      <span style={{ fontSize: 11, color: 'var(--ink-3)', fontWeight: 500 }}>{label}</span>
      <input value={form[key]} onChange={e => set(key, e.target.value)} placeholder={placeholder}
        style={{ fontFamily: 'Kanit, sans-serif', fontSize: 13, padding: '7px 10px',
          background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 3, color: 'var(--ink)', outline: 'none' }}
        onFocus={e => e.target.style.borderColor = 'var(--ink)'}
        onBlur={e  => e.target.style.borderColor = 'var(--line)'}/>
    </div>
  );

  const selInp = (label, key, options) => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
      <span style={{ fontSize: 11, color: 'var(--ink-3)', fontWeight: 500 }}>{label}</span>
      <select value={form[key]} onChange={e => set(key, e.target.value)}
        style={{ fontFamily: 'Kanit, sans-serif', fontSize: 13, padding: '7px 10px',
          background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 3, color: 'var(--ink)', outline: 'none', cursor: 'pointer' }}>
        <option value="">— ไม่ระบุ —</option>
        {options.map(o => <option key={o} value={o}>{o}</option>)}
      </select>
    </div>
  );

  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(20,22,28,0.5)', zIndex: 400, display: 'grid', placeItems: 'center' }}>
      <div onClick={e => e.stopPropagation()} style={{ background: 'var(--panel)', width: 460, maxWidth: '92vw', borderRadius: 4, boxShadow: 'var(--shadow-modal)', display: 'flex', flexDirection: 'column' }}>
        <div style={{ padding: '18px 22px', borderBottom: '1px solid var(--line)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <h2 style={{ fontSize: 16, fontWeight: 500, margin: 0 }}>แก้ไขข้อมูลบริษัท</h2>
          <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ink-3)', padding: 4 }}><Icon name="close" size={14}/></button>
        </div>
        <div style={{ padding: '18px 22px', display: 'flex', flexDirection: 'column', gap: 12 }}>
          {err && <div style={{ padding: '8px 12px', background: 'var(--negative-bg)', border: '1px solid var(--negative)', borderRadius: 3, fontSize: 12, color: 'var(--negative)' }}>{err}</div>}
          {textInp('ชื่อบริษัท *', 'name', 'บริษัท ตัวอย่าง จำกัด')}
          {textInp('เลขประจำตัวผู้เสียภาษี', 'taxId', '0105xxxxxxxxx')}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            {selInp('Sector / ประเภทธุรกิจ', 'sector', COMPANY_SECTORS)}
            {selInp('ขนาดองค์กร', 'size', COMPANY_SIZES)}
          </div>
          {textInp('จังหวัด', 'province', 'กรุงเทพมหานคร')}
        </div>
        <div style={{ padding: '12px 22px', borderTop: '1px solid var(--line)', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <Button variant="ghost" onClick={onClose}>ยกเลิก</Button>
          <Button variant="primary" onClick={handleSave} disabled={saving}>{saving ? 'กำลังบันทึก…' : 'บันทึก'}</Button>
        </div>
      </div>
    </div>
  );
};

// ─── Contact add/edit modal ───────────────────────────────────────────────────

const EMPTY_CONTACT = { name: '', role: '', email: '', phone: '', mobile: '', isPrimary: false, contactType: 'Primary' };

const ContactFormModal = ({ companyId, contact, onSave, onClose }) => {
  const isEdit = !!contact?.id;
  const [form, setForm] = React.useState(contact ? {
    name: contact.name || '', role: contact.role || '',
    email: contact.email || '', phone: contact.phone || '',
    mobile: contact.mobile || '', isPrimary: contact.isPrimary || false,
    contactType: contact.contactType || 'Primary',
  } : { ...EMPTY_CONTACT });
  const [saving, setSaving] = React.useState(false);
  const [err, setErr]       = React.useState(null);

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSave = async () => {
    if (!form.name.trim()) { setErr('กรุณาระบุชื่อ contact'); return; }
    setSaving(true); setErr(null);
    try {
      const url    = isEdit ? `/api/contacts/${contact.id}` : '/api/contacts';
      const method = isEdit ? 'PATCH' : 'POST';
      const body   = isEdit ? form : { ...form, companyId };
      const r   = await window.apiFetch(url, { method, body: JSON.stringify(body) });
      const data = await r.json();
      if (!r.ok) { setErr(data.error || 'เกิดข้อผิดพลาด'); return; }
      onSave(data, isEdit);
    } catch (e) { setErr('Network error'); }
    finally { setSaving(false); }
  };

  const inp = (label, key, opts = {}) => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
      <span style={{ fontSize: 11, color: 'var(--ink-3)', fontWeight: 500 }}>{label}</span>
      <input
        value={form[key]}
        onChange={e => set(key, e.target.value)}
        placeholder={opts.placeholder || ''}
        type={opts.type || 'text'}
        style={{
          fontFamily: 'Kanit, sans-serif', fontSize: 13,
          padding: '7px 10px', background: 'var(--panel)',
          border: '1px solid var(--line)', borderRadius: 3,
          color: 'var(--ink)', outline: 'none',
        }}
        onFocus={e => e.target.style.borderColor = 'var(--ink)'}
        onBlur={e => e.target.style.borderColor = 'var(--line)'}
      />
    </div>
  );

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(20,22,28,0.5)',
      zIndex: 400, display: 'grid', placeItems: 'center',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        background: 'var(--panel)', width: 440, maxWidth: '92vw',
        borderRadius: 4, boxShadow: 'var(--shadow-modal)',
        display: 'flex', flexDirection: 'column',
      }}>
        {/* Header */}
        <div style={{ padding: '18px 22px', borderBottom: '1px solid var(--line)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <h2 style={{ fontSize: 16, fontWeight: 500, margin: 0 }}>
            {isEdit ? 'แก้ไข contact' : 'เพิ่ม contact'}
          </h2>
          <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ink-3)', padding: 4 }}>
            <Icon name="close" size={14}/>
          </button>
        </div>

        {/* Body */}
        <div style={{ padding: '18px 22px', display: 'flex', flexDirection: 'column', gap: 12 }}>
          {err && (
            <div style={{ padding: '8px 12px', background: 'var(--negative-bg)', border: '1px solid var(--negative)', borderRadius: 3, fontSize: 12, color: 'var(--negative)' }}>{err}</div>
          )}
          {inp('ชื่อ-นามสกุล *', 'name', { placeholder: 'สมชาย ใจดี' })}
          {inp('ตำแหน่ง', 'role', { placeholder: 'Operations Manager' })}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            {inp('อีเมล', 'email', { type: 'email', placeholder: 'name@company.com' })}
            {inp('เบอร์โทรศัพท์', 'phone', { placeholder: '02-xxx-xxxx' })}
          </div>
          {inp('มือถือ', 'mobile', { placeholder: '081-xxx-xxxx' })}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
            <span style={{ fontSize: 11, color: 'var(--ink-3)', fontWeight: 500 }}>ประเภทผู้ติดต่อ · Contact type</span>
            <select
              value={form.contactType || 'Primary'}
              onChange={e => set('contactType', e.target.value)}
              style={{
                fontFamily: 'Kanit, sans-serif', fontSize: 13,
                padding: '7px 10px', background: 'var(--panel)',
                border: '1px solid var(--line)', borderRadius: 3,
                color: 'var(--ink)', outline: 'none',
              }}>
              <option value="Primary">Primary</option>
              <option value="Executive">Executive</option>
              <option value="Accounting">Accounting</option>
              <option value="Sales">Sales</option>
              <option value="Technical">Technical</option>
            </select>
          </div>
        </div>

        {/* Footer */}
        <div style={{ padding: '12px 22px', borderTop: '1px solid var(--line)', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <Button variant="ghost" onClick={onClose}>ยกเลิก</Button>
          <Button variant="primary" onClick={handleSave} disabled={saving}>
            {saving ? 'กำลังบันทึก…' : (isEdit ? 'บันทึก' : 'เพิ่ม contact')}
          </Button>
        </div>
      </div>
    </div>
  );
};

// ─── Customer detail modal helpers ───────────────────────────────────────────

const custGhostMini = {
  display: 'inline-flex', alignItems: 'center', gap: 4,
  background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 3,
  padding: '4px 9px', fontSize: 11, fontFamily: 'Kanit, sans-serif', color: 'var(--ink-2)', cursor: 'pointer',
};

const CustKpi = ({ label, value }) => (
  <div style={{ background: 'var(--panel)', padding: '11px 14px' }}>
    <div className="eyebrow" style={{ fontSize: 9 }}>{label}</div>
    <div className="num" style={{ fontSize: 19, fontWeight: 500, letterSpacing: '-0.02em', marginTop: 4 }}>{value}</div>
  </div>
);

const CustSectionHeader = ({ n, label, th, action }) => (
  <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
    <span style={{ width: 22, height: 22, borderRadius: 3, background: 'var(--ink)', color: '#fff', display: 'grid', placeItems: 'center', fontSize: 11, fontWeight: 600, flexShrink: 0 }}>{n}</span>
    <div style={{ flex: 1 }}>
      <div style={{ fontSize: 14, fontWeight: 600, letterSpacing: '-0.01em' }}>{label}</div>
      <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{th}</div>
    </div>
    {action}
  </div>
);

const CustDefRow = ({ label, value }) => (
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12, padding: '6px 0' }}>
    <span style={{ fontSize: 11, color: 'var(--ink-3)', flexShrink: 0 }}>{label}</span>
    <span style={{ fontSize: 12.5, color: 'var(--ink)', textAlign: 'right', fontWeight: 500 }}>{value || '—'}</span>
  </div>
);

const orderContractPeriod = (order) => {
  const months = order.contractMonths || 12;
  const start = new Date(order.estimatedStart || order.createdAt);
  const end = new Date(start);
  end.setMonth(end.getMonth() + months);
  return { start, end };
};

const ProductContractCard = ({ order, onOpenOrder }) => {
  const [previewDoc, setPreviewDoc] = React.useState(null); // { id, filename }
  const period = orderContractPeriod(order);
  const daysLeft = Math.round((period.end - new Date()) / 86400000);
  const contractLive = order.statusId === 'active' || order.statusId === 'provisioning';
  const expiringSoon = contractLive && daysLeft <= 60 && daysLeft >= 0;
  const expired = contractLive && daysLeft < 0;
  const docs = order.documents || [];
  const getFileUrl = (docId) => {
    const token = localStorage.getItem('sol_auth_token') || '';
    return `/api/orders/${order.id}/documents/${docId}/file?token=${encodeURIComponent(token)}`;
  };

  return (
    <div style={{ border: `1px solid ${expiringSoon || expired ? '#f4c684' : 'var(--line)'}`, borderRadius: 4, overflow: 'hidden' }}>
      {/* Product rows */}
      {(order.items || []).map((it, idx) => (
        <div key={idx} style={{ padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 12, borderBottom: '1px solid var(--line-2)' }}>
          <span style={{ width: 8, height: 8, borderRadius: '50%', background: it.productColor || 'var(--ink-4)', flexShrink: 0 }}/>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ fontWeight: 600, fontSize: 13.5 }}>{it.productName}</span>
              {(expiringSoon || expired) && idx === 0 && (
                <span style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  fontSize: 10, fontWeight: 500, padding: '2px 7px', borderRadius: 999,
                  background: expired ? 'var(--negative-bg)' : '#fef0e0',
                  color: expired ? 'var(--negative)' : '#c26a1d',
                }}>
                  <Icon name="bell" size={10}/>
                  {expired ? 'หมดอายุแล้ว' : <><span className="num">{daysLeft}</span> วัน</>}
                </span>
              )}
            </div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <div className="num" style={{ fontSize: 13, fontWeight: 500 }}>{fmtBaht(order.monthly)}</div>
            <div style={{ fontSize: 10, color: 'var(--ink-3)' }}>/mo</div>
          </div>
        </div>
      ))}

      {/* Contract period row */}
      <div style={{ padding: '10px 14px', background: 'var(--bg-2)', display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span className="eyebrow" style={{ fontSize: 9 }}>สัญญา</span>
          <button onClick={onOpenOrder} className="num" style={{ fontSize: 11.5, color: 'var(--brand)', cursor: 'pointer', fontWeight: 500, background: 'none', border: 'none', padding: 0, fontFamily: 'IBM Plex Mono, monospace' }}>{order.id}</button>
          <span style={{ fontSize: 10, padding: '1px 6px', background: (order.statusColor || '#888') + '18', color: order.statusColor || 'var(--ink-3)', borderRadius: 2, fontWeight: 500 }}>{order.statusLabel}</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span className="eyebrow" style={{ fontSize: 9 }}>ระยะเวลา</span>
          <span className="num" style={{ fontSize: 11.5, color: expired ? 'var(--negative)' : 'var(--ink-2)' }}>{fmtDate(period.start)} → {fmtDate(period.end)}</span>
          <span style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>(<span className="num">{order.contractMonths}</span> เดือน)</span>
        </div>
        <div style={{ flex: 1 }}/>
        {(expiringSoon || expired) && (
          <button onClick={onOpenOrder} style={{
            display: 'inline-flex', alignItems: 'center', gap: 5,
            background: 'var(--brand)', color: '#fff',
            border: 'none', borderRadius: 3, padding: '5px 11px', fontSize: 11, fontFamily: 'Kanit, sans-serif', cursor: 'pointer',
          }}><Icon name="spark" size={11} color="#fff"/> Renew contract</button>
        )}
      </div>

      {/* Documents */}
      {docs.length === 0 ? (
        <div style={{ padding: '10px 14px', fontSize: 11, color: 'var(--ink-4)', borderTop: '1px solid var(--line-2)' }}>
          ยังไม่มีเอกสารแนบ
        </div>
      ) : (
        <div style={{ borderTop: '1px solid var(--line-2)' }}>
          {docs.map((doc) => (
            <div key={doc.id} style={{ padding: '8px 14px', display: 'flex', alignItems: 'center', gap: 10, borderBottom: '1px solid var(--line-2)' }}>
              <Icon name="file" size={13} color="var(--ink-3)"/>
              <span style={{ flex: 1, fontSize: 11.5, color: 'var(--ink-2)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{doc.filename}</span>
              {doc.size && <span style={{ fontSize: 10.5, color: 'var(--ink-4)', flexShrink: 0 }}>{doc.size}</span>}
              <button
                onClick={() => setPreviewDoc(doc)}
                title="Preview"
                style={{
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
                  width: 28, height: 28, borderRadius: 4,
                  background: 'var(--bg-2)', border: '1px solid var(--line)',
                  cursor: 'pointer', color: 'var(--ink-2)',
                }}
              ><Icon name="eye" size={13}/></button>
            </div>
          ))}
        </div>
      )}

      {/* File preview modal */}
      {previewDoc && (
        <div onClick={() => setPreviewDoc(null)} style={{ position: 'fixed', inset: 0, background: 'rgba(20,22,28,0.6)', zIndex: 500, display: 'grid', placeItems: 'center' }}>
          <div onClick={e => e.stopPropagation()} style={{ background: 'var(--panel)', width: 800, maxWidth: '96vw', height: '88vh', display: 'flex', flexDirection: 'column', boxShadow: 'var(--shadow-modal)', borderRadius: 4 }}>
            <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--line)', display: 'flex', alignItems: 'center', gap: 10, flexShrink: 0 }}>
              <Icon name="file" size={15} color="var(--ink-3)"/>
              <span style={{ fontSize: 13, fontWeight: 500, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{previewDoc.filename}</span>
              {previewDoc.hasFile && (
                <a href={getFileUrl(previewDoc.id)} download={previewDoc.filename}
                  style={{ ...custGhostMini, textDecoration: 'none' }}>
                  <Icon name="download" size={11}/> Download
                </a>
              )}
              <button onClick={() => setPreviewDoc(null)} style={{ color: 'var(--ink-3)', background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}>
                <Icon name="close" size={15}/>
              </button>
            </div>
            {previewDoc.hasFile ? (
              <iframe
                src={getFileUrl(previewDoc.id)}
                style={{ flex: 1, border: 'none', background: '#e9e9e6' }}
                title={previewDoc.filename}
              />
            ) : (
              <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 12, color: 'var(--ink-3)' }}>
                <Icon name="file" size={40} color="var(--ink-4)"/>
                <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink-2)' }}>ยังไม่มีไฟล์ที่อัปโหลด</div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>เอกสารนี้ถูกบันทึกชื่อไว้แต่ยังไม่ได้ upload ไฟล์</div>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
};

// ─── Customer detail modal (centered dialog) ──────────────────────────────────

const CustomerDetailModal = ({ customerId, onClose, onOpenOrder, onNewOrder }) => {
  const [data, setData]       = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError]     = React.useState(null);
  const [contactModal, setContactModal] = React.useState(null);
  const [companyModal, setCompanyModal] = React.useState(false);

  React.useEffect(() => {
    if (!customerId) return;
    setLoading(true); setData(null); setError(null);
    window.apiFetch(`/api/customers/${customerId}`)
      .then(r => r.ok ? r.json() : r.json().then(d => Promise.reject(d.error)))
      .then(d => setData(d))
      .catch(e => setError(typeof e === 'string' ? e : 'โหลดข้อมูลไม่ได้'))
      .finally(() => setLoading(false));
  }, [customerId]);

  // Close on Escape
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  const { perms: drawerPerms = {} } = React.useContext(window.PermCtx);
  const canEditCustomer = drawerPerms['Edit customer'] === true;

  const { company, orders = [] } = data || {};
  const contacts = data?.contacts || [];
  const activeMrr = orders.filter(o => o.statusId === 'active').reduce((s, o) => s + o.monthly, 0);
  const activeCount = orders.filter(o => o.statusId === 'active').length;

  const handleCompanySave = (saved) => {
    setData(prev => prev ? { ...prev, company: saved } : prev);
    setCompanyModal(false);
    showToast('อัปเดตข้อมูลบริษัทสำเร็จ', { variant: 'success' });
  };

  const handleContactSave = (saved, isEdit) => {
    setData(prev => {
      if (!prev) return prev;
      let updated;
      if (isEdit) {
        updated = prev.contacts.map(c => c.id === saved.id ? saved : c);
      } else {
        updated = [...prev.contacts, saved];
      }
      // Re-sort: primary first, then by name
      if (saved.isPrimary) {
        updated = updated.map(c => c.id === saved.id ? c : { ...c, isPrimary: false });
      }
      return { ...prev, contacts: updated };
    });
    setContactModal(null);
    showToast(isEdit ? 'อัปเดต contact สำเร็จ' : 'เพิ่ม contact สำเร็จ', { variant: 'success' });
  };

  const totalContract = orders.filter(o => o.statusId !== 'rejected').reduce((s, o) => s + o.monthly * (o.contractMonths || 12), 0);

  return (
    <>
      {/* Centered dialog backdrop */}
      <div onClick={onClose} style={{
        position: 'fixed', inset: 0, background: 'rgba(20,22,28,0.45)',
        zIndex: 300, display: 'grid', placeItems: 'center',
        animation: '__toastIn 140ms ease-out',
      }}>
        <div onClick={e => e.stopPropagation()} style={{
          background: 'var(--panel)', width: 900, maxWidth: '94vw', maxHeight: '90vh',
          display: 'flex', flexDirection: 'column', boxShadow: 'var(--shadow-modal)', borderRadius: 4,
        }}>
          {/* Header */}
          <div style={{ padding: '20px 24px 18px', borderBottom: '1px solid var(--line)', flexShrink: 0 }}>
            {loading ? (
              <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                <div style={{ width: 44, height: 44, borderRadius: 4, background: 'var(--bg-3)' }}/>
                <div style={{ fontSize: 13, color: 'var(--ink-4)' }}>กำลังโหลด…</div>
              </div>
            ) : error ? (
              <div style={{ color: 'var(--negative)', fontSize: 13 }}>{error}</div>
            ) : company && (
              <>
                <div style={{ display: 'flex', alignItems: 'flex-start', gap: 14 }}>
                  <Avatar name={company.name} size={44} square/>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <h2 style={{ fontSize: 19, fontWeight: 600, letterSpacing: '-0.01em', margin: 0 }}>{company.name}</h2>
                      {canEditCustomer && (
                        <button onClick={() => setCompanyModal(true)} title="แก้ไขข้อมูลบริษัท"
                          style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ink-4)', padding: '2px 3px', display: 'flex', lineHeight: 1 }}
                          onMouseEnter={e => e.currentTarget.style.color = 'var(--brand)'}
                          onMouseLeave={e => e.currentTarget.style.color = 'var(--ink-4)'}>
                          <Icon name="edit" size={13}/>
                        </button>
                      )}
                    </div>
                    {company.taxId && (
                      <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 3 }}>
                        TAX <span className="num" style={{ color: 'var(--ink-2)' }}>{company.taxId}</span>
                      </div>
                    )}
                    <div style={{ display: 'flex', gap: 6, marginTop: 10, flexWrap: 'wrap' }}>
                      {[company.sector, company.size, company.province].filter(Boolean).map((t, i) => (
                        <span key={i} style={{ fontSize: 11, padding: '3px 9px', background: 'var(--bg-2)', color: 'var(--ink-2)', borderRadius: 3 }}>{t}</span>
                      ))}
                    </div>
                  </div>
                  <button onClick={onClose} style={{ color: 'var(--ink-3)', background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}>
                    <Icon name="close" size={16}/>
                  </button>
                </div>

                {/* KPI strip */}
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 1, background: 'var(--line)', border: '1px solid var(--line)', borderRadius: 4, overflow: 'hidden', marginTop: 16 }}>
                  <CustKpi label="TOTAL ORDERS" value={<span className="num">{orders.length}</span>}/>
                  <CustKpi label="ACTIVE" value={<span className="num">{activeCount}</span>}/>
                  <CustKpi label="ACTIVE MRR" value={fmtBaht(activeMrr)}/>
                  <CustKpi label="CONTRACT VALUE" value={fmtBaht(totalContract)}/>
                </div>
              </>
            )}
            {!loading && !error && !company && (
              <button onClick={onClose} style={{ color: 'var(--ink-3)', background: 'none', border: 'none', cursor: 'pointer', padding: 4, position: 'absolute', top: 16, right: 16 }}>
                <Icon name="close" size={16}/>
              </button>
            )}
          </div>

          {/* Body — scrollable */}
          {!loading && !error && data && (
            <div style={{ padding: '20px 24px 24px', overflowY: 'auto', flex: 1 }}>
              {/* ── Section 1: Customer information ── */}
              <CustSectionHeader n="1" label="Customer information" th="ข้อมูลลูกค้า"/>

              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.3fr', gap: 16, marginBottom: 28 }}>
                {/* Company info */}
                <div style={{ border: '1px solid var(--line)', borderRadius: 4, overflow: 'hidden' }}>
                  <div style={{ padding: '10px 14px', borderBottom: '1px solid var(--line)', background: 'var(--bg-2)' }}>
                    <div className="eyebrow" style={{ fontSize: 9.5 }}>Company · ข้อมูลบริษัท</div>
                  </div>
                  <div style={{ padding: '10px 14px' }}>
                    <CustDefRow label="ชื่อบริษัท" value={company.name}/>
                    <CustDefRow label="Tax ID" value={<span className="num">{company.taxId}</span>}/>
                    <div style={{ borderTop: '1px solid var(--line-2)', margin: '8px 0 6px' }}/>
                    <CustDefRow label="รายได้รวมต่อเดือน (Active MRR)" value={<span className="num" style={{ color: 'var(--positive)', fontWeight: 500 }}>{fmtBaht(activeMrr)}</span>}/>
                    <CustDefRow label="มูลค่าสัญญารวม (Contract value)" value={<span className="num" style={{ fontWeight: 500 }}>{fmtBaht(totalContract)}</span>}/>
                    <CustDefRow label="Lifetime MRR" value={<span className="num">{fmtBaht(orders.reduce((s, o) => s + o.monthly, 0))}</span>}/>
                  </div>
                </div>

                {/* Contacts */}
                <div style={{ border: '1px solid var(--line)', borderRadius: 4, overflow: 'hidden' }}>
                  <div style={{ padding: '10px 14px', borderBottom: '1px solid var(--line)', background: 'var(--bg-2)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                    <div className="eyebrow" style={{ fontSize: 9.5 }}>Contacts · ผู้ติดต่อทั้งหมด (<span className="num">{contacts.length}</span>)</div>
                    {canEditCustomer && (
                      <button style={custGhostMini} onClick={() => setContactModal({})}>
                        <Icon name="plus" size={10}/> Add
                      </button>
                    )}
                  </div>
                  <div>
                    {contacts.length === 0 ? (
                      <div style={{ padding: '20px 14px', fontSize: 12, color: 'var(--ink-4)', textAlign: 'center' }}>
                        ยังไม่มี contact — กด Add เพื่อเพิ่ม
                      </div>
                    ) : contacts
                      .slice()
                      .sort((a, b) => (b.isPrimary ? 1 : 0) - (a.isPrimary ? 1 : 0))
                      .map((ct, i) => (
                      <div key={ct.id} style={{ padding: '11px 14px', borderBottom: i === contacts.length - 1 ? 'none' : '1px solid var(--line-2)', display: 'flex', gap: 11, alignItems: 'flex-start' }}>
                        <Avatar name={ct.name} size={30}/>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                            <span style={{ fontSize: 12.5, fontWeight: 500 }}>{ct.name}</span>
                            <span style={{ fontSize: 9.5, padding: '1px 6px', borderRadius: 2, background: ct.isPrimary ? 'var(--brand-bg)' : 'var(--bg-3)', color: ct.isPrimary ? 'var(--brand)' : 'var(--ink-3)', fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.05em' }}>
                              {ct.contactType || (ct.isPrimary ? 'Primary' : 'Contact')}
                            </span>
                          </div>
                          {ct.role && <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 1 }}>{ct.role}</div>}
                          <div style={{ display: 'flex', gap: 14, marginTop: 6, flexWrap: 'wrap' }}>
                            {ct.email && <a href={`mailto:${ct.email}`} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--brand)', textDecoration: 'none' }}><Icon name="mail" size={11} color="var(--ink-3)"/>{ct.email}</a>}
                            {(ct.mobile || ct.phone) && <span className="num" style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--ink-2)' }}><Icon name="phone" size={11} color="var(--ink-3)"/>{ct.mobile || ct.phone}</span>}
                          </div>
                        </div>
                        {canEditCustomer && (
                          <button onClick={() => setContactModal({ contact: ct })} title="แก้ไข contact"
                            style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ink-4)', padding: '2px 4px', flexShrink: 0 }}
                            onMouseEnter={e => e.currentTarget.style.color = 'var(--brand)'}
                            onMouseLeave={e => e.currentTarget.style.color = 'var(--ink-4)'}>
                            <Icon name="edit" size={12}/>
                          </button>
                        )}
                      </div>
                    ))}
                  </div>
                </div>
              </div>

              {/* ── Section 2: Product information ── */}
              <CustSectionHeader n="2" label="Product information" th="บริการที่สมัคร · ระยะเวลาสัญญา"
                action={<button style={custGhostMini} onClick={() => { onClose(); onNewOrder(); }}><Icon name="plus" size={10}/> New order</button>}/>

              {orders.filter(o => o.statusId === 'active').length === 0 ? (
                <div style={{ padding: '28px', textAlign: 'center', color: 'var(--ink-3)', fontSize: 12.5, border: '1px dashed var(--line)', borderRadius: 4 }}>
                  ยังไม่มีบริการที่ Active
                </div>
              ) : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                  {orders.filter(o => o.statusId === 'active').map((o) => (
                    <ProductContractCard key={o.id} order={o} onOpenOrder={() => { onClose(); onOpenOrder(o.id); }}/>
                  ))}
                </div>
              )}
            </div>
          )}
        </div>
      </div>

      {companyModal && company && (
        <CompanyFormModal company={company} onSave={handleCompanySave} onClose={() => setCompanyModal(false)}/>
      )}
      {contactModal && (
        <ContactFormModal companyId={company?.id} contact={contactModal.contact || null} onSave={handleContactSave} onClose={() => setContactModal(null)}/>
      )}
    </>
  );
};

const CUSTOMER_COLS = [
  { key: 'name',       label: 'Company',    align: 'left',  sortable: true  },
  { key: 'taxId',      label: 'Tax ID',     align: 'left',  sortable: false },
  { key: 'sector',     label: 'Sector',     align: 'left',  sortable: true  },
  { key: 'size',       label: 'Size',       align: 'left',  sortable: true  },
  { key: 'products',   label: 'Products',   align: 'left',  sortable: false },
  { key: 'orderCount', label: 'Orders',     align: 'right', sortable: true  },
  { key: 'mrr',        label: 'Active MRR', align: 'right', sortable: true  },
  { key: '_action',    label: '',           align: 'right', sortable: false },
];

const CustomersView = ({ onOpen, onNew, initialCustomerId, onClearInitial }) => {
  const [customers, setCustomers] = React.useState([]);
  const [loading, setLoading]     = React.useState(true);
  const [sort, setSort]           = React.useState({ col: 'name', dir: 'asc' });
  const [selectedId, setSelectedId] = React.useState(initialCustomerId || null);
  const [page, setPage]           = React.useState(1);
  const [perPage, setPerPage]     = React.useState(10);

  // Open drawer immediately when arriving from search
  React.useEffect(() => {
    if (initialCustomerId) {
      setSelectedId(initialCustomerId);
      onClearInitial?.();
    }
  }, [initialCustomerId]);

  React.useEffect(() => {
    setLoading(true);
    window.apiFetch('/api/customers')
      .then(r => r.ok ? r.json() : Promise.reject())
      .then(data => {
        setCustomers(data);
        // Keep window.COMPANIES in sync for global search
        window.COMPANIES = data.map(c => ({ id: c.id, name: c.name, taxId: c.taxId, sector: c.sector, size: c.size, province: c.province }));
      })
      .catch(() => {})
      .finally(() => setLoading(false));
  }, []);

  const handleSort = (col) => {
    setPage(1);
    setSort(prev =>
      prev.col === col
        ? { col, dir: prev.dir === 'asc' ? 'desc' : 'asc' }
        : { col, dir: 'asc' }
    );
  };

  const sorted = React.useMemo(() => {
    const { col, dir } = sort;
    return [...customers].sort((a, b) => {
      const av = a[col] ?? '', bv = b[col] ?? '';
      const cmp = typeof av === 'string' ? av.localeCompare(bv, 'th') : av - bv;
      return dir === 'asc' ? cmp : -cmp;
    });
  }, [customers, sort]);

  const totalPages = Math.max(1, Math.ceil(sorted.length / perPage));
  const safePage   = Math.min(page, totalPages);
  const paged      = sorted.slice((safePage - 1) * perPage, safePage * perPage);

  const SortIcon = ({ col }) => {
    if (sort.col !== col) return (
      <span style={{ opacity: 0.25, marginLeft: 4, fontSize: 9 }}>↕</span>
    );
    return (
      <span style={{ marginLeft: 4, fontSize: 9, color: 'var(--brand)' }}>
        {sort.dir === 'asc' ? '↑' : '↓'}
      </span>
    );
  };

  return (
    <>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 18 }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: 6 }}>Solutions · Customers</div>
          <h1 style={{ fontSize: 22, fontWeight: 500, letterSpacing: '-0.01em', margin: 0 }}>ลูกค้ากลุ่มธุรกิจ</h1>
          <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4 }}>
            {loading
              ? 'กำลังโหลด…'
              : <><span className="num">{customers.length}</span> companies registered</>}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <Button variant="ghost" icon="download">Export</Button>
          <Button variant="primary" icon="plus" onClick={() => onNew()}>New order</Button>
        </div>
      </div>

      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4, overflow: 'hidden' }}>
        {loading ? (
          <div style={{ padding: '48px 0', textAlign: 'center', color: 'var(--ink-4)', fontSize: 13 }}>
            กำลังโหลดข้อมูลลูกค้า…
          </div>
        ) : customers.length === 0 ? (
          <div style={{ padding: '48px 0', textAlign: 'center', color: 'var(--ink-4)', fontSize: 13 }}>
            ยังไม่มีข้อมูลลูกค้า
          </div>
        ) : (
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5 }}>
            <thead>
              <tr style={{ background: 'var(--bg-2)' }}>
                {CUSTOMER_COLS.map(col => (
                  <th key={col.key}
                    className="eyebrow"
                    onClick={col.sortable ? () => handleSort(col.key) : undefined}
                    style={{
                      padding: '10px',
                      textAlign: col.align,
                      fontWeight: 500,
                      borderBottom: '1px solid var(--line)',
                      cursor: col.sortable ? 'pointer' : 'default',
                      userSelect: 'none',
                      whiteSpace: 'nowrap',
                      color: sort.col === col.key ? 'var(--brand)' : undefined,
                    }}>
                    {col.label}
                    {col.sortable && <SortIcon col={col.key}/>}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {paged.map((c, i) => (
                <tr key={c.id}
                  onClick={() => setSelectedId(c.id)}
                  style={{
                    borderBottom: i === paged.length - 1 ? 'none' : '1px solid var(--line-2)',
                    cursor: 'pointer', transition: 'background 120ms',
                    background: selectedId === c.id ? 'var(--bg-hover)' : 'transparent',
                  }}
                  onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-hover)'}
                  onMouseLeave={e => e.currentTarget.style.background = selectedId === c.id ? 'var(--bg-hover)' : 'transparent'}>
                  <td style={{ padding: '12px 10px' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <Avatar name={c.name} size={28} square/>
                      <div>
                        <div style={{ fontWeight: 500 }}>{c.name}</div>
                        <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{c.province}</div>
                      </div>
                    </div>
                  </td>
                  <td className="num" style={{ padding: '12px 10px', color: 'var(--ink-2)', fontSize: 11.5 }}>{c.taxId || '—'}</td>
                  <td style={{ padding: '12px 10px', color: 'var(--ink-2)' }}>{c.sector || '—'}</td>
                  <td className="num" style={{ padding: '12px 10px', color: 'var(--ink-2)' }}>{c.size || '—'}</td>
                  <td style={{ padding: '12px 10px' }}>
                    <div style={{ display: 'flex', gap: 4 }}>
                      {(c.products || []).map(pid => {
                        const p = (window.PRODUCTS || []).find(x => x.id === pid);
                        if (!p) return null;
                        return <span key={pid} title={p.name} style={{ width: 7, height: 7, borderRadius: '50%', background: p.color }}/>;
                      })}
                      {(c.products || []).length === 0 && <span style={{ fontSize: 11, color: 'var(--ink-4)' }}>—</span>}
                    </div>
                  </td>
                  <td className="num" style={{ padding: '12px 10px', textAlign: 'right', fontWeight: 500 }}>
                    {c.orderCount}
                    <span style={{ fontSize: 10.5, color: 'var(--ink-3)', marginLeft: 3, fontWeight: 400 }}>({c.activeCount} active)</span>
                  </td>
                  <td className="num" style={{ padding: '12px 10px', textAlign: 'right', fontWeight: 500 }}>{fmtBaht(c.mrr)}</td>
                  <td style={{ padding: '12px 10px', textAlign: 'right', color: 'var(--ink-3)' }}>
                    <Icon name="chevron" size={12}/>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      {/* Pagination bar */}
      {!loading && sorted.length > 0 && (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 14, padding: '0 2px' }}>
          {/* Left: per-page selector + count */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>แสดง</span>
            {[10, 20, 50].map(n => (
              <button key={n} onClick={() => { setPerPage(n); setPage(1); }} style={{
                padding: '3px 10px', fontSize: 11.5, borderRadius: 3, cursor: 'pointer',
                border: '1px solid var(--line)',
                background: perPage === n ? 'var(--ink)' : 'var(--panel)',
                color: perPage === n ? '#fff' : 'var(--ink-2)',
                fontFamily: 'IBM Plex Mono, monospace',
                fontWeight: perPage === n ? 600 : 400,
              }}>{n}</button>
            ))}
            <span style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>
              รายการ &nbsp;·&nbsp; <span className="num">{(safePage - 1) * perPage + 1}</span>–<span className="num">{Math.min(safePage * perPage, sorted.length)}</span> จาก <span className="num">{sorted.length}</span>
            </span>
          </div>

          {/* Right: prev / page numbers / next */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
            <button onClick={() => setPage(p => Math.max(1, p - 1))} disabled={safePage === 1} style={{
              width: 28, height: 28, borderRadius: 3, border: '1px solid var(--line)',
              background: 'var(--panel)', cursor: safePage === 1 ? 'default' : 'pointer',
              opacity: safePage === 1 ? 0.35 : 1, display: 'grid', placeItems: 'center',
            }}><Icon name="chevron" size={11} style={{ transform: 'rotate(180deg)' }}/></button>

            {(() => {
              const pages = [];
              const delta = 1;
              for (let p = 1; p <= totalPages; p++) {
                if (p === 1 || p === totalPages || (p >= safePage - delta && p <= safePage + delta)) {
                  pages.push(p);
                } else if (pages[pages.length - 1] !== '…') {
                  pages.push('…');
                }
              }
              return pages.map((p, i) => p === '…' ? (
                <span key={'e' + i} style={{ width: 28, textAlign: 'center', fontSize: 12, color: 'var(--ink-4)' }}>…</span>
              ) : (
                <button key={p} onClick={() => setPage(p)} style={{
                  width: 28, height: 28, borderRadius: 3, border: '1px solid var(--line)',
                  background: safePage === p ? 'var(--ink)' : 'var(--panel)',
                  color: safePage === p ? '#fff' : 'var(--ink-2)',
                  cursor: 'pointer', fontSize: 12, fontFamily: 'IBM Plex Mono, monospace',
                  fontWeight: safePage === p ? 600 : 400,
                }}>{p}</button>
              ));
            })()}

            <button onClick={() => setPage(p => Math.min(totalPages, p + 1))} disabled={safePage === totalPages} style={{
              width: 28, height: 28, borderRadius: 3, border: '1px solid var(--line)',
              background: 'var(--panel)', cursor: safePage === totalPages ? 'default' : 'pointer',
              opacity: safePage === totalPages ? 0.35 : 1, display: 'grid', placeItems: 'center',
            }}><Icon name="chevron" size={11}/></button>
          </div>
        </div>
      )}

      {selectedId && (
        <CustomerDetailModal
          customerId={selectedId}
          onClose={() => setSelectedId(null)}
          onOpenOrder={(id) => { setSelectedId(null); onOpen(id); }}
          onNewOrder={() => onNew()}
        />
      )}

    </>
  );
};

Object.assign(window, { CatalogView, CustomersView });
