// Customers screen — list, drawer (4 tabs), add/edit modal, bulk
const { useState: cuState, useMemo: cuMemo, useRef: cuRef, useEffect: cuEffect } = React;

// ---------- Reference data ----------
const CUST_TYPES = ['company', 'government', 'retailer', 'individual', 'other'];
const CUST_STATUSES = ['active', 'inactive', 'suspended', 'prospect'];
const CUST_TIERS = ['A', 'B', 'C'];
const PAYMENT_TERMS = ['COD', 'NET15', 'NET30', 'NET45'];

// Common Thai provinces (commercially active subset — keeps dropdown manageable)
const TH_PROVINCES = [
  { th: 'กรุงเทพมหานคร',     en: 'Bangkok' },
  { th: 'นนทบุรี',           en: 'Nonthaburi' },
  { th: 'ปทุมธานี',          en: 'Pathum Thani' },
  { th: 'สมุทรปราการ',       en: 'Samut Prakan' },
  { th: 'สมุทรสาคร',         en: 'Samut Sakhon' },
  { th: 'นครปฐม',            en: 'Nakhon Pathom' },
  { th: 'ชลบุรี',            en: 'Chon Buri' },
  { th: 'ระยอง',             en: 'Rayong' },
  { th: 'ฉะเชิงเทรา',        en: 'Chachoengsao' },
  { th: 'พระนครศรีอยุธยา',   en: 'Phra Nakhon Si Ayutthaya' },
  { th: 'เชียงใหม่',         en: 'Chiang Mai' },
  { th: 'เชียงราย',          en: 'Chiang Rai' },
  { th: 'ลำพูน',             en: 'Lamphun' },
  { th: 'ขอนแก่น',           en: 'Khon Kaen' },
  { th: 'นครราชสีมา',        en: 'Nakhon Ratchasima' },
  { th: 'อุบลราชธานี',       en: 'Ubon Ratchathani' },
  { th: 'อุดรธานี',          en: 'Udon Thani' },
  { th: 'สงขลา',             en: 'Songkhla' },
  { th: 'ภูเก็ต',            en: 'Phuket' },
  { th: 'สุราษฎร์ธานี',      en: 'Surat Thani' },
  { th: 'นครศรีธรรมราช',     en: 'Nakhon Si Thammarat' },
  { th: 'เพชรบุรี',          en: 'Phetchaburi' },
  { th: 'ประจวบคีรีขันธ์',   en: 'Prachuap Khiri Khan' }
];

// ---------- Helpers ----------
function custDisplayName(c, lang) {
  if (lang === 'th') return c.nameTh || c.rawName || c.code;
  return c.nameEn || c.nameTh || c.rawName || c.code;
}
function tierColorClass(tier) {
  if (tier === 'A') return 'cust-tier cust-tier-A';
  if (tier === 'B') return 'cust-tier cust-tier-B';
  return 'cust-tier cust-tier-C';
}
function statusChipClass(status) {
  return 'pill cust-pill-' + status;
}
function fmtTaxId(s) {
  const d = (s || '').replace(/\D/g, '').slice(0, 13);
  if (d.length <= 1) return d;
  if (d.length <= 5) return d.slice(0,1) + ' ' + d.slice(1);
  if (d.length <= 10) return d.slice(0,1) + ' ' + d.slice(1,5) + ' ' + d.slice(5);
  if (d.length <= 12) return d.slice(0,1) + ' ' + d.slice(1,5) + ' ' + d.slice(5,10) + ' ' + d.slice(10);
  return d.slice(0,1) + ' ' + d.slice(1,5) + ' ' + d.slice(5,10) + ' ' + d.slice(10,12) + ' ' + d.slice(12);
}
function isValidTaxId(s) {
  return /^\d{13}$/.test((s || '').replace(/\D/g, ''));
}
function suggestTier(rev) {
  if (rev >= 400000) return 'A';
  if (rev >= 80000) return 'B';
  return 'C';
}
function matchesCustomer(customerRawName, lineCustomer) {
  if (!customerRawName || !lineCustomer) return false;
  const a = customerRawName.replace(/\(.*$/u, '').trim().toLowerCase();
  const b = lineCustomer.replace(/\(.*$/u, '').trim().toLowerCase();
  if (!a || !b) return false;
  const len = Math.min(20, Math.min(a.length, b.length));
  return a.slice(0, len) === b.slice(0, len);
}

// ---------- Top screen ----------
function CustomersScreen({ t, lang, role, density }) {
  const { state, dispatch } = useStore();
  const toast = useToast();
  const customers = state.customers;
  const reps = state.reps || [];

  const [query, setQuery] = cuState('');
  const [statusFilter, setStatusFilter] = cuState('all');
  const [tierFilter, setTierFilter] = cuState('all');
  const [typeFilter, setTypeFilter] = cuState('all');
  const [repFilter, setRepFilter] = cuState('all');
  const [sortKey, setSortKey] = cuState('revenue');
  const [sortDir, setSortDir] = cuState('desc');
  const [selected, setSelected] = cuState(new Set());
  const [drawerId, setDrawerId] = cuState(null);
  const [modal, setModal] = cuState(null); // { mode: 'add' } | { mode: 'edit', customer }
  const [confirmDelete, setConfirmDelete] = cuState(null);

  const canManage = canRoleDo(role, 'customer_manage');
  const canDelete = canRoleDo(role, 'customer_delete');

  const filtered = cuMemo(() => {
    const q = query.trim().toLowerCase();
    let list = customers.filter(c => {
      if (q) {
        const hay = (c.nameTh + ' ' + c.nameEn + ' ' + c.rawName + ' ' + c.code + ' ' + c.shortName + ' ' + (c.taxId||'')).toLowerCase();
        if (!hay.includes(q)) return false;
      }
      if (statusFilter !== 'all' && c.status !== statusFilter) return false;
      if (tierFilter !== 'all' && c.tier !== tierFilter) return false;
      if (typeFilter !== 'all' && c.type !== typeFilter) return false;
      if (repFilter !== 'all' && !(c.salesReps || []).includes(repFilter)) return false;
      return true;
    });
    list.sort((a, b) => {
      let av, bv;
      if (sortKey === 'name') {
        av = custDisplayName(a, lang).toLowerCase();
        bv = custDisplayName(b, lang).toLowerCase();
        return sortDir === 'asc' ? av.localeCompare(bv) : bv.localeCompare(av);
      }
      if (sortKey === 'lastDate') {
        av = a.lastDate || '';
        bv = b.lastDate || '';
        return sortDir === 'asc' ? av.localeCompare(bv) : bv.localeCompare(av);
      }
      av = a[sortKey] || 0;
      bv = b[sortKey] || 0;
      return sortDir === 'asc' ? (av - bv) : (bv - av);
    });
    return list;
  }, [customers, query, statusFilter, tierFilter, typeFilter, repFilter, sortKey, sortDir, lang]);

  const activeCount = customers.filter(c => c.status === 'active').length;
  const totalRevenue = customers.reduce((s, c) => s + (c.revenue || 0), 0);
  const unclaimedCount = customers.filter(c => !c.claimed).length;

  const liveDrawer = drawerId ? customers.find(c => c.id === drawerId) : null;

  function toggleSelect(id) {
    const s = new Set(selected);
    if (s.has(id)) s.delete(id); else s.add(id);
    setSelected(s);
  }
  function selectAll() {
    if (selected.size === filtered.length) setSelected(new Set());
    else setSelected(new Set(filtered.map(c => c.id)));
  }
  function clearFilters() {
    setQuery(''); setStatusFilter('all'); setTierFilter('all'); setTypeFilter('all'); setRepFilter('all');
  }
  function bulkSetStatus(status) {
    const ids = [...selected];
    dispatch({ type: 'BULK_UPDATE_CUSTOMERS', ids, patch: { status } });
    toast(t.cust_toast_updated);
    setSelected(new Set());
  }
  function bulkSetRep(repCode) {
    const ids = [...selected];
    dispatch({ type: 'BULK_UPDATE_CUSTOMERS', ids, patch: { assignedRep: repCode } });
    toast(t.cust_toast_updated);
    setSelected(new Set());
  }

  const filtersActive = query || statusFilter !== 'all' || tierFilter !== 'all' || typeFilter !== 'all' || repFilter !== 'all';

  return (
    <div className="page" style={{ paddingTop: 20 }}>
      <div className="page-head">
        <div>
          <h1>{t.cust_title}</h1>
          <div className="page-sub">
            {t.cust_sub} · {fmtThousands(customers.length)} {t.items}
            {unclaimedCount > 0 && (
              <> · <span style={{ color: 'var(--warn)' }}>{fmtThousands(unclaimedCount)} {t.cust_unclaimed}</span></>
            )}
          </div>
        </div>
        <div className="page-head-actions">
          {canRoleDo(role, 'stock_export') && (
            <ExportButton
              t={t}
              filename={'ckw_customers_' + new Date().toISOString().slice(0,10)}
              sheetName="Customers"
              getData={() => ({
                headers: ['Code','Name (TH)','Name (EN)','Tax ID','Type','Tier','Status','Rep','Phone','Email','Province','Terms','Credit','Invoices','Revenue','Last order'],
                rows: filtered.map(c => [
                  c.code, c.nameTh || c.rawName, c.nameEn, c.taxId, c.type, c.tier, c.status,
                  c.assignedRep, c.phone, c.email, c.province, c.paymentTerms, c.creditLimit,
                  c.invoiceCount, c.revenue, c.lastDate
                ])
              })}
            />
          )}
          {canManage ? (
            <button className="btn btn-primary" onClick={() => setModal({ mode: 'add' })}>
              <Icon.Plus className="icon icon-sm" /> {t.cust_add}
            </button>
          ) : (
            <span className="permission-note">
              <Icon.Lock className="icon icon-sm" /> {t.admin_manager_only}
            </span>
          )}
        </div>
      </div>

      {/* Quick KPIs */}
      <div className="grid grid-4" style={{ marginBottom: 18 }}>
        <CustKpi
          label={t.cust_total}
          value={fmtThousands(customers.length)}
          sub={`${fmtThousands(activeCount)} ${t.cust_active.toLowerCase()}`}
          icon={<Icon.User />}
        />
        <CustKpi
          label={t.cust_revenue_period}
          value={fmtCurrency(totalRevenue)}
          sub={t.kpi_value_unit + ' · ' + t.cust_period_label}
          icon={<Icon.Trend />}
          accent="ok"
        />
        <CustKpi
          label="Tier A"
          value={fmtThousands(customers.filter(c => c.tier === 'A').length)}
          sub={lang === 'th' ? 'ลูกค้ามูลค่าสูง' : 'High-value accounts'}
          icon={<Icon.Sparkle />}
          accent="warn"
        />
        <CustKpi
          label={t.cust_unclaimed}
          value={fmtThousands(unclaimedCount)}
          sub={t.cust_unclaimed_hint}
          icon={<Icon.AlertCircle />}
          accent={unclaimedCount > 0 ? 'warn' : 'ok'}
        />
      </div>

      {/* Toolbar */}
      <div className="card" style={{ overflow: 'hidden' }}>
        <div className="toolbar">
          <div className="search" style={{ width: 300 }}>
            <Icon.Search className="icon icon-sm" />
            <input value={query} onChange={e => setQuery(e.target.value)} placeholder={t.cust_search_ph} />
            {query && <button className="btn-ghost" onClick={() => setQuery('')} style={{ padding: 0 }}><Icon.X className="icon icon-sm" /></button>}
          </div>
          <CustFilterChips
            options={[
              { key: 'all', label: t.filter_all },
              ...CUST_STATUSES.map(s => ({ key: s, label: t['cust_status_' + s] }))
            ]}
            value={statusFilter}
            onChange={setStatusFilter}
          />
          <span className="spacer"></span>
          <CustDropdown
            label={tierFilter === 'all' ? t.cust_filter_tier : 'Tier ' + tierFilter}
            options={[{ key:'all', label: t.filter_all }, ...CUST_TIERS.map(c => ({ key: c, label: 'Tier ' + c }))]}
            value={tierFilter}
            onChange={setTierFilter}
          />
          <CustDropdown
            label={typeFilter === 'all' ? t.cust_filter_type : t['cust_type_' + typeFilter]}
            options={[{ key:'all', label: t.filter_all }, ...CUST_TYPES.map(c => ({ key: c, label: t['cust_type_' + c] }))]}
            value={typeFilter}
            onChange={setTypeFilter}
          />
          <CustDropdown
            label={repFilter === 'all' ? t.cust_filter_rep : repFilter}
            options={[{ key:'all', label: t.filter_all }, ...reps.map(r => ({ key: r.code, label: r.code + ' · ' + r.name }))]}
            value={repFilter}
            onChange={setRepFilter}
          />
          <CustDropdown
            label={
              (sortKey === 'revenue' ? t.cust_sort_revenue :
               sortKey === 'name'    ? t.cust_sort_name    :
               sortKey === 'lastDate'? t.cust_sort_last    :
                                       t.cust_sort_invoices)
            }
            options={[
              { key: 'revenue',  label: t.cust_sort_revenue },
              { key: 'name',     label: t.cust_sort_name, dir: 'asc' },
              { key: 'lastDate', label: t.cust_sort_last },
              { key: 'invoiceCount', label: t.cust_sort_invoices }
            ]}
            value={sortKey}
            onChange={(v, opt) => { setSortKey(v); setSortDir(opt && opt.dir ? opt.dir : 'desc'); }}
          />
          {filtersActive && (
            <button className="btn btn-ghost" onClick={clearFilters}><Icon.X className="icon icon-sm" />{t.filter_clear}</button>
          )}
        </div>

        {selected.size > 0 && (
          <div className="bulk-bar">
            <Icon.Check className="icon icon-sm" />
            <span>{t.selected_count.replace('{n}', selected.size)}</span>
            <span className="spacer"></span>
            <CustBulkMenu
              label={t.cust_bulk_status}
              icon={<Icon.Sparkle className="icon icon-sm" />}
              options={CUST_STATUSES.map(s => ({ key: s, label: t['cust_status_' + s] }))}
              onPick={bulkSetStatus}
            />
            <CustBulkMenu
              label={t.cust_bulk_rep}
              icon={<Icon.User className="icon icon-sm" />}
              options={reps.map(r => ({ key: r.code, label: r.code + ' · ' + r.name }))}
              onPick={bulkSetRep}
            />
            <button className="btn btn-ghost" onClick={() => setSelected(new Set())}>{t.bulk_clear}</button>
          </div>
        )}

        <div style={{ overflowX: 'auto', maxHeight: 'calc(100vh - 420px)', overflowY: 'auto' }}>
          <table className="tbl">
            <thead>
              <tr>
                <th style={{ width: 36 }}>
                  <input
                    type="checkbox"
                    className="checkbox"
                    checked={selected.size > 0 && selected.size === filtered.length}
                    ref={el => { if (el) el.indeterminate = selected.size > 0 && selected.size < filtered.length; }}
                    onChange={selectAll}
                  />
                </th>
                <th>{t.cust_col_customer}</th>
                <th>{t.cust_col_type}</th>
                <th>{t.cust_col_tier}</th>
                <th>{t.cust_col_status}</th>
                <th>{t.cust_col_rep}</th>
                <th className="num">{t.cust_col_invoices}</th>
                <th className="num">{t.cust_col_revenue}</th>
                <th>{t.cust_col_last}</th>
                <th style={{ width: 60 }}></th>
              </tr>
            </thead>
            <tbody>
              {filtered.length === 0 && (
                <tr><td colSpan={10}>
                  <div className="empty">
                    <div className="empty-icon"><Icon.User /></div>
                    <h3>{filtersActive ? t.no_results : t.cust_empty_title}</h3>
                    <div>{filtersActive ? t.no_results_sub : t.cust_empty_sub}</div>
                  </div>
                </td></tr>
              )}
              {filtered.slice(0, 200).map(c => (
                <CustomerRow
                  key={c.id}
                  c={c}
                  t={t}
                  lang={lang}
                  reps={reps}
                  selected={selected.has(c.id)}
                  canManage={canManage}
                  canDelete={canDelete}
                  onToggleSelect={() => toggleSelect(c.id)}
                  onOpenDrawer={() => setDrawerId(c.id)}
                  onEdit={() => setModal({ mode: 'edit', customer: c })}
                  onDelete={() => setConfirmDelete({ ids: [c.id] })}
                />
              ))}
              {filtered.length > 200 && (
                <tr><td colSpan={10} style={{ textAlign: 'center', color: 'var(--ink-3)' }}>
                  {lang === 'th'
                    ? `แสดง 200 จาก ${filtered.length} รายการ — ใช้ตัวกรองเพื่อค้นหาเพิ่มเติม`
                    : `Showing 200 of ${filtered.length} — use filters to narrow down`}
                </td></tr>
              )}
            </tbody>
          </table>
        </div>
      </div>

      {liveDrawer && (
        <CustomerDrawer
          key={liveDrawer.id}
          c={liveDrawer}
          t={t}
          lang={lang}
          role={role}
          canManage={canManage}
          canDelete={canDelete}
          reps={reps}
          onClose={() => setDrawerId(null)}
          onEdit={() => setModal({ mode: 'edit', customer: liveDrawer })}
          onDelete={() => setConfirmDelete({ ids: [liveDrawer.id] })}
          onUpdate={(patch, activity) => dispatch({
            type: 'UPDATE_CUSTOMER', id: liveDrawer.id, patch, activity
          })}
        />
      )}

      {modal && (
        <CustomerModal
          mode={modal.mode}
          customer={modal.customer}
          t={t}
          lang={lang}
          reps={reps}
          existingCount={customers.length}
          onClose={() => setModal(null)}
          onSave={(payload, isClaim) => {
            if (modal.mode === 'add') {
              dispatch({ type: 'ADD_CUSTOMER', customer: payload });
              toast(t.cust_toast_added);
            } else {
              dispatch({
                type: 'UPDATE_CUSTOMER',
                id: modal.customer.id,
                patch: payload,
                activity: { kind: isClaim ? 'claimed' : 'updated', actor: 'me',
                  th: isClaim ? t.cust_activity_claimed : t.cust_activity_updated,
                  en: isClaim ? 'Customer details confirmed' : 'Customer record updated' }
              });
              toast(isClaim ? t.cust_toast_claimed : t.cust_toast_updated);
            }
            setModal(null);
          }}
        />
      )}

      {confirmDelete && (
        <ConfirmModal
          t={t}
          title={t.confirm_delete_title}
          body={`${t.confirm_delete_body} (${confirmDelete.ids.length} ${t.items})`}
          onClose={() => setConfirmDelete(null)}
          onConfirm={() => {
            dispatch({ type: 'DELETE_CUSTOMERS', ids: confirmDelete.ids });
            if (confirmDelete.ids.includes(drawerId)) setDrawerId(null);
            setConfirmDelete(null);
            toast(t.cust_toast_deleted);
          }}
        />
      )}
    </div>
  );
}

// ---------- KPI tile (small variant) ----------
function CustKpi({ label, value, sub, icon, accent }) {
  const accentMap = {
    ok: { bg: 'var(--ok-soft)', fg: 'var(--ok)' },
    warn: { bg: 'var(--warn-soft)', fg: 'var(--warn)' },
    bad: { bg: 'var(--bad-soft)', fg: 'var(--bad)' },
    info: { bg: 'var(--info-soft)', fg: 'var(--info)' }
  };
  const c = accentMap[accent] || { bg: 'var(--accent-soft)', fg: 'var(--accent)' };
  return (
    <div className="kpi">
      <div className="kpi-icon" style={{ background: c.bg, color: c.fg }}>{icon}</div>
      <div className="kpi-label">{label}</div>
      <div className="kpi-value">{value}</div>
      <div className="kpi-sub">{sub}</div>
    </div>
  );
}

// ---------- Row ----------
function CustomerRow({ c, t, lang, reps, selected, canManage, canDelete, onToggleSelect, onOpenDrawer, onEdit, onDelete }) {
  const [menuOpen, setMenuOpen] = cuState(false);
  const menuRef = cuRef();
  useOutsideClick(menuRef, () => setMenuOpen(false));
  const repObj = reps.find(r => r.code === c.assignedRep);
  const repLabel = repObj ? repObj.name : (c.assignedRep || '—');
  const display = custDisplayName(c, lang);
  return (
    <tr className={selected ? 'selected' : ''}>
      <td onClick={e => e.stopPropagation()}>
        <input type="checkbox" className="checkbox" checked={selected} onChange={onToggleSelect} />
      </td>
      <td onClick={onOpenDrawer} style={{ maxWidth: 380 }}>
        <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
          <div className={"cust-avatar tier-" + c.tier}>{(display || '?').trim().charAt(0).toUpperCase()}</div>
          <div style={{ minWidth: 0, flex: 1 }}>
            <div style={{ fontWeight: 600, display: 'flex', gap: 8, alignItems: 'center' }}>
              <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 240 }}>{display}</span>
              {!c.claimed && (
                <span className="chip cust-chip-unclaimed" title={t.cust_unclaimed_hint}>
                  <Icon.AlertCircle className="icon icon-sm" /> {t.cust_unclaimed}
                </span>
              )}
            </div>
            <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginTop: 2 }}>
              <span className="mono t-muted" style={{ fontSize: 11.5 }}>{c.code}</span>
              {c.shortName && c.shortName !== display && (
                <span className="t-muted" style={{ fontSize: 11.5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 180 }}>
                  · {c.shortName}
                </span>
              )}
            </div>
          </div>
        </div>
      </td>
      <td onClick={onOpenDrawer}>
        <span className="chip">{t['cust_type_' + c.type] || c.type}</span>
      </td>
      <td onClick={onOpenDrawer}><span className={tierColorClass(c.tier)}>{c.tier}</span></td>
      <td onClick={onOpenDrawer}><span className={statusChipClass(c.status)}>{t['cust_status_' + c.status]}</span></td>
      <td onClick={onOpenDrawer} style={{ maxWidth: 160, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
        <span className="cust-rep-chip">
          <span className="cust-rep-dot"></span>{repLabel}
        </span>
      </td>
      <td className="num" onClick={onOpenDrawer}>
        <div style={{ fontWeight: 600 }}>{fmtThousands(c.invoiceCount)}</div>
        {c.soCount !== c.invoiceCount && <div className="t-muted" style={{ fontSize: 11 }}>SO {c.soCount}</div>}
      </td>
      <td className="num" onClick={onOpenDrawer}>
        <div style={{ fontWeight: 700 }}>{fmtCurrency(c.revenue)}</div>
        <div className="t-muted" style={{ fontSize: 11 }}>฿ · {t.cust_period_label}</div>
      </td>
      <td onClick={onOpenDrawer}>
        {c.lastDate ? (
          <>
            <div>{fmtDate(c.lastDate, lang)}</div>
            <div className="t-muted" style={{ fontSize: 11 }}>{daysSince(c.lastDate)} {t.days_ago}</div>
          </>
        ) : <span className="t-muted">—</span>}
      </td>
      <td onClick={e => e.stopPropagation()} style={{ position: 'relative' }}>
        <div ref={menuRef}>
          <button className="btn-icon btn-ghost" onClick={() => setMenuOpen(o => !o)}>
            <Icon.More className="icon icon-sm" />
          </button>
          {menuOpen && (
            <div className="menu" style={{ right: 8, top: 40 }}>
              <button onClick={() => { onOpenDrawer(); setMenuOpen(false); }}>
                <Icon.Eye className="icon icon-sm" />{t.action_view}
              </button>
              {canManage && (
                <button onClick={() => { onEdit(); setMenuOpen(false); }}>
                  <Icon.Edit className="icon icon-sm" />{t.action_edit}
                </button>
              )}
              {canDelete && (
                <>
                  <div className="sep"></div>
                  <button onClick={() => { onDelete(); setMenuOpen(false); }} style={{ color: 'var(--bad)' }}>
                    <Icon.Trash className="icon icon-sm" />{t.cust_delete}
                  </button>
                </>
              )}
            </div>
          )}
        </div>
      </td>
    </tr>
  );
}

// ---------- Filter / Bulk helpers ----------
function CustFilterChips({ options, value, onChange }) {
  return (
    <div className="segmented">
      {options.map(o => (
        <button key={o.key} className={value === o.key ? 'active' : ''} onClick={() => onChange(o.key)}>{o.label}</button>
      ))}
    </div>
  );
}
function CustDropdown({ label, options, value, onChange }) {
  const [open, setOpen] = cuState(false);
  const ref = cuRef();
  useOutsideClick(ref, () => setOpen(false));
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button className="btn" onClick={() => setOpen(o => !o)}>
        {label} <Icon.ArrowDown className="icon icon-sm" />
      </button>
      {open && (
        <div className="menu" style={{ top: 44, right: 0, minWidth: 200, maxHeight: 320, overflowY: 'auto' }}>
          {options.map(o => (
            <button key={o.key} onClick={() => { onChange(o.key, o); setOpen(false); }}>
              {value === o.key ? <Icon.Check className="icon icon-sm" /> : <span style={{ width: 16 }}></span>}
              <span>{o.label}</span>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}
function CustBulkMenu({ label, icon, options, onPick }) {
  const [open, setOpen] = cuState(false);
  const ref = cuRef();
  useOutsideClick(ref, () => setOpen(false));
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button className="btn btn-ghost" onClick={() => setOpen(o => !o)}>
        {icon} {label} <Icon.ArrowDown className="icon icon-sm" />
      </button>
      {open && (
        <div className="menu" style={{ top: 40, right: 0, minWidth: 220, maxHeight: 300, overflowY: 'auto' }}>
          {options.map(o => (
            <button key={o.key} onClick={() => { onPick(o.key); setOpen(false); }}>{o.label}</button>
          ))}
        </div>
      )}
    </div>
  );
}

// ---------- Customer Drawer ----------
function CustomerDrawer({ c, t, lang, role, canManage, canDelete, reps, onClose, onEdit, onDelete, onUpdate }) {
  const [tab, setTab] = cuState('overview');
  const { state } = useStore();
  const toast = useToast();

  const display = custDisplayName(c, lang);
  const repObj = reps.find(r => r.code === c.assignedRep);
  const aov = c.invoiceCount > 0 ? c.revenue / c.invoiceCount : 0;
  const recencyDays = c.lastDate ? daysSince(c.lastDate) : null;

  // Build per-customer order history from seed.recentLines (grouped by invoice)
  const recentLines = (window.CKW_SEED && window.CKW_SEED.recentLines) || [];
  const myLines = cuMemo(() =>
    recentLines.filter(l => matchesCustomer(c.rawName, l.customer)),
  [c.rawName]);

  const invoices = cuMemo(() => {
    const m = new Map();
    myLines.forEach(l => {
      if (!m.has(l.invoice)) m.set(l.invoice, { invoice: l.invoice, date: l.date, rep: l.rep, lines: [], amount: 0 });
      const entry = m.get(l.invoice);
      entry.lines.push(l);
      // Synthesize amount: qty × unitCost from product table when possible
      const prod = state.products.find(p => p.sku === l.sku);
      const unit = prod ? prod.avgPrice || prod.unitCost || 0 : 0;
      entry.amount += (l.qty || 0) * unit;
    });
    return [...m.values()].sort((a, b) => (b.date || '').localeCompare(a.date || ''));
  }, [myLines, state.products]);

  const productsBought = cuMemo(() => {
    const m = new Map();
    myLines.forEach(l => {
      const key = l.sku;
      if (!m.has(key)) m.set(key, { sku: l.sku, name: l.name, qty: 0, unit: l.unit, invoices: 0, revenue: 0 });
      const e = m.get(key);
      e.qty += l.qty || 0;
      e.invoices += 1;
      const prod = state.products.find(p => p.sku === l.sku);
      const unit = prod ? prod.avgPrice || prod.unitCost || 0 : 0;
      e.revenue += (l.qty || 0) * unit;
    });
    return [...m.values()].sort((a, b) => b.revenue - a.revenue);
  }, [myLines, state.products]);

  const [notesDraft, setNotesDraft] = cuState(c.notes || '');
  const notesDirty = notesDraft !== (c.notes || '');
  function saveNotes() {
    onUpdate({ notes: notesDraft }, { kind: 'updated', actor: 'me', th: 'แก้ไขบันทึก', en: 'Notes updated' });
    toast(t.cust_toast_updated);
  }

  return (
    <>
      <div className="drawer-backdrop" onClick={onClose}></div>
      <div className="drawer cust-drawer">
        <div className="drawer-header">
          <div className={"cust-avatar tier-" + c.tier} style={{ width: 44, height: 44, fontSize: 17 }}>
            {(display || '?').trim().charAt(0).toUpperCase()}
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <h2 style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{display}</h2>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 4, flexWrap: 'wrap' }}>
              <span className="mono t-muted" style={{ fontSize: 12.5 }}>{c.code}</span>
              <span className={tierColorClass(c.tier)}>Tier {c.tier}</span>
              <span className={statusChipClass(c.status)}>{t['cust_status_' + c.status]}</span>
              <span className="chip">{t['cust_type_' + c.type] || c.type}</span>
            </div>
          </div>
          {canManage && (
            <button className="btn-icon btn-ghost" title={t.cust_edit} onClick={onEdit}>
              <Icon.Edit className="icon" />
            </button>
          )}
          <button className="btn-icon btn-ghost" onClick={onClose}><Icon.X className="icon" /></button>
        </div>

        <div className="tabs">
          <button className={tab === 'overview' ? 'active' : ''} onClick={() => setTab('overview')}>{t.cust_tab_overview}</button>
          <button className={tab === 'orders' ? 'active' : ''} onClick={() => setTab('orders')}>{t.cust_tab_orders} ({invoices.length})</button>
          <button className={tab === 'products' ? 'active' : ''} onClick={() => setTab('products')}>{t.cust_tab_products} ({productsBought.length})</button>
          <button className={tab === 'notes' ? 'active' : ''} onClick={() => setTab('notes')}>{t.cust_tab_notes}</button>
        </div>

        <div className="drawer-body">
          {tab === 'overview' && (
            <div style={{ display: 'grid', gap: 16 }}>
              {!c.claimed && canManage && (
                <div className="alert warn">
                  <div className="icon-circle"><Icon.AlertCircle /></div>
                  <div style={{ flex: 1 }}>
                    <div className="alert-title">{t.cust_unclaimed}</div>
                    <div className="alert-body">{t.cust_unclaimed_hint}</div>
                  </div>
                  <button className="btn btn-primary" onClick={onEdit} style={{ alignSelf: 'center' }}>
                    {t.cust_claim}
                  </button>
                </div>
              )}

              {/* KPIs */}
              <div className="cust-kpi-grid">
                <CustDrawerKpi label={t.cust_kpi_revenue} value={fmtCurrency(c.revenue)} unit="฿" sub={t.cust_period_label} accent="ok" />
                <CustDrawerKpi label={t.cust_kpi_invoices} value={fmtThousands(c.invoiceCount)} sub={c.soCount && c.soCount !== c.invoiceCount ? `SO: ${c.soCount}` : ''} />
                <CustDrawerKpi label={t.cust_kpi_aov} value={fmtCurrency(aov)} unit="฿" />
                <CustDrawerKpi
                  label={t.cust_kpi_recency}
                  value={recencyDays != null ? fmtThousands(recencyDays) : '—'}
                  unit={recencyDays != null ? t.cust_kpi_days : ''}
                  sub={c.lastDate ? fmtDate(c.lastDate, lang) : t.never}
                  accent={recencyDays != null && recencyDays > 60 ? 'warn' : 'info'}
                />
              </div>

              {/* Identity */}
              <DrawerSection title={t.cust_sec_identity}>
                <CustField label={t.cust_f_code}>
                  <span className="mono">{c.code}</span>
                </CustField>
                <CustField label={t.cust_f_tax}>
                  {c.taxId ? (
                    <span className="mono" style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                      {fmtTaxId(c.taxId)}
                      {isValidTaxId(c.taxId) && <Icon.Check className="icon icon-sm" style={{ color: 'var(--ok)' }} />}
                    </span>
                  ) : <span className="t-muted">—</span>}
                </CustField>
                <CustField label={t.cust_f_name_th}>{c.nameTh || <span className="t-muted">—</span>}</CustField>
                <CustField label={t.cust_f_name_en}>{c.nameEn || <span className="t-muted">—</span>}</CustField>
                <CustField label={t.cust_f_short}>{c.shortName || <span className="t-muted">—</span>}</CustField>
                <CustField label={t.cust_f_rep}>
                  {repObj ? (
                    <span className="cust-rep-chip">
                      <span className="cust-rep-dot"></span>{repObj.name}
                      <span className="t-muted mono" style={{ marginLeft: 6, fontSize: 11 }}>{repObj.code}</span>
                    </span>
                  ) : <span className="t-muted">—</span>}
                </CustField>
              </DrawerSection>

              {/* All involved reps from history */}
              {c.salesReps && c.salesReps.length > 1 && (
                <DrawerSection title={lang === 'th' ? 'พนักงานขายที่เคยดูแล' : 'Reps who dealt with this customer'}>
                  <div style={{ gridColumn: '1 / -1', display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                    {c.salesReps.map(code => {
                      const r = reps.find(x => x.code === code);
                      return (
                        <span key={code} className="cust-rep-chip">
                          <span className="cust-rep-dot"></span>
                          {r ? r.name : code}
                          <span className="t-muted mono" style={{ marginLeft: 6, fontSize: 11 }}>{code}</span>
                        </span>
                      );
                    })}
                  </div>
                </DrawerSection>
              )}

              {/* Contact */}
              <DrawerSection title={t.cust_sec_contact}>
                <CustField label={t.cust_f_contact}>{c.contactPerson || <span className="t-muted">—</span>}</CustField>
                <CustField label={t.cust_f_phone}>
                  {c.phone ? <span className="mono">{c.phone}</span> : <span className="t-muted">—</span>}
                </CustField>
                <CustField label={t.cust_f_email} span={2}>
                  {c.email ? <a href={`mailto:${c.email}`} style={{ color: 'var(--accent-strong)' }}>{c.email}</a> : <span className="t-muted">—</span>}
                </CustField>
                <CustField label={t.cust_f_address} span={2}>
                  {c.address ? <div style={{ whiteSpace: 'pre-wrap' }}>{c.address}</div> : <span className="t-muted">—</span>}
                </CustField>
                <CustField label={t.cust_f_province}>{c.province || <span className="t-muted">—</span>}</CustField>
              </DrawerSection>

              {/* Finance */}
              <DrawerSection title={t.cust_sec_finance}>
                <CustField label={t.cust_f_terms}>
                  <span className={"chip " + (c.paymentTerms === 'COD' ? 'chip-warn' : 'chip-info')}>{c.paymentTerms}</span>
                </CustField>
                <CustField label={t.cust_f_credit}>
                  {c.creditLimit > 0
                    ? <span style={{ fontWeight: 600 }}>{fmtCurrency(c.creditLimit)} <span className="t-muted" style={{ fontSize: 12 }}>฿</span></span>
                    : <span className="chip">{lang === 'th' ? 'เงินสดเท่านั้น' : 'Cash only'}</span>}
                </CustField>
              </DrawerSection>
            </div>
          )}

          {tab === 'orders' && (
            invoices.length === 0 ? (
              <div className="empty">
                <div className="empty-icon"><Icon.Clock /></div>
                <h3>{t.cust_no_orders}</h3>
                <div>{lang === 'th' ? 'ลูกค้ารายนี้ยังไม่มีใบกำกับในเดือนนี้' : 'No invoices recorded for this customer'}</div>
              </div>
            ) : (
              <div className="card" style={{ overflow: 'hidden' }}>
                <div style={{ padding: '10px 14px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 10, background: 'var(--surface-2)' }}>
                  <Icon.InfoCircle className="icon icon-sm" style={{ color: 'var(--ink-3)' }} />
                  <span className="t-muted" style={{ fontSize: 12.5 }}>
                    {lang === 'th' ? 'อ้างอิงจากการเคลื่อนไหว ' : 'Sourced from movement records · '}
                    {fmtThousands(myLines.length)} {lang === 'th' ? 'รายการสินค้า' : 'line items'} · {invoices.length} {lang === 'th' ? 'ใบกำกับ' : 'invoices'}
                  </span>
                </div>
                {invoices.map((inv, i) => {
                  const rObj = reps.find(r => r.code === (inv.rep || '').split(' ')[0]);
                  return (
                    <div key={inv.invoice + i} className="cust-order-row">
                      <div className="cust-order-icon"><Icon.Receive className="icon icon-sm" /></div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                          <span className="mono" style={{ fontWeight: 600 }}>{inv.invoice}</span>
                          <span className="chip" style={{ fontSize: 11 }}>{inv.lines.length} {lang === 'th' ? 'รายการ' : 'lines'}</span>
                        </div>
                        <div className="t-muted" style={{ fontSize: 12, marginTop: 3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                          {rObj ? rObj.name : (inv.rep || '—')}
                        </div>
                      </div>
                      <div style={{ textAlign: 'right' }}>
                        <div style={{ fontWeight: 700 }}>{fmtCurrency(inv.amount)} <span className="t-muted" style={{ fontSize: 11 }}>฿</span></div>
                        <div className="t-muted" style={{ fontSize: 11 }}>{fmtDate(inv.date, lang)}</div>
                      </div>
                    </div>
                  );
                })}
              </div>
            )
          )}

          {tab === 'products' && (
            productsBought.length === 0 ? (
              <div className="empty">
                <div className="empty-icon"><Icon.Box /></div>
                <h3>{t.cust_no_products}</h3>
              </div>
            ) : (
              <div className="card" style={{ overflow: 'hidden' }}>
                <table className="tbl">
                  <thead>
                    <tr>
                      <th>{t.col_sku}</th>
                      <th>{t.col_name}</th>
                      <th className="num">{t.col_qty}</th>
                      <th className="num">{t.cust_col_revenue}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {productsBought.map(p => (
                      <tr key={p.sku} style={{ cursor: 'default' }}>
                        <td className="mono">{p.sku}</td>
                        <td style={{ maxWidth: 240, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                          {p.name}
                        </td>
                        <td className="num">
                          <div style={{ fontWeight: 600 }}>{fmtThousands(p.qty)}</div>
                          <div className="t-muted" style={{ fontSize: 11 }}>{p.unit}</div>
                        </td>
                        <td className="num">
                          <div style={{ fontWeight: 600 }}>{fmtCurrency(p.revenue)}</div>
                          <div className="t-muted" style={{ fontSize: 11 }}>{p.invoices} {lang === 'th' ? 'ใบ' : 'inv'}</div>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )
          )}

          {tab === 'notes' && (
            <div style={{ display: 'grid', gap: 16 }}>
              <div>
                <div className="kpi-label" style={{ marginBottom: 8 }}>
                  {t.cust_f_notes}
                  <span className="t-muted" style={{ fontWeight: 400, marginLeft: 6 }}>· {t.cust_f_notes_help}</span>
                </div>
                <textarea
                  className="textarea"
                  rows={6}
                  value={notesDraft}
                  onChange={e => setNotesDraft(e.target.value)}
                  placeholder={lang === 'th' ? 'เช่น ลูกค้าเก่า โอนผ่านธนาคาร, แจ้งซื้อทุกเดือนต้นเดือน...' : 'e.g. Long-time customer, prefers bank transfer, orders early each month...'}
                  disabled={!canManage}
                />
                {notesDirty && canManage && (
                  <div className="row" style={{ marginTop: 8, justifyContent: 'flex-end', gap: 8 }}>
                    <button className="btn" onClick={() => setNotesDraft(c.notes || '')}>{t.cancel}</button>
                    <button className="btn btn-primary" onClick={saveNotes}>{t.save}</button>
                  </div>
                )}
              </div>

              <DrawerSection title={lang === 'th' ? 'ประวัติกิจกรรม' : 'Activity log'}>
                <div style={{ gridColumn: '1 / -1' }}>
                  {(c.activity && c.activity.length > 0) ? c.activity.map((a, i) => (
                    <div key={i} className="cust-activity-row">
                      <div className={"cust-activity-dot kind-" + a.kind}></div>
                      <div style={{ flex: 1 }}>
                        <div style={{ fontSize: 13.5, fontWeight: 500 }}>{lang === 'th' ? a.th : a.en}</div>
                        <div className="t-muted" style={{ fontSize: 11.5, marginTop: 2 }}>
                          {fmtDate(a.date, lang)} · {a.actor || 'system'}
                        </div>
                      </div>
                    </div>
                  )) : <div className="t-muted" style={{ fontSize: 13 }}>—</div>}
                </div>
              </DrawerSection>
            </div>
          )}
        </div>

        <div className="drawer-foot">
          {canDelete && tab === 'overview' && (
            <button className="btn btn-danger" onClick={onDelete}><Icon.Trash className="icon icon-sm" /> {t.cust_delete}</button>
          )}
          <span className="spacer"></span>
          <button className="btn" onClick={onClose}>{t.close}</button>
          {canManage && tab === 'overview' && (
            <button className="btn btn-primary" onClick={onEdit}>
              <Icon.Edit className="icon icon-sm" /> {t.cust_edit}
            </button>
          )}
        </div>
      </div>
    </>
  );
}

function CustDrawerKpi({ label, value, unit, sub, accent }) {
  const accentMap = {
    ok: 'var(--ok)', warn: 'var(--warn)', info: 'var(--info)'
  };
  const valColor = accentMap[accent] || 'var(--ink)';
  return (
    <div className="cust-kpi-tile">
      <div className="kpi-label" style={{ fontSize: 11.5 }}>{label}</div>
      <div style={{ fontSize: 22, fontWeight: 700, marginTop: 4, color: valColor, lineHeight: 1.1, fontVariantNumeric: 'tabular-nums' }}>
        {value}
        {unit && <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink-3)', marginLeft: 4 }}>{unit}</span>}
      </div>
      {sub && <div className="t-muted" style={{ fontSize: 11.5, marginTop: 4 }}>{sub}</div>}
    </div>
  );
}

function DrawerSection({ title, children }) {
  return (
    <div className="card">
      <div className="card-header" style={{ padding: '12px 16px' }}>
        <h2 style={{ fontSize: 13, textTransform: 'uppercase', letterSpacing: '.04em', color: 'var(--ink-3)', fontWeight: 700 }}>{title}</h2>
      </div>
      <div className="cust-grid-2col">
        {children}
      </div>
    </div>
  );
}

function CustField({ label, children, span }) {
  return (
    <div style={{ gridColumn: span === 2 ? '1 / -1' : 'auto' }}>
      <div className="kpi-label" style={{ marginBottom: 4, fontSize: 11.5 }}>{label}</div>
      <div style={{ fontSize: 14, color: 'var(--ink)' }}>{children}</div>
    </div>
  );
}

// ---------- Customer Add / Edit modal ----------
function CustomerModal({ mode, customer, t, lang, reps, existingCount, onClose, onSave }) {
  const isEdit = mode === 'edit';
  const startCode = isEdit ? customer.code : ('CUS-' + String(existingCount + 1).padStart(3, '0'));

  const [form, setForm] = cuState({
    code: startCode,
    nameTh: (customer && customer.nameTh) || '',
    nameEn: (customer && customer.nameEn) || '',
    shortName: (customer && customer.shortName) || '',
    taxId: (customer && customer.taxId) || '',
    type: (customer && customer.type) || 'company',
    tier: (customer && customer.tier) || 'C',
    status: (customer && customer.status) || 'prospect',
    assignedRep: (customer && customer.assignedRep) || '',
    contactPerson: (customer && customer.contactPerson) || '',
    phone: (customer && customer.phone) || '',
    email: (customer && customer.email) || '',
    address: (customer && customer.address) || '',
    province: (customer && customer.province) || '',
    paymentTerms: (customer && customer.paymentTerms) || 'COD',
    creditLimit: (customer && customer.creditLimit) || 0,
    notes: (customer && customer.notes) || ''
  });
  const [errors, setErrors] = cuState({});
  const [tierOverridden, setTierOverridden] = cuState(false);

  const suggestedTier = isEdit ? suggestTier(customer.revenue || 0) : suggestTier(0);
  const taxClean = (form.taxId || '').replace(/\D/g, '');
  const taxOk = taxClean.length === 13;
  const taxPartial = taxClean.length > 0 && !taxOk;

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

  function submit() {
    const errs = {};
    if (!form.nameTh.trim()) errs.nameTh = t.required;
    if (form.taxId && !taxOk) errs.taxId = t.cust_f_tax_invalid;
    if (Number(form.creditLimit) < 0) errs.creditLimit = lang === 'th' ? 'ต้องไม่ติดลบ' : 'Must be ≥ 0';
    setErrors(errs);
    if (Object.keys(errs).length) return;

    const payload = {
      ...form,
      taxId: taxClean,
      creditLimit: Number(form.creditLimit) || 0,
      shortName: form.shortName || form.nameTh.slice(0, 28)
    };
    if (!isEdit) {
      // Brand new customer — fill the metric fields with zeros
      const c = {
        id: form.code,
        ...payload,
        rawName: form.nameTh,
        invoiceCount: 0,
        soCount: 0,
        revenue: 0,
        firstDate: null,
        lastDate: null,
        salesReps: form.assignedRep ? [form.assignedRep] : [],
        activity: [{
          date: new Date().toISOString().slice(0,10),
          kind: 'created', actor: 'me',
          th: lang === 'th' ? 'สร้างลูกค้าใหม่' : 'Customer created',
          en: 'Customer created'
        }],
        claimed: !!(payload.nameTh && taxOk)
      };
      onSave(c, false);
    } else {
      // Edit path — claim if going from no-taxid to valid taxid
      const wasClaim = !customer.claimed && payload.nameTh && taxOk;
      onSave(payload, wasClaim);
    }
  }

  return (
    <>
      <div className="modal-backdrop" onClick={onClose}></div>
      <div className="modal cust-modal">
        <div className="modal-header">
          {isEdit ? <Icon.Edit className="icon" style={{ color: 'var(--accent)' }} /> : <Icon.Plus className="icon" style={{ color: 'var(--accent)' }} />}
          <h2>{isEdit ? t.cust_edit : t.cust_add}</h2>
          <span className="mono t-muted" style={{ marginLeft: 6, fontSize: 13 }}>{form.code}</span>
          <span className="spacer"></span>
          <button className="btn-icon btn-ghost" onClick={onClose}><Icon.X className="icon" /></button>
        </div>

        <div className="modal-body">
          {/* Identity */}
          <div className="cust-modal-section">
            <div className="cust-modal-section-head">
              <div className="cust-section-num">1</div>
              <div>
                <div className="cust-section-title">{t.cust_sec_identity}</div>
                <div className="t-muted" style={{ fontSize: 12, marginTop: 2 }}>
                  {lang === 'th' ? 'ระบุชื่อจริงและเลขผู้เสียภาษีเพื่อใช้ออกใบกำกับ' : 'Real legal name + tax ID for VAT invoicing'}
                </div>
              </div>
            </div>

            <div className="cust-form-grid">
              <div className="field">
                <label>{t.cust_f_code}</label>
                <input className="input mono" value={form.code} readOnly disabled style={{ background: 'var(--surface-2)' }} />
                <div className="field-help">{t.cust_f_code_help}</div>
              </div>
              <div className="field">
                <label>
                  {t.cust_f_tax}
                  {taxOk && <span className="chip chip-ok" style={{ marginLeft: 8 }}><Icon.Check className="icon icon-sm" />{t.cust_f_tax_ok}</span>}
                  {taxPartial && <span className="t-muted" style={{ marginLeft: 8, fontSize: 11 }}>{taxClean.length}/13</span>}
                </label>
                <input
                  className={"input mono " + (errors.taxId ? 'input-err' : '')}
                  value={fmtTaxId(form.taxId)}
                  onChange={e => set('taxId', e.target.value)}
                  placeholder="0 0000 00000 00 0"
                  inputMode="numeric"
                />
                {errors.taxId
                  ? <div className="field-error">{errors.taxId}</div>
                  : <div className="field-help">{t.cust_f_tax_help}</div>}
              </div>

              <div className="field">
                <label>{t.cust_f_name_th} <span style={{ color: 'var(--bad)' }}>*</span></label>
                <input
                  className={"input " + (errors.nameTh ? 'input-err' : '')}
                  value={form.nameTh}
                  onChange={e => set('nameTh', e.target.value)}
                  placeholder={lang === 'th' ? 'เช่น บริษัท จักรวาล จำกัด' : 'e.g. บริษัท จักรวาล จำกัด'}
                />
                {errors.nameTh && <div className="field-error">{errors.nameTh}</div>}
              </div>
              <div className="field">
                <label>{t.cust_f_name_en}</label>
                <input
                  className="input"
                  value={form.nameEn}
                  onChange={e => set('nameEn', e.target.value)}
                  placeholder="e.g. Chakawal Co., Ltd."
                />
              </div>

              <div className="field">
                <label>{t.cust_f_short}</label>
                <input
                  className="input"
                  value={form.shortName}
                  onChange={e => set('shortName', e.target.value)}
                  placeholder={lang === 'th' ? 'เช่น จักรวาล' : 'e.g. Chakawal'}
                  maxLength={32}
                />
                <div className="field-help">{t.cust_f_short_help}</div>
              </div>
              <div className="field">
                <label>{t.cust_f_type}</label>
                <select className="select" value={form.type} onChange={e => set('type', e.target.value)}>
                  {CUST_TYPES.map(ty => <option key={ty} value={ty}>{t['cust_type_' + ty]}</option>)}
                </select>
              </div>

              <div className="field">
                <label>
                  {t.cust_f_tier}
                  {isEdit && !tierOverridden && (
                    <span className="t-muted" style={{ marginLeft: 8, fontSize: 11 }}>
                      ({t.cust_f_tier_auto}: {suggestedTier})
                    </span>
                  )}
                </label>
                <div className="segmented" style={{ width: 'fit-content' }}>
                  {CUST_TIERS.map(ti => (
                    <button
                      key={ti}
                      type="button"
                      className={form.tier === ti ? 'active' : ''}
                      onClick={() => { set('tier', ti); setTierOverridden(true); }}
                    >
                      Tier {ti}
                    </button>
                  ))}
                </div>
              </div>
              <div className="field">
                <label>{t.cust_f_status}</label>
                <select className="select" value={form.status} onChange={e => set('status', e.target.value)}>
                  {CUST_STATUSES.map(s => <option key={s} value={s}>{t['cust_status_' + s]}</option>)}
                </select>
              </div>

              <div className="field" style={{ gridColumn: '1 / -1' }}>
                <label>{t.cust_f_rep}</label>
                <select className="select" value={form.assignedRep} onChange={e => set('assignedRep', e.target.value)}>
                  <option value="">— {t.none} —</option>
                  {reps.map(r => <option key={r.code} value={r.code}>{r.code} · {r.name}</option>)}
                </select>
              </div>
            </div>
          </div>

          {/* Contact */}
          <div className="cust-modal-section">
            <div className="cust-modal-section-head">
              <div className="cust-section-num">2</div>
              <div>
                <div className="cust-section-title">{t.cust_sec_contact}</div>
                <div className="t-muted" style={{ fontSize: 12, marginTop: 2 }}>
                  {lang === 'th' ? 'ผู้ติดต่อ ที่อยู่สำหรับวางบิล และข้อมูลติดต่อ' : 'Primary contact, billing address, and contact info'}
                </div>
              </div>
            </div>

            <div className="cust-form-grid">
              <div className="field">
                <label>{t.cust_f_contact}</label>
                <input className="input" value={form.contactPerson} onChange={e => set('contactPerson', e.target.value)} placeholder={lang === 'th' ? 'เช่น คุณสมศรี' : 'e.g. K. Somsri'} />
              </div>
              <div className="field">
                <label>{t.cust_f_phone}</label>
                <input className="input mono" value={form.phone} onChange={e => set('phone', e.target.value)} placeholder="0X-XXX-XXXX" />
              </div>

              <div className="field" style={{ gridColumn: '1 / -1' }}>
                <label>{t.cust_f_email}</label>
                <input className="input" type="email" value={form.email} onChange={e => set('email', e.target.value)} placeholder="contact@company.co.th" />
              </div>

              <div className="field" style={{ gridColumn: '1 / -1' }}>
                <label>{t.cust_f_address}</label>
                <textarea
                  className="textarea"
                  rows={3}
                  value={form.address}
                  onChange={e => set('address', e.target.value)}
                  placeholder={lang === 'th' ? 'เลขที่ ถนน แขวง/ตำบล เขต/อำเภอ จังหวัด รหัสไปรษณีย์' : 'No., Street, Sub-district, District, Province, Postal Code'}
                />
              </div>

              <div className="field">
                <label>{t.cust_f_province}</label>
                <select className="select" value={form.province} onChange={e => set('province', e.target.value)}>
                  <option value="">— {t.none} —</option>
                  {TH_PROVINCES.map(p => (
                    <option key={p.th} value={lang === 'th' ? p.th : p.en}>{lang === 'th' ? p.th : p.en}</option>
                  ))}
                </select>
              </div>
              <div></div>
            </div>
          </div>

          {/* Finance */}
          <div className="cust-modal-section">
            <div className="cust-modal-section-head">
              <div className="cust-section-num">3</div>
              <div>
                <div className="cust-section-title">{t.cust_sec_finance}</div>
                <div className="t-muted" style={{ fontSize: 12, marginTop: 2 }}>
                  {lang === 'th' ? 'เงื่อนไขการชำระเงินและวงเงินเครดิต' : 'Payment terms and credit limit'}
                </div>
              </div>
            </div>

            <div className="cust-form-grid">
              <div className="field">
                <label>{t.cust_f_terms}</label>
                <div className="segmented" style={{ width: 'fit-content' }}>
                  {PAYMENT_TERMS.map(pt => (
                    <button
                      key={pt}
                      type="button"
                      className={form.paymentTerms === pt ? 'active' : ''}
                      onClick={() => set('paymentTerms', pt)}
                    >
                      {pt}
                    </button>
                  ))}
                </div>
              </div>
              <div className="field">
                <label>{t.cust_f_credit}</label>
                <input
                  className={"input num " + (errors.creditLimit ? 'input-err' : '')}
                  type="number"
                  value={form.creditLimit}
                  onChange={e => set('creditLimit', e.target.value)}
                  min={0}
                  step={1000}
                />
                {errors.creditLimit
                  ? <div className="field-error">{errors.creditLimit}</div>
                  : <div className="field-help">{t.cust_f_credit_help}</div>}
              </div>

              <div className="field" style={{ gridColumn: '1 / -1' }}>
                <label>{t.cust_f_notes}</label>
                <textarea
                  className="textarea"
                  rows={3}
                  value={form.notes}
                  onChange={e => set('notes', e.target.value)}
                  placeholder={lang === 'th' ? 'บันทึกภายในสำหรับทีมขาย เช่น เงื่อนไขพิเศษ ส่วนลด ฯลฯ' : 'Internal note for the sales team — special terms, discounts, etc.'}
                />
                <div className="field-help">{t.cust_f_notes_help}</div>
              </div>
            </div>
          </div>
        </div>

        <div className="modal-foot">
          <button className="btn" onClick={onClose}>{t.cancel}</button>
          <button className="btn btn-primary" onClick={submit}>
            <Icon.Check className="icon icon-sm" />
            {isEdit && !customer.claimed ? t.cust_save_claim : t.save}
          </button>
        </div>
      </div>
    </>
  );
}

window.CustomersScreen = CustomersScreen;