// CRM interno (v1): ambiente à parte para completar e corrigir dados comerciais em profundidade.
// Cada campo de contato nas outras telas tem um lápis que abre aqui o registro certo (go('crm',{id})).
// Regra de integridade: dado público (Receita/PNCP) nunca é sobrescrito; o que é digitado aqui fica separado, rotulado "Manual", com autor e data.
function crmMissing(p) {
  const m = (p.profile && p.profile.manual_contact) || {};
  const out = [];
  if (!p.phone && !m.phone) out.push('Sem telefone');
  if (!p.email && !m.email) out.push('Sem e-mail');
  if (!(typeof pdFmtAddress === 'function' && pdFmtAddress(p)) && !m.address) out.push('Sem endereço');
  return out;
}
const crmFmtPhone = v => (typeof pdFmtPhone === 'function' ? pdFmtPhone(v) : v);

function CrmManualContactForm({ p, onSaved }) {
  const { Input, Button, Alert } = window.VRticeDesignSystem_d763eb;
  const { toast } = useShell();
  const m = (p.profile && p.profile.manual_contact) || {};
  const [f, setF] = React.useState({ phone: crmFmtPhone(m.phone || ''), phone2: crmFmtPhone(m.phone2 || ''), email: m.email || '', address: m.address || '', note: m.note || '' });
  const [busy, setBusy] = React.useState(false);
  const set = k => e => setF(o => ({ ...o, [k]: e.target.value }));
  const save = async () => {
    setBusy(true);
    try { await window.VxSalesIntelligence.setManualContact(p.id, f); toast('Contato e endereço salvos'); onSaved && onSaved(); }
    catch (e) { toast(e.message || 'Falha ao salvar', 'ph-warning'); }
    setBusy(false);
  };
  return <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
    <div style={{ display: 'flex', gap: 24, flexWrap: 'wrap' }}>
      <div style={{ flex: '1 1 260px', display: 'flex', flexDirection: 'column', gap: 4 }}>
        <span style={vxEyebrow}>DADO PÚBLICO (RECEITA FEDERAL) · SOMENTE LEITURA</span>
        <span style={{ fontSize: 14 }}>Telefone: {p.phone ? crmFmtPhone(p.phone) : '—'}{p.phone2 ? ' · ' + crmFmtPhone(p.phone2) : ''}</span>
        <span style={{ fontSize: 14 }}>E-mail: {p.email || '—'}</span>
        <span style={{ fontSize: 14 }}>Endereço: {(typeof pdFmtAddress === 'function' && pdFmtAddress(p)) || '—'}</span>
        <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{typeof pdContactNote === 'function' ? pdContactNote(p) : ''}</span>
      </div>
    </div>
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(220px,1fr))', gap: 14 }}>
      <Input label="Telefone (manual)" value={f.phone} onChange={set('phone')} placeholder="(11) 98888-7777" />
      <Input label="Telefone 2 (manual)" value={f.phone2} onChange={set('phone2')} placeholder="(11) 3333-4444" />
      <Input label="E-mail (manual)" value={f.email} onChange={set('email')} placeholder="contato@empresa.com.br" />
    </div>
    <Input label="Endereço (manual)" value={f.address} onChange={set('address')} placeholder="Rua, número, bairro, cidade/UF, CEP" />
    <Input label="Observação (origem da informação)" value={f.note} onChange={set('note')} placeholder="Ex.: informado pelo comprador em ligação de 12/10" />
    <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
      <PBtn perm="commercial_intelligence.edit" icon="ph-floppy-disk" onClick={save} disabled={busy}>{busy ? 'Salvando…' : 'Salvar contato e endereço'}</PBtn>
      <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>Fica marcado como “Manual”, com data e autor. Deixe em branco e salve para remover.</span>
    </div>
  </div>;
}

const crmBrl = n => Number(n || 0).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL', maximumFractionDigits: 0 });
const crmDate = v => (v ? new Date(v).toLocaleDateString('pt-BR') : '—');

function CrmRelationship({ p, details, onChanged }) {
  const { Button, Select, Input } = window.VRticeDesignSystem_d763eb;
  const { toast } = useShell();
  const R = window.VxSalesIntelligence;
  const [notes, setNotes] = React.useState(p.notes || '');
  const [busy, setBusy] = React.useState(false);
  const saveNotes = async () => { setBusy(true); try { await R.setNotes(p.id, notes); toast('Anotações salvas'); } catch (e) { toast(e.message || 'Falha ao salvar', 'ph-warning'); } setBusy(false); };
  const log = async type => { try { await R.activity(p.id, type, type === 'CALL' ? 'Ligação' : type === 'EMAIL' ? 'E-mail' : 'Reunião'); toast('Atividade registrada'); onChanged && onChanged(); } catch (e) { toast(e.message || 'Falha ao registrar', 'ph-warning'); } };
  return <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
    <div><span style={vxEyebrow}>ESTÁGIO</span>
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 10 }}>{R.STAGES.map(st => <PBtn perm="commercial_intelligence.edit" key={st[0]} size="sm" variant={st[0] === p.stage ? 'tonal' : 'ghost'} onClick={() => R.stage(p.id, st[0]).then(() => toast('Estágio: ' + st[1]), err => toast(err.message || 'Falha ao alterar o estágio', 'ph-warning'))}>{st[1]}</PBtn>)}</div></div>
    <div style={{ maxWidth: 320 }}><Select label="Responsável" options={p.owner ? ['Sem responsável', p.owner] : ['Sem responsável']} value={p.owner || 'Sem responsável'} onChange={e => R.assign(p.id, e.target.value === 'Sem responsável' ? null : e.target.value).then(() => toast('Responsável atualizado'), err => toast(err.message || 'Falha ao atualizar o responsável', 'ph-warning'))} /></div>
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      <label style={vxEyebrow} htmlFor="crm-notes">ANOTAÇÕES</label>
      <textarea id="crm-notes" value={notes} onChange={e => setNotes(e.target.value)} rows={5} placeholder="Quem decide, objeções, histórico de conversa…" style={{ resize: 'vertical', padding: 12, borderRadius: 12, border: '1px solid var(--border-field)', background: 'var(--surface-field, transparent)', color: 'var(--text-primary)', fontFamily: 'inherit', fontSize: 14 }} />
      <div><PBtn perm="commercial_intelligence.edit" variant="secondary" icon="ph-floppy-disk" onClick={saveNotes} disabled={busy}>{busy ? 'Salvando…' : 'Salvar anotações'}</PBtn></div>
    </div>
    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
      <PBtn perm="commercial_intelligence.edit" variant="secondary" icon="ph-phone-call" onClick={() => log('CALL')}>Registrar ligação</PBtn>
      <PBtn perm="commercial_intelligence.edit" variant="secondary" icon="ph-envelope-simple" onClick={() => log('EMAIL')}>Registrar e-mail</PBtn>
      <PBtn perm="commercial_intelligence.edit" variant="secondary" icon="ph-calendar-check" onClick={() => log('MEETING')}>Registrar reunião</PBtn>
    </div>
  </div>;
}

const crmMonthLabel = m => { const [y, mo] = String(m).slice(0, 7).split('-'); return ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'][Number(mo) - 1] + '/' + y.slice(2); };

// Faturamento mensal informado (nota fiscal, balanço, base de crédito, manual). Dado separado do valor público do PNCP.
function CrmRevenueForm({ p }) {
  const { Input, Select, Button } = window.VRticeDesignSystem_d763eb;
  const { toast } = useShell();
  const V = window.VxSalesIntelligence;
  const months = React.useMemo(() => { const out = [], d = new Date(); for (let i = 0; i < 12; i++) { const t = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() - i, 1)); out.push(t.toISOString().slice(0, 7)); } return out; }, []);
  const [rows, setRows] = React.useState(null), [err, setErr] = React.useState('');
  const [f, setF] = React.useState({ month: months[0], amount: '', source: 'MANUAL', evidence: '' });
  const [busy, setBusy] = React.useState(false);
  const reload = () => V.listRevenue(p.id).then(r => { setRows(r); setErr(''); }).catch(e => { setRows([]); setErr(e.message || 'Falha ao carregar'); });
  React.useEffect(() => { reload(); }, [p.id]);
  const srcName = k => (V.REV_SOURCES.find(s => s[0] === k) || [k, k])[1];
  const save = async () => { setBusy(true); try { await V.saveRevenue(p.id, f); toast('Faturamento salvo'); setF(o => ({ ...o, amount: '', evidence: '' })); await reload(); } catch (e) { toast(e.message || 'Falha ao salvar', 'ph-warning'); } setBusy(false); };
  const del = async id => { try { await V.removeRevenue(id); toast('Valor removido'); await reload(); } catch (e) { toast(e.message || 'Falha ao remover', 'ph-warning'); } };
  return <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
    <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>Valores reais que a empresa faturou em cada mês, de uma fonte identificada. Nada é estimado; mês sem valor fica vazio. Se houver mais de uma fonte para o mesmo mês, o sistema usa uma só (fiscal, depois balanço, crédito, manual) e não soma.</span>
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(170px,1fr))', gap: 14 }}>
      <Select label="Mês" options={months.map(crmMonthLabel)} value={crmMonthLabel(f.month)} onChange={e => setF(o => ({ ...o, month: months.find(m => crmMonthLabel(m) === e.target.value) || o.month }))} />
      <Input label="Valor faturado (R$)" value={f.amount} onChange={e => setF(o => ({ ...o, amount: e.target.value }))} placeholder="150000,00" />
      <Select label="Fonte" options={V.REV_SOURCES.map(s => s[1])} value={srcName(f.source)} onChange={e => setF(o => ({ ...o, source: (V.REV_SOURCES.find(s => s[1] === e.target.value) || [o.source])[0] }))} />
    </div>
    <Input label="Origem da informação (opcional)" value={f.evidence} onChange={e => setF(o => ({ ...o, evidence: e.target.value }))} placeholder="Ex.: NF-e 1234, balanço 2025, relatório de crédito" />
    <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
      <PBtn perm="commercial_intelligence.create" icon="ph-floppy-disk" onClick={save} disabled={busy}>{busy ? 'Salvando…' : 'Salvar faturamento do mês'}</PBtn>
      <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>Salvar de novo o mesmo mês e fonte atualiza o valor.</span>
    </div>
    {err && <span style={{ fontSize: 13, color: 'var(--text-danger)' }}>{err}</span>}
    {rows === null ? <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>Carregando…</span> : rows.length ? <div style={{ overflowX: 'auto' }}><table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}><thead><tr style={{ color: 'var(--text-muted)', textAlign: 'left' }}><th style={{ padding: '4px 8px 4px 0' }}>Mês</th><th style={{ padding: '4px 8px' }}>Valor</th><th style={{ padding: '4px 8px' }}>Fonte</th><th style={{ padding: '4px 8px' }}>Origem</th><th /></tr></thead><tbody>{rows.map(r => <tr key={r.id} style={{ borderTop: '1px solid var(--border-subtle)' }}><td style={{ padding: '4px 8px 4px 0' }}>{crmMonthLabel(r.month)}</td><td style={{ padding: '4px 8px', ...cxMono }}>{Number(r.amount).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })}</td><td style={{ padding: '4px 8px' }}>{srcName(r.source)}</td><td style={{ padding: '4px 8px', color: 'var(--text-muted)' }}>{r.evidence || '—'}</td><td style={{ padding: '4px 0', textAlign: 'right' }}><PBtn perm="commercial_intelligence.manage" size="sm" variant="ghost" icon="ph-trash" onClick={() => del(r.id)}>Remover</PBtn></td></tr>)}</tbody></table></div> : !err && <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>Nenhum faturamento informado nos últimos 12 meses.</span>}
  </div>;
}

function CrmRecord({ id }) {
  const { Card, EmptyState, Button, PageHeader, Badge, DataField } = window.VRticeDesignSystem_d763eb;
  const { go, bp } = useShell();
  const p = useProspects().find(x => x.id === id);
  const [d, setD] = React.useState(null);
  const reload = () => window.VxSalesIntelligence.accountDetails(id).then(setD);
  React.useEffect(() => { if (p) reload(); }, [id, !!p]);
  if (!p) return <Card variant="panel" padding={24}><EmptyState variant="block" icon="ph-address-book" title="Registro não encontrado" action={<Button onClick={() => go('crm')}>Voltar ao CRM</Button>} /></Card>;
  const details = d || { contacts: [], activities: [], tasks: [] };
  const miss = crmMissing(p);
  return <BlockGrid.Auto id="crm-record">
    <PageHeader size="lg" eyebrow="ADMINISTRAÇÃO · CRM" title={p.name} description={(p.city || '—') + ' - ' + (p.uf || '—') + ' · ' + (p.cnpj || '—')}
      actions={<><Button variant="secondary" icon="ph-arrow-left" onClick={() => go('crm')}>Todos os registros</Button><Button variant="secondary" icon="ph-database" onClick={() => go('prospect', { id: p.id })}>Abrir perfil do prospect</Button></>} />
    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}><StageBadge stage={p.stage} />{miss.length ? miss.map(x => <Badge key={x} tone="warning">{x}</Badge>) : <Badge tone="success">Cadastro completo</Badge>}</div>
    <div style={{ display: 'flex', gap: 20, flexWrap: 'wrap', alignItems: 'flex-start' }}>
      <div style={{ flex: '999 1 520px', minWidth: 0, display: 'flex', flexDirection: 'column', gap: 20 }}>
        <CcPanel title="Contato e endereço da empresa" sub="Complete o que o cadastro público não trouxe"><CrmManualContactForm p={p} onSaved={() => {}} /></CcPanel>
        <CcPanel title="Faturamento mensal (últimos 12 meses)" sub="Informado por fonte · separado dos valores públicos do PNCP"><CrmRevenueForm p={p} /></CcPanel>
        <CcPanel title="Contatos e decisores" sub="Pessoas da empresa; atualiza Prontidão e Prioridade"><ProspectContactsPanel p={p} details={details} onChanged={reload} /></CcPanel>
        <CcPanel title="Relacionamento" sub="Estágio, responsável, anotações e interações"><CrmRelationship p={p} details={details} onChanged={reload} /></CcPanel>
      </div>
      <div style={{ flex: '1 1 300px', maxWidth: bp === 'desktop' ? 380 : 'none', display: 'flex', flexDirection: 'column', gap: 20 }}>
        <CcPanel title="Cadastro público" sub="Somente leitura · Receita Federal / PNCP" gap={14}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(150px,1fr))', gap: 14 }}>
            <DataField label="CNPJ" mono>{p.cnpj || '—'}</DataField><DataField label="CNAE" mono>{p.cnae || '—'}</DataField><DataField label="Porte">{p.size || '—'}</DataField>
            <DataField label="Contratos 12 meses" mono>{p.contracts}</DataField><DataField label="Prioridade" mono>{p.total}</DataField><DataField label="Confiança dos dados" mono>{p.confidence}%</DataField>
          </div>
        </CcPanel>
        <CcPanel title="Atividades recentes" sub={details.activities.length + ' registradas'} gap={0}>
          {details.activities.length ? details.activities.slice(0, 8).map(a => <div key={a.id} style={{ padding: '10px 0', borderTop: '1px solid var(--border-subtle)' }}><strong style={{ fontSize: 14 }}>{a.subject || a.type}</strong><span style={{ display: 'block', fontSize: 12, color: 'var(--text-muted)' }}>{new Date(a.occurred_at).toLocaleString('pt-BR')} · {a.type}</span></div>) : <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>Nenhuma atividade registrada ainda.</span>}
        </CcPanel>
      </div>
    </div>
  </BlockGrid.Auto>;
}

function crmExport(list) {
  const q = window.VxSafe.csvCell; // neutraliza fórmulas (CSV injection)
  const head = ['Empresa', 'CNPJ', 'Cidade', 'UF', 'Segmento', 'Telefone', 'E-mail', 'Endereço', 'Editais válidos', 'Faturamento médio informado 12m (R$)', 'Meses com faturamento informado', 'Média mensal contratada 12m (R$)', 'Média mensal homologada 12m (R$)', 'Prioridade'];
  const lines = list.map(r => [r.name, r.cnpj, r.city, r.uf, r.sector, r.ph, r.em, r.ad, r.nEd == null ? '' : r.nEd, r.avgF == null ? '' : Math.round(r.avgF), r.nF || 0, r.avgC == null ? '' : Math.round(r.avgC), r.avgA == null ? '' : Math.round(r.avgA), r.total].map(q).join(';'));
  const blob = new Blob(['\ufeff' + [head.map(q).join(';'), ...lines].join('\r\n')], { type: 'text/csv;charset=utf-8' });
  const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'crm-' + new Date().toISOString().slice(0, 10) + '.csv'; document.body.appendChild(a); a.click(); a.remove();
}

function CrmKpi({ label, value, tone, active, onClick }) {
  return <button type="button" onClick={onClick} style={{ all: 'unset', cursor: 'pointer', boxSizing: 'border-box', flex: '1 1 150px', padding: '14px 16px', borderRadius: 14, border: '1px solid ' + (active ? 'var(--text-accent)' : 'var(--border-subtle)'), display: 'flex', flexDirection: 'column', gap: 4 }}>
    <span style={vxEyebrow}>{label}</span><strong style={{ fontSize: 24, fontWeight: 600, color: tone === 'warning' && value > 0 ? 'var(--status-warning)' : 'var(--text-primary)' }}>{value}</strong></button>;
}

function CrmScreen({ params }) {
  if (params && params.id) return <CrmRecord id={params.id} />;
  const { Card, PageHeader, Badge, EmptyState, Input, Select, Button } = window.VRticeDesignSystem_d763eb;
  const { go, bp } = useShell();
  const all = useProspects();
  const [filter, setFilter] = React.useState('all'), [q, setQ] = React.useState(''), [uf, setUf] = React.useState(''), [seg, setSeg] = React.useState(''), [rev, setRev] = React.useState({}), [fat, setFat] = React.useState({}), [vp, setVp] = React.useState({});
  const idsKey = all.map(r => r.empresaId).filter(Boolean).sort().join(',');
  React.useEffect(() => { let live = true; const ids = idsKey ? idsKey.split(',') : []; if (ids.length) { window.VxSalesIntelligence.publicRevenue12m(ids).then(x => live && setRev(x)).catch(() => {}); window.VxSalesIntelligence.validProcurementCounts(ids).then(x => live && setVp(x)).catch(() => {}); } return () => { live = false; }; }, [idsKey]);
  const accKey = all.filter(r => !r.candidate).map(r => r.id).sort().join(',');
  React.useEffect(() => { let live = true; const ids = accKey ? accKey.split(',') : []; if (ids.length) window.VxSalesIntelligence.revenueByAccount(ids).then(x => live && setFat(x)).catch(() => {}); return () => { live = false; }; }, [accKey]);
  const rows = all.filter(r => !r.candidate).map(r => { const m = (r.profile && r.profile.manual_contact) || {}; const pub = typeof pdFmtAddress === 'function' ? pdFmtAddress(r) : ''; const rv = rev[r.empresaId]; const tc = rv ? rv.contracts.reduce((a, b) => a + b, 0) : null, ta = rv ? rv.awarded.reduce((a, b) => a + b, 0) : null; const fv = fat[r.id]; return { ...r, nEd: r.empresaId && vp[r.empresaId] != null ? vp[r.empresaId] : null, avgF: fv ? fv.avg : null, nF: fv ? fv.filledCount : 0, avgC: tc == null ? null : tc / 12, avgA: ta == null ? null : ta / 12, ph: r.phone || m.phone || '', em: r.email || m.email || '', ad: pub || m.address || '', miss: crmMissing(r) }; });
  const norm = typeof ppnNorm === 'function' ? ppnNorm : v => String(v || '').toLowerCase();
  const terms = norm(q).split(/\s+/).filter(Boolean);
  const FILT = { phone: 'Sem telefone', email: 'Sem e-mail', addr: 'Sem endereço' };
  const ufs = [...new Set(rows.map(r => r.uf).filter(Boolean))].sort(), segs = [...new Set(rows.map(r => r.sector).filter(Boolean))].sort();
  const shown = rows.filter(r => (filter === 'all' || r.miss.includes(FILT[filter])) && (!uf || r.uf === uf) && (!seg || r.sector === seg) && (!terms.length || terms.every(t => norm([r.name, r.cnpj, r.city, r.uf, r.ph, r.em, r.ad].join(' ')).includes(t))));
  const count = k => rows.filter(r => r.miss.includes(k)).length;
  return <BlockGrid.Auto id="crm">
    <PageHeader size="lg" eyebrow="ADMINISTRAÇÃO" title="CRM" description="Complete e corrija dados comerciais em profundidade. O dado público nunca é sobrescrito: o que você digita fica separado e marcado como manual." />
    <CxLoadError />
    <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
      <CrmKpi label="EMPRESAS" value={rows.length} active={filter === 'all'} onClick={() => setFilter('all')} />
      <CrmKpi label="SEM TELEFONE" value={count('Sem telefone')} tone="warning" active={filter === 'phone'} onClick={() => setFilter('phone')} />
      <CrmKpi label="SEM E-MAIL" value={count('Sem e-mail')} tone="warning" active={filter === 'email'} onClick={() => setFilter('email')} />
      <CrmKpi label="SEM ENDEREÇO" value={count('Sem endereço')} tone="warning" active={filter === 'addr'} onClick={() => setFilter('addr')} />
    </div>
    <Card variant="panel" padding={0}>
      <div style={{ padding: '16px 24px', display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'flex-end' }}>
        <div style={{ flex: '1 1 260px', maxWidth: 420 }}><Input aria-label="Buscar no CRM" value={q} onChange={e => setQ(e.target.value)} placeholder="Buscar empresa, CNPJ, cidade, telefone…" /></div>
        <div style={{ width: 120 }}><Select aria-label="Filtrar por UF" options={['UF: todas', ...ufs]} value={uf || 'UF: todas'} onChange={e => setUf(e.target.value === 'UF: todas' ? '' : e.target.value)} /></div>
        <div style={{ width: 220 }}><Select aria-label="Filtrar por segmento" options={['Segmento: todos', ...segs]} value={seg || 'Segmento: todos'} onChange={e => setSeg(e.target.value === 'Segmento: todos' ? '' : e.target.value)} /></div>
        <PBtn perm="commercial_intelligence.export" variant="secondary" icon="ph-download-simple" onClick={() => crmExport(shown)}>Exportar lista (CSV)</PBtn>
      </div>
      {shown.length ? <VxTable id="crm-registros" cellX={bp === 'mobile' ? 12 : 24} rowY={14} minWidth={2040} onRowClick={r => go('crm', { id: r.id })} rows={shown} columns={[
        { key: 'name', label: 'Empresa', width: '260px', render: r => <strong style={{ fontWeight: 600, overflowWrap: 'anywhere' }}>{r.name}</strong> },
        { key: 'city', label: 'Cidade', sort: r => (r.city || '') + ' ' + (r.uf || ''), width: '170px', render: r => (r.city || '—') + ' - ' + (r.uf || '—') },
        { key: 'sector', label: 'Segmento', width: '170px', render: r => r.sector || <span style={{ color: 'var(--text-muted)' }}>—</span> },
        { key: 'stage', label: 'Estágio', sort: r => r.stage, width: '140px', render: r => <StageBadge stage={r.stage} /> },
        { key: 'ph', label: 'Telefone', width: '170px', render: r => r.ph ? <span style={cxMono}>{crmFmtPhone(r.ph)}{!r.phone && <Badge tone="info"> Manual</Badge>}</span> : <span style={{ color: 'var(--text-muted)' }}>—</span> },
        { key: 'em', label: 'E-mail', width: '230px', render: r => r.em ? <span style={{ overflowWrap: 'anywhere' }}>{r.em}</span> : <span style={{ color: 'var(--text-muted)' }}>—</span> },
        { key: 'ad', label: 'Endereço', width: '340px', render: r => r.ad ? <span style={{ overflowWrap: 'anywhere' }}>{r.ad}</span> : <span style={{ color: 'var(--text-muted)' }}>—</span> },
        { key: 'nEd', label: 'Editais válidos', sort: r => r.nEd, width: '130px', render: r => r.nEd == null ? <span style={{ color: 'var(--text-muted)' }}>…</span> : <span style={cxMono}>{r.nEd}</span> },
        { key: 'avgF', label: 'Faturamento informado (12 m)', sort: r => r.avgF, width: '210px', render: r => r.avgF == null ? <span style={{ color: 'var(--text-muted)' }}>—</span> : <span style={cxMono}>{crmBrl(r.avgF)}<span style={{ color: 'var(--text-muted)', fontSize: 11 }}> · {r.nF} {r.nF === 1 ? 'mês' : 'meses'}</span></span> },
        { key: 'avgC', label: 'Faturamento contratado (média mensal, 12 m)', sort: r => r.avgC, width: '200px', render: r => r.avgC == null ? <span style={{ color: 'var(--text-muted)' }}>…</span> : r.avgC > 0 ? <span style={cxMono}>{crmBrl(r.avgC)}</span> : <span style={{ color: 'var(--text-muted)' }}>—</span> },
        { key: 'avgA', label: 'Homologado (média mensal, 12 m)', sort: r => r.avgA, width: '200px', render: r => r.avgA == null ? <span style={{ color: 'var(--text-muted)' }}>…</span> : r.avgA > 0 ? <span style={cxMono}>{crmBrl(r.avgA)}</span> : <span style={{ color: 'var(--text-muted)' }}>—</span> },
        { key: 'total', label: 'Prioridade', sort: r => r.total, width: '110px', render: r => <span style={cxMono}>{r.total}</span> },
        { key: 'pend', label: 'Pendências', sort: r => r.miss.length, width: '230px', render: r => r.miss.length ? r.miss.map(x => <Badge key={x} tone="warning">{x}</Badge>) : <Badge tone="success">Completo</Badge> },
      ]} /> : <div style={{ padding: 24 }}><EmptyState variant="block" icon="ph-address-book" title="Nada para mostrar" /></div>}
    </Card>
  </BlockGrid.Auto>;
}
