/* Marketing · Leads · Prospeção — pool de empresas/contactos (BD marketing), fontes Apollo, Apify e ficheiros. */

const PROSP_API = '/api/marketing/prospeccao';
const PROSP_ESTADOS = [
  { id: 'novo', label: 'Novo', cor: '#3859D0' },
  { id: 'validado', label: 'Validado', cor: '#0891b2' },
  { id: 'atribuido', label: 'Atribuído', cor: '#7c3aed' },
  { id: 'em_contacto', label: 'Em contacto', cor: '#d97706' },
  { id: 'qualificado', label: 'Qualificado', cor: '#15803d' },
  { id: 'convertido', label: 'Convertido', cor: '#15803d' },
  { id: 'descartado', label: 'Descartado', cor: '#6b7fa3' },
  { id: 'opt_out', label: 'Opt-out', cor: '#9f1239' },
  { id: 'ja_no_gestor', label: 'Já no Gestor', cor: '#15803d' },
];
const PROSP_FONTES = { apollo: 'Apollo', apify: 'Apify', pagina: 'Página', import: 'Ficheiro', excel: 'Excel', validacao: 'Validação', manual: 'Manual' };

function prospQs(extra) {
  const p = new URLSearchParams();
  Object.entries(extra || {}).forEach(([k, v]) => { if (v !== undefined && v !== null && v !== '') p.set(k, v); });
  const email = window.currentUser?.email || '';
  if (email) p.set('email', email);
  return p.toString();
}

async function prospApi(path, { method = 'GET', body, form, query } = {}) {
  const opts = { method, headers: {} };
  if (form) opts.body = form;
  else if (body !== undefined) { opts.body = JSON.stringify(body); opts.headers['Content-Type'] = 'application/json'; }
  const r = await fetch(`${PROSP_API}${path}?${prospQs(query)}`, opts);
  const d = await r.json().catch(() => ({}));
  if (!r.ok || d.error) throw new Error(d.error || `HTTP ${r.status}`);
  return d;
}

const prospEstado = (id) => PROSP_ESTADOS.find(e => e.id === id) || { id, label: id || '—', cor: '#64748b' };
const prospData = (iso) => (iso ? new Date(iso).toLocaleString('pt-PT', { dateStyle: 'short', timeStyle: 'short' }) : '—');
const prospNum = (n) => Number(n || 0).toLocaleString('pt-PT');
const prospUsd = (n) => (n == null ? '—' : `$${Number(n).toFixed(2)}`);
function prospCreditos(n, eur) {
  const cred = `${n} ${Number(n) === 1 ? 'crédito' : 'créditos'}`;
  if (eur == null || eur === '') return cred;
  const valor = (Number(n) * Number(eur)).toLocaleString('pt-PT', { style: 'currency', currency: 'EUR' });
  return `${cred} (${valor})`;
}

function ProspBadge({ estado }) {
  const e = prospEstado(estado);
  return <span style={{ fontSize: 11, fontWeight: 650, color: e.cor, whiteSpace: 'nowrap' }}>{e.label}</span>;
}

function ProspShell({ children }) {
  return (
    <div data-theme="light" style={{
      height: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden', background: '#f8fafc',
      '--bg': '#f8fafc', '--bg-elev': '#ffffff', '--bg-hover': '#f1f5f9', '--bg-sunken': '#e8edf5',
      '--border': '#dde3ef', '--text': '#112954', '--text-muted': '#4a5e7a', '--text-dim': '#6b7fa3', '--ai-500': '#3859D0',
    }}>
      <style>{'.prosp-row:hover{background:#f8fafc}.prosp-chip:hover{border-color:var(--ai-500)}.prosp-mapa .leaflet-tile-pane{filter:grayscale(1) sepia(.28) hue-rotate(188deg) saturate(.42) brightness(1.06) contrast(.9)}@keyframes spin{to{transform:rotate(360deg)}}'}</style>
      {children}
    </div>
  );
}

function ProspCard({ children, style }) {
  return <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 16, ...style }}>{children}</div>;
}

function ProspKpis({ resumo, tab, admin, onIr }) {
  const c = resumo?.contactos || {};
  const items = [
    { id: 'base', label: 'Empresas', value: resumo?.total || 0, accent: '#3859D0' },
    { id: 'contactos', label: 'Contactos', value: c.total || 0, accent: '#7c3aed' },
    { id: 'mercados', label: 'Mercados', value: resumo?.mercados || 0, accent: '#0891b2' },
    ...(admin ? [{ id: 'pesquisa', label: 'Pesquisar', value: resumo?.pesquisas || 0, accent: '#b45309' }] : []),
    { id: 'execucoes', label: 'Histórico', value: resumo?.execucoes || 0, accent: '#15803d' },
  ];
  return (
    <div style={{ display: 'flex', gap: 12 }}>
      {items.map(k => {
        const on = tab === k.id;
        return (
          <div key={k.id} onClick={() => onIr(k.id)} style={{ flex: '1 1 0', background: '#fff', border: `1px solid ${on ? k.accent : 'var(--border)'}`, borderRadius: 8, padding: '12px 16px 0', cursor: 'pointer', display: 'flex', flexDirection: 'column', gap: 4, overflow: 'hidden' }}>
            <div style={{ fontSize: 9.5, fontWeight: 600, letterSpacing: '0.10em', textTransform: 'uppercase', color: on ? k.accent : 'var(--text-muted)', fontFamily: 'var(--font-mono)' }}>{k.label}</div>
            <div style={{ fontSize: 22, fontWeight: 700, fontFamily: 'var(--font-display)', color: k.accent, lineHeight: 1, paddingBottom: 10 }}>{prospNum(k.value)}</div>
            <div style={{ height: 3, background: 'var(--bg-sunken)', overflow: 'hidden' }}><div style={{ height: '100%', width: '100%', background: k.accent }} /></div>
          </div>
        );
      })}
    </div>
  );
}

function ProspDrop({ label, value, onChange, options }) {
  if (typeof ResFiltro === 'function') return <ResFiltro label={label} value={value} onChange={onChange} options={options} />;
  if (typeof AudFilterDropdown === 'function') return <AudFilterDropdown label={label} value={value} onChange={onChange} options={options} />;
  return (
    <label style={{ display: 'inline-flex', alignItems: 'center', gap: 8, border: '1px solid var(--border)', borderRadius: 6, padding: '6px 10px', background: '#fff', fontSize: 12 }}>
      <span style={{ color: 'var(--text-dim)', fontSize: 10, textTransform: 'uppercase', letterSpacing: '.06em' }}>{label}</span>
      <select value={value} onChange={e => onChange(e.target.value)} style={{ border: 'none', background: 'transparent', color: 'var(--text)', fontSize: 12 }}>
        {options.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
    </label>
  );
}

function ProspField({ label, hint, children }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: 12, color: 'var(--text)', minWidth: 0 }}>
      <span style={{ fontWeight: 650 }}>{label}</span>
      {children}
      {hint && <span style={{ fontSize: 12, lineHeight: 1.4, color: 'var(--text-dim)' }}>{hint}</span>}
    </label>
  );
}

function ProspSecao({ titulo, children, separador }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12, ...(separador ? { borderTop: '1px solid var(--border)', paddingTop: 16 } : {}) }}>
      {titulo && <div style={{ fontSize: 11, fontWeight: 650, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-dim)' }}>{titulo}</div>}
      {children}
    </div>
  );
}

function ProspAviso({ children }) {
  return <div style={{ fontSize: 12, lineHeight: 1.45, color: 'var(--text-muted)', background: '#f4f7fb', borderRadius: 8, padding: '10px 12px' }}>{children}</div>;
}

function ProspBotao({ disabled, onClick, children }) {
  return <button type="button" className="btn btn-ai" disabled={disabled} onClick={onClick} style={{ width: '100%', justifyContent: 'center' }}>{children}</button>;
}

function ProspGrelha({ children }) {
  return <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>{children}</div>;
}

function ProspChip({ on, label, title, onClick }) {
  return (
    <button type="button" title={title || ''} onClick={onClick} className="prosp-chip" style={{
      padding: '8px 10px', borderRadius: 8, cursor: 'pointer', fontFamily: 'inherit',
      border: `1px solid ${on ? 'var(--ai-500)' : 'var(--border)'}`,
      background: on ? 'color-mix(in oklch, var(--ai-500, #3859D0) 12%, #fff)' : '#fff',
      color: on ? 'var(--ai-500)' : 'var(--text)',
      fontSize: 12.5, fontWeight: 650, lineHeight: 1.25, textAlign: 'center',
      transition: 'background .12s, border-color .12s, color .12s',
    }}>{label}</button>
  );
}

const prospInput = { border: '1px solid var(--border)', borderRadius: 8, padding: '9px 11px', fontSize: 13, background: '#fff', color: 'var(--text)', minWidth: 0, width: '100%', fontFamily: 'inherit', boxSizing: 'border-box' };
const prospTh = { textAlign: 'left', fontSize: 10, fontWeight: 600, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.04em', padding: '8px 10px', borderBottom: '1px solid var(--border)', whiteSpace: 'nowrap', background: 'none' };
const prospTd = { fontSize: 12, padding: '10px', borderBottom: '1px solid var(--border)', verticalAlign: 'middle' };

function ProspMsg({ msg }) {
  if (!msg) return null;
  const erro = msg.tipo === 'erro';
  return <div style={{ fontSize: 13, padding: '8px 12px', borderRadius: 8, background: erro ? '#fef2f2' : '#f0fdf4', border: `1px solid ${erro ? '#fecaca' : '#bbf7d0'}`, color: erro ? '#991b1b' : '#166534' }}>{msg.texto}</div>;
}

// ── Base ──────────────────────────────────────────────────────────────────────

function prospContactos(r) {
  if (!r.n_contactos) return 'Sem contactos';
  if (r.n_emails) return `${r.n_emails} ${r.n_emails === 1 ? 'email' : 'emails'}`;
  return `${r.n_contactos} ${r.n_contactos === 1 ? 'contacto' : 'contactos'}`;
}

function ProspBase({ resumo, admin, onChanged, vendedores, marca, onOpen, desde, ate, f, setF, vista, cFiltro, onVista, onCFiltro }) {
  const [page, setPage] = React.useState(1);
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(false);
  const [erro, setErro] = React.useState('');
  const [sel, setSel] = React.useState(new Set());
  const [msg, setMsg] = React.useState(null);
  const [tick, setTick] = React.useState(0);
  const pessoas = vista === 'contactos';

  const filtros = React.useMemo(() => (pessoas
    ? { marca, desde, ate, page, limit: 50, pais: f.pais, fonte: f.fonte, ordem: f.ordem === 'nome' ? 'nome' : 'recentes', com_email: cFiltro === 'email' ? '1' : '', com_telemovel: cFiltro === 'telemovel' ? '1' : '' }
    : { ...f, marca, desde, ate, page, limit: 50 }), [pessoas, f, marca, desde, ate, page, cFiltro]);
  React.useEffect(() => { setPage(1); setSel(new Set()); }, [marca, desde, ate, vista, cFiltro, f.estado, f.pais, f.fonte, f.com_email, f.com_telefone, f.ordem]);
  React.useEffect(() => {
    let stop = false;
    setLoading(true); setErro('');
    const t = setTimeout(() => {
      prospApi(pessoas ? '/contactos' : '/empresas', { query: filtros })
        .then(d => { if (!stop) setData(d); })
        .catch(e => { if (!stop) setErro(e.message); })
        .finally(() => { if (!stop) setLoading(false); });
    }, 250);
    return () => { stop = true; clearTimeout(t); };
  }, [filtros, tick, pessoas]);

  const rows = data?.rows || [];
  const pages = data ? Math.max(1, Math.ceil(data.total / data.limit)) : 1;
  const toggle = (id) => setSel(prev => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n; });
  const todos = rows.length > 0 && rows.every(r => sel.has(r.id));

  const acao = async (fn, ok) => {
    setMsg(null);
    try { const d = await fn(); setMsg({ tipo: 'ok', texto: ok(d) }); setSel(new Set()); setTick(t => t + 1); onChanged?.(); }
    catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
  };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
      {admin && !pessoas && sel.size > 0 && (
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', fontSize: 13 }}>
          <strong>{sel.size} seleccionadas</strong>
          <button type="button" className="btn btn-sm btn-ai" onClick={() => acao(() => prospApi('/validar', { method: 'POST', body: { ids: [...sel], marca: marca || undefined } }), d => `Validação #${d.run_id} a correr — vê no Histórico.`)}>Validar</button>
          <button type="button" className="btn btn-sm" onClick={() => acao(() => prospApi('/apify/websites', { method: 'POST', body: { empresa_ids: [...sel] } }), d => `Extracção de contactos dos websites #${d.run_id} a correr (Apify).`)}>Extrair contactos dos websites</button>
          <button type="button" className="btn btn-sm btn-ghost" onClick={() => setSel(new Set())}>Limpar</button>
        </div>
      )}
      <ProspMsg msg={msg} />
      {erro && <ProspMsg msg={{ tipo: 'erro', texto: erro }} />}

      <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, overflow: 'auto' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead>
            <tr>
              {pessoas ? (
                <>
                  <th style={prospTh}>Nome</th>
                  <th style={prospTh}>Cargo</th>
                  <th style={prospTh}>Email</th>
                  <th style={prospTh}>Telefone</th>
                  <th style={prospTh}>LinkedIn</th>
                </>
              ) : (
                <>
                  {admin && <th style={{ ...prospTh, width: 36 }}><input type="checkbox" checked={todos} onChange={() => setSel(todos ? new Set() : new Set(rows.map(r => r.id)))} /></th>}
                  <th style={prospTh}>Empresa</th>
                  <th style={prospTh}>Local</th>
                  <th style={prospTh}>Contactos</th>
                  <th style={prospTh}>Estado</th>
                  <th style={prospTh}>Fonte</th>
                </>
              )}
            </tr>
          </thead>
          <tbody>
            {pessoas ? rows.map(r => (
              <tr key={r.id} className="prosp-row" onClick={() => onOpen({ id: r.empresa_id, nome: r.empresa_nome, pais: r.pais, fonte: r.fonte, estado: r.empresa_estado })} style={{ cursor: 'pointer' }}>
                <td style={prospTd}>
                  <div style={{ fontWeight: 650, fontSize: 13 }}>{r.nome_completo || [r.nome, r.apelido].filter(Boolean).join(' ') || '—'}</div>
                  {r.empresa_nome && <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{r.empresa_nome}</div>}
                </td>
                <td style={prospTd}>{r.cargo && r.cargo !== 'Contacto publicado' ? r.cargo : '—'}</td>
                <td style={{ ...prospTd, color: r.email ? 'var(--text)' : 'var(--text-dim)' }}>{r.email || '—'}</td>
                <td style={prospTd}>{r.telemovel_e164 || r.telemovel || r.empresa_telefone_e164 || r.empresa_telefone || '—'}</td>
                <td style={prospTd}>{r.linkedin_url ? <a href={r.linkedin_url} target="_blank" rel="noreferrer" onClick={ev => ev.stopPropagation()} style={{ color: 'var(--ai-500)', textDecoration: 'none' }}>Perfil</a> : '—'}</td>
              </tr>
            )) : rows.map(r => (
              <tr key={r.id} className="prosp-row" onClick={() => onOpen(r)} style={{ cursor: 'pointer' }}>
                {admin && <td style={prospTd} onClick={e => e.stopPropagation()}><input type="checkbox" checked={sel.has(r.id)} onChange={() => toggle(r.id)} /></td>}
                <td style={prospTd}>
                  <div style={{ fontWeight: 650, fontSize: 13 }}>{r.nome}</div>
                  <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{[r.dominio, r.industria, r.nif && `NIF ${r.nif}`].filter(Boolean).join(' · ') || '—'}</div>
                  <ProspLinksRede redes={r.redes} />
                </td>
                <td style={prospTd}>
                  <div>{[r.cidade, r.pais].filter(Boolean).join(', ') || '—'}</div>
                  {(r.telefone_e164 || r.telefone) && <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{r.telefone_e164 || r.telefone}</div>}
                </td>
                <td style={{ ...prospTd, color: r.n_contactos ? 'var(--text)' : 'var(--text-dim)' }}>{prospContactos(r)}</td>
                <td style={prospTd}><ProspBadge estado={r.estado} /></td>
                <td style={{ ...prospTd, color: 'var(--text-muted)' }}>{PROSP_FONTES[r.fonte] || r.fonte || '—'}</td>
              </tr>
            ))}
            {loading && !rows.length && <tr><td colSpan={pessoas ? 5 : (admin ? 6 : 5)} style={{ ...prospTd, padding: 36 }}><div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', gap: 10 }}><ProspSpin />A carregar…</div></td></tr>}
            {!rows.length && !loading && <tr><td colSpan={pessoas ? 5 : (admin ? 6 : 5)} style={{ ...prospTd, textAlign: 'center', color: 'var(--text-muted)', padding: 28 }}>{pessoas ? 'Sem contactos com estes filtros.' : (marca ? 'Nenhuma empresa desta marca. Em Todas vês a base completa.' : 'Sem empresas com estes filtros.')}</td></tr>}
          </tbody>
        </table>
      </div>

      {pages > 1 && (
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12 }}>
          <button type="button" className="btn" disabled={page <= 1} onClick={() => setPage(p => p - 1)}>Anterior</button>
          <span style={{ color: 'var(--text-muted)' }}>{(page - 1) * 50 + 1}–{Math.min(data?.total || 0, page * 50)} de {prospNum(data?.total)}</span>
          <button type="button" className="btn" disabled={page >= pages} onClick={() => setPage(p => p + 1)}>Seguinte</button>
        </div>
      )}
    </div>
  );
}

function ProspFicha({ id, admin, vendedores, onClose, onChanged, onLoaded }) {
  const [d, setD] = React.useState(null);
  const [erro, setErro] = React.useState('');
  const [tick, setTick] = React.useState(0);
  const [notas, setNotas] = React.useState('');
  const [msg, setMsg] = React.useState(null);

  React.useEffect(() => {
    let stop = false;
    setErro('');
    prospApi(`/empresas/${id}`).then(r => { if (!stop) { setD(r); if (r?.empresa) onLoaded?.(r.empresa); } }).catch(e => { if (!stop) setErro(e.message); });
    return () => { stop = true; };
  }, [id, tick]);

  const patch = async (body, texto) => {
    setMsg(null);
    try { await prospApi(`/empresas/${id}`, { method: 'PATCH', body: { ...body, notas: notas || undefined } }); setNotas(''); setMsg({ tipo: 'ok', texto }); setTick(t => t + 1); onChanged?.(); }
    catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
  };
  const revelar = async (ids) => {
    setMsg(null);
    try { const r = await prospApi('/contactos/revelar', { method: 'POST', body: { contacto_ids: ids } }); setMsg({ tipo: 'ok', texto: `${r.revelados} de ${r.pedidos} emails revelados (Apollo).` }); setTick(t => t + 1); }
    catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
  };

  const e = d?.empresa;
  const redes = redesDaEmpresa(e);
  const temRedes = ['facebook', 'instagram', 'tiktok', 'linkedin'].some(k => redes[k]);
  const v = e?.validacao || {};
  const porRevelar = (d?.contactos || []).filter(c => c.apollo_id && !c.email).map(c => c.id);
  const linha = (label, valor) => valor ? <div style={{ display: 'flex', gap: 8, fontSize: 13 }}><span style={{ color: 'var(--text-muted)', minWidth: 110 }}>{label}</span><span style={{ minWidth: 0, overflowWrap: 'anywhere' }}>{valor}</span></div> : null;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18, maxWidth: 980 }}>
      {!e && !erro && <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>A carregar…</div>}
      {erro && <ProspMsg msg={{ tipo: 'erro', texto: erro }} />}
        <ProspMsg msg={msg} />
        {e && (
          <>
            <ProspCard style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {linha('NIF', e.nif && `${e.nif}${v.nif ? (v.nif.ok === false ? ' · inválido' : v.nif.ok ? ' · válido' : ' · por confirmar') : ''}${v.nif?.vies?.registado ? ' · VIES' : ''}`)}
              {linha('Nome oficial', v.nif?.vies?.nome_oficial)}
              {linha('Website', e.website && <a href={/^https?:/.test(e.website) ? e.website : `https://${e.website}`} target="_blank" rel="noreferrer">{e.website}</a>)}
              {temRedes && linha('Redes', <ProspLinksRede redes={redes} />)}
              {linha('Telefone', e.telefone_e164 || e.telefone)}
              {linha('Morada', [e.morada, e.codigo_postal, e.cidade, e.distrito, e.pais].filter(Boolean).join(', '))}
              {linha('Sector', [e.industria, e.cae && `CAE ${e.cae}`].filter(Boolean).join(' · '))}
              {linha('Empregados', e.funcionarios)}
              {linha('Google', e.sinais?.gmb && `${e.sinais.gmb.rating ?? '—'}★ · ${e.sinais.gmb.reviews ?? 0} avaliações`)}
              {linha('Gestor', e.fm_entidade_id && `Já existe no Gestor (${e.fm_tenant} #${e.fm_entidade_id}, por ${e.fm_match_por})`)}
              {linha('Validação', e.validado_em && `${prospData(e.validado_em)}${v.dominio ? ` · domínio ${v.dominio.mx ? 'com' : 'sem'} email (MX)` : ''}`)}
            </ProspCard>

            <ProspCard style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
              <div style={{ fontWeight: 650 }}>Seguimento comercial</div>
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                <select style={prospInput} value={e.vendedor_id || ''} onChange={ev => patch({ vendedor_id: ev.target.value || null }, 'Vendedor actualizado.')}>
                  <option value="">Sem vendedor</option>
                  {vendedores.map(vd => <option key={vd.email} value={vd.email}>{vd.nome}</option>)}
                  {e.vendedor_id && !vendedores.some(vd => vd.email === e.vendedor_id) && <option value={e.vendedor_id}>{e.vendedor_id}</option>}
                </select>
                <select style={prospInput} value={e.estado} onChange={ev => patch({ estado: ev.target.value }, 'Estado actualizado.')}>
                  {PROSP_ESTADOS.map(s => <option key={s.id} value={s.id}>{s.label}</option>)}
                </select>
              </div>
              <textarea style={{ ...prospInput, minHeight: 60, resize: 'vertical' }} placeholder="Nota (opcional) — fica no histórico" value={notas} onChange={ev => setNotas(ev.target.value)} />
              {notas && <div><button type="button" className="btn btn-sm" onClick={() => patch({}, 'Nota registada.')}>Guardar nota</button></div>}
            </ProspCard>

            <ProspCard style={{ padding: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', padding: '12px 16px', gap: 8 }}>
                <div style={{ fontWeight: 650, flex: 1 }}>Contactos ({d.contactos.length})</div>
                {admin && porRevelar.length > 0 && <button type="button" className="btn btn-sm btn-ai" onClick={() => revelar(porRevelar)} title="Usa créditos Apollo">Revelar {porRevelar.length} emails (Apollo)</button>}
              </div>
              <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                <thead><tr><th style={prospTh}>Nome</th><th style={prospTh}>Cargo</th><th style={prospTh}>Email</th><th style={prospTh}>Telemóvel</th></tr></thead>
                <tbody>
                  {d.contactos.map(c => (
                    <tr key={c.id} style={{ opacity: c.opt_out ? 0.5 : 1 }}>
                      <td style={prospTd}>{c.nome_completo || '—'}{c.linkedin_url && <> · <a href={c.linkedin_url} target="_blank" rel="noreferrer">LinkedIn</a></>}{c.opt_out && <div style={{ fontSize: 11, color: '#b91c1c' }}>opt-out</div>}</td>
                      <td style={{ ...prospTd, fontSize: 12 }}>{c.cargo || '—'}</td>
                      <td style={{ ...prospTd, fontSize: 12 }}>{c.email || (c.apollo_id ? <span style={{ color: 'var(--text-dim)' }}>por revelar</span> : '—')}{c.email_status && <div style={{ fontSize: 10, color: c.email_status === 'invalido' ? '#b91c1c' : 'var(--text-dim)' }}>{c.email_status}{c.validacao?.email?.generico ? ' · genérico' : ''}</div>}</td>
                      <td style={{ ...prospTd, fontSize: 12, whiteSpace: 'nowrap' }}>{c.telemovel_e164 || c.telemovel || '—'}</td>
                    </tr>
                  ))}
                  {!d.contactos.length && <tr><td colSpan={4} style={{ ...prospTd, color: 'var(--text-muted)' }}>Sem contactos. {admin && e.website ? 'Selecciona a empresa na lista e usa “Extrair contactos dos websites”.' : ''}</td></tr>}
                </tbody>
              </table>
            </ProspCard>

            {d.eventos.length > 0 && (
              <ProspCard style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                <div style={{ fontWeight: 650 }}>Histórico</div>
                {d.eventos.map(ev => (
                  <div key={ev.id} style={{ fontSize: 12, borderLeft: '2px solid var(--border)', paddingLeft: 10 }}>
                    <div><strong>{ev.tipo.replace('estado:', 'Estado → ')}</strong> · {prospData(ev.criado_em)} · {ev.criado_por}</div>
                    {ev.notas && <div style={{ color: 'var(--text-muted)', whiteSpace: 'pre-wrap' }}>{ev.notas}</div>}
                  </div>
                ))}
              </ProspCard>
            )}
          </>
        )}
    </div>
  );
}

// ── Nova pesquisa ─────────────────────────────────────────────────────────────

const PROSP_FONTES_PESQUISA = [
  { id: 'apollo', label: 'Apollo' },
  { id: 'pagina', label: 'Página' },
];
const PROSP_REDES = [
  { id: 'facebook', label: 'Facebook', nota: 'Páginas de empresa: nome, categoria, telefone, email e site.' },
  { id: 'instagram', label: 'Instagram', nota: 'Perfis públicos do segmento. O site entra quando o perfil o tem.' },
  { id: 'tiktok', label: 'TikTok', nota: 'Perfis públicos. Útil em decoração e reclamos; na indústria rende pouco.' },
];
const PROSP_PAISES = [{ value: 'PT', label: 'Portugal' }, { value: 'ES', label: 'Espanha' }, { value: 'FR', label: 'França' }];

function redesDaEmpresa(e) {
  const w = e?.sinais?.website_contactos || {};
  return { linkedin: w.linkedin, facebook: w.facebook, instagram: w.instagram, ...(e?.sinais?.redes || {}) };
}

function ProspLinksRede({ redes }) {
  const links = [
    ['Facebook', redes?.facebook],
    ['Instagram', redes?.instagram],
    ['TikTok', redes?.tiktok],
    ['LinkedIn', redes?.linkedin],
  ].filter(([, url]) => url);
  if (!links.length) return null;
  return (
    <span style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }} onClick={ev => ev.stopPropagation()}>
      {links.map(([label, url]) => <a key={label} href={url} target="_blank" rel="noreferrer" style={{ fontSize: 12, color: 'var(--ai-500)', textDecoration: 'none' }}>{label}</a>)}
    </span>
  );
}

function ProspSeparadores({ items, activo, onChange }) {
  return (
    <div style={{ display: 'flex', gap: 0, flexWrap: 'wrap' }}>
      {items.map(b => {
        const on = b.id === activo;
        return (
          <button key={b.id} type="button" onClick={() => onChange(b.id)} style={{
            background: 'none', border: 'none', outline: 'none',
            borderBottom: `2px solid ${on ? 'var(--ai-500)' : 'transparent'}`,
            color: on ? 'var(--text)' : 'var(--text-muted)',
            fontSize: 13, fontWeight: on ? 600 : 500,
            fontFamily: 'var(--font-display)', letterSpacing: '.01em',
            padding: '10px 16px 12px', cursor: 'pointer', whiteSpace: 'nowrap',
          }}>{b.label}</button>
        );
      })}
    </div>
  );
}

function ProspMenuFontes({ activo, onChange, filtros }) {
  const [over, setOver] = React.useState('');
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      {PROSP_FONTES_PESQUISA.map(p => {
        const on = p.id === activo;
        const hover = over === p.id && !on;
        return (
          <div key={p.id}
            onMouseEnter={() => setOver(p.id)} onMouseLeave={() => setOver('')}
            style={{
              border: `1px solid ${on || hover ? 'var(--ai-500)' : 'var(--border)'}`,
              borderRadius: 8, overflow: 'hidden',
              background: on ? 'color-mix(in oklch, var(--ai-500, #3859D0) 8%, #fff)' : (hover ? '#f4f7ff' : '#fff'),
              transition: 'background .12s, border-color .12s',
            }}>
            <button type="button" onClick={() => onChange(p.id)} style={{
              display: 'block', width: '100%', textAlign: 'left', background: 'transparent', border: 'none',
              color: on ? 'var(--ai-500)' : 'var(--text)', padding: '10px 12px',
              fontSize: 13, fontWeight: 650, cursor: 'pointer', fontFamily: 'inherit',
            }}>{p.label}</button>
            {on && (
              <div style={{ borderTop: '1px solid var(--border)', background: '#fff', padding: '12px 12px 14px', display: 'flex', flexDirection: 'column', gap: 16 }}>
                {filtros}
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

function ProspPesquisasGuardadas({ g }) {
  const [over, setOver] = React.useState(null);
  const [nome, setNome] = React.useState('');
  const aberta = g.rows.find(r => r.id === g.aberta) || null;
  React.useEffect(() => { setNome(aberta?.nome || ''); }, [g.aberta]);
  const canalDe = (fonte) => (fonte === 'pagina' ? 'Página' : 'Apollo');
  const nomeFinal = (nome.trim() || g.rascunho?.rotulo || '').trim();
  const gravar = async (comoNova) => {
    if (!nomeFinal) return;
    if (aberta && !comoNova) await g.onActualizar(aberta.id, nomeFinal);
    else await g.onGuardar(nomeFinal);
  };
  return (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 16, display: 'flex', flexDirection: 'column', gap: 12 }}>
      <div style={{ fontSize: 11, fontWeight: 650, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-dim)' }}>Pesquisas guardadas</div>
      {!g.rows.length && (
        <div style={{ border: '1px solid var(--border)', borderRadius: 8, padding: '10px 12px', fontSize: 13, color: 'var(--text-muted)' }}>Ainda não há pesquisas guardadas.</div>
      )}
      {g.rows.length > 0 && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {g.rows.map(r => {
            const on = g.aberta === r.id;
            const hover = over === r.id && !on;
            return (
              <div key={r.id} onMouseEnter={() => setOver(r.id)} onMouseLeave={() => setOver(null)} style={{
                display: 'flex', alignItems: 'center', gap: 8,
                border: `1px solid ${on || hover ? 'var(--ai-500)' : 'var(--border)'}`, borderRadius: 8, padding: '8px 10px',
                background: on ? 'color-mix(in oklch, var(--ai-500, #3859D0) 10%, #fff)' : (hover ? '#f4f7ff' : '#fff'),
              }}>
                <button type="button" onClick={() => g.onAbrir(r)} style={{ flex: 1, minWidth: 0, textAlign: 'left', background: 'transparent', border: 'none', cursor: 'pointer', fontFamily: 'inherit', padding: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 650, color: on ? 'var(--ai-500)' : 'var(--text)' }}>{r.nome}</div>
                  <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 2 }}>{canalDe(r.fonte)} · {r.alvo === 'contactos' ? 'Contactos' : 'Empresas'}</div>
                </button>
                <button type="button" aria-label="Editar pesquisa" title="Editar" onClick={() => g.onAbrir(r)} style={{ border: 'none', background: 'transparent', color: on ? 'var(--ai-500)' : 'var(--text-dim)', cursor: 'pointer', fontSize: 12, fontWeight: 650, fontFamily: 'inherit', padding: 4 }}>Editar</button>
                <button type="button" aria-label="Apagar pesquisa" onClick={() => g.onApagar(r.id)} style={{ border: 'none', background: 'transparent', color: 'var(--text-dim)', cursor: 'pointer', fontSize: 16, lineHeight: 1, padding: 4 }}>×</button>
              </div>
            );
          })}
        </div>
      )}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, borderTop: '1px solid var(--border)', paddingTop: 12 }}>
        <div style={{ fontSize: 12, color: 'var(--text-muted)', lineHeight: 1.4 }}>{aberta ? 'A editar esta pesquisa. Muda o nome ou os filtros em cima.' : 'Guarda os filtros que estão em cima, sem os lançar.'}</div>
        <input style={prospInput} value={nome} placeholder={g.rascunho?.rotulo || 'Nome da pesquisa'} onChange={ev => setNome(ev.target.value)} />
        <ProspBotao disabled={!g.rascunho?.pode || !nomeFinal || g.aGuardar} onClick={() => gravar(false)}>{g.aGuardar ? 'A guardar…' : (aberta ? 'Actualizar' : 'Guardar esta')}</ProspBotao>
        {aberta && (
          <button type="button" disabled={!g.rascunho?.pode || !nomeFinal || g.aGuardar} onClick={() => gravar(true)} style={{
            width: '100%', border: '1px solid var(--border)', background: '#fff', borderRadius: 8,
            padding: '8px 10px', fontFamily: 'inherit', fontSize: 13, fontWeight: 650, color: 'var(--text)',
            cursor: 'pointer', opacity: !g.rascunho?.pode || !nomeFinal || g.aGuardar ? 0.5 : 1,
          }}>Guardar como nova</button>
        )}
        {g.erro && <div style={{ fontSize: 12, color: '#b91c1c', lineHeight: 1.4 }}>{g.erro}</div>}
      </div>
    </div>
  );
}

function ProspDirectorio({ busy, caixa, resultados, onRun }) {
  const [url, setUrl] = React.useState('');
  const valido = /^https?:\/\/\S+\.\S+/.test(url.trim());
  const reportar = caixa.onRascunho;
  React.useEffect(() => {
    let rotulo = 'Página';
    try { if (url.trim()) rotulo = new URL(url.trim()).hostname.replace(/^www\./, ''); } catch { /* ainda não é um endereço */ }
    reportar?.({ fonte: 'pagina', alvo: caixa.alvo, parametros: { url: url.trim() }, rotulo, pode: valido });
  }, [url, valido, caixa.alvo, reportar]);
  React.useEffect(() => {
    const p = caixa.pedido;
    if (!p || p.fonte !== 'pagina') return;
    setUrl(p.parametros?.url || '');
  }, [caixa.pedido && caixa.pedido.n]);
  return (
    <ProspColunas caixa={caixa} resultados={resultados} filtros={
      <>
        <ProspSecao titulo="Endereço">
          <ProspField label="URL" hint="Lista ou ficha. Ex.: https://atp.pt/pt-pt/empresas/">
            <input style={prospInput} value={url} placeholder="https://" disabled={busy} onChange={ev => setUrl(ev.target.value)} />
          </ProspField>
        </ProspSecao>
        <ProspAviso>Com o ScrapeGraph ligado em Ligações, lê a página — tabela ou aplicação — e grava cada empresa. Sem essa chave, só entra o que estiver escrito no HTML. O ScrapeGraph gasta créditos do plano dele.</ProspAviso>
        <ProspBotao disabled={busy || !valido} onClick={() => onRun({ url: url.trim() })}>
          {busy ? <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><ProspSpin />A extrair…</span> : 'Extrair contactos'}
        </ProspBotao>
      </>
    } />
  );
}

function ProspPesquisa({ fonte, onFonte, onLancada, onOpen, marca, marcaLabel }) {
  const [msg, setMsg] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [run, setRun] = React.useState(null);
  const [rows, setRows] = React.useState([]);
  const [alvo, setAlvo] = React.useState('empresas');
  const [aberto, setAberto] = React.useState(true);
  const [guardadas, setGuardadas] = React.useState([]);
  const [aberta, setAberta] = React.useState(null);
  const [rascunho, setRascunho] = React.useState(null);
  const [pedido, setPedido] = React.useState(null);
  const [aGuardar, setAGuardar] = React.useState(false);
  const [erroGuardar, setErroGuardar] = React.useState('');
  const onRascunho = React.useCallback((snap) => {
    setRascunho(prev => {
      const antes = prev && { fonte: prev.fonte, alvo: prev.alvo, rotulo: prev.rotulo, pode: prev.pode, parametros: prev.parametros };
      return JSON.stringify(antes) === JSON.stringify(snap) ? prev : snap;
    });
  }, []);
  React.useEffect(() => {
    prospApi('/pesquisas/guardadas').then(d => setGuardadas(d.rows || [])).catch(() => setGuardadas([]));
  }, []);
  const grupo = ['facebook', 'instagram', 'tiktok'].includes(fonte) ? 'redes' : fonte;
  const comMarca = (b) => (marca ? { ...b, marca } : b);
  const aLer = busy || run?.estado === 'a_correr';
  const correr = async (fn, nota = 'A pesquisar…') => {
    setBusy(true); setMsg(null); setRows([]); setRun({ estado: 'a_correr', notas: nota });
    try {
      const d = await fn();
      setRun({ id: d.run_id, estado: d.estado || 'a_correr', notas: nota });
      onLancada?.();
    } catch (e) { setRun(null); setMsg({ tipo: 'erro', texto: e.message }); }
    finally { setBusy(false); }
  };
  React.useEffect(() => { setRun(null); setRows([]); setMsg(null); }, [fonte]);
  React.useEffect(() => {
    if (!run?.id || run.estado !== 'a_correr') return;
    let stop = false;
    const ler = async () => {
      try {
        const d = await prospApi(`/runs/${run.id}`);
        if (stop || !d.run) return;
        if (d.run.estado === 'a_correr') {
          setRun(d.run);
          if (Number(d.run.n_empresas) > 0) {
            const e = await prospApi(alvo === 'contactos' ? '/contactos' : '/empresas', { query: { run_id: run.id, limit: 200 } });
            if (!stop) setRows(e.rows || []);
          }
          return;
        }
        setRun(d.run);
        if (d.run.estado === 'concluido') onLancada?.();
      } catch (e) { if (!stop) setMsg({ tipo: 'erro', texto: e.message }); }
    };
    ler();
    const id = setInterval(ler, 4000);
    return () => { stop = true; clearInterval(id); };
  }, [run?.id, run?.estado, alvo]);
  React.useEffect(() => {
    if (!run?.id || run.estado !== 'concluido' || run.fonte === 'validacao') {
      if (run?.fonte === 'validacao') setRows([]);
      return;
    }
    let stop = false;
    prospApi(alvo === 'contactos' ? '/contactos' : '/empresas', { query: { run_id: run.id, limit: 200 } })
      .then(e => { if (!stop) setRows(e.rows || []); })
      .catch(() => { if (!stop) setRows([]); });
    return () => { stop = true; };
  }, [run?.id, run?.estado, run?.fonte, alvo]);
  const escolher = (id) => {
    if (['facebook', 'instagram', 'tiktok'].includes(id)) { setAberto(true); onFonte(id); return; }
    if (id === grupo && aberto) { setAberto(false); return; }
    setAberto(true);
    onFonte(id);
  };
  const redeActual = PROSP_REDES.find(r => r.id === fonte);
  const notaMarca = marcaLabel ? <>Fica em <strong>{marcaLabel}</strong>.</> : 'Sem marca. Escolhe uma marca na tab se quiseres que fique associada.';
  const abrirGuardada = (item) => {
    setAberta(item.id);
    setAlvo(item.alvo === 'contactos' ? 'contactos' : 'empresas');
    setAberto(true);
    onFonte(item.fonte);
    setPedido({ n: Date.now(), fonte: item.fonte, alvo: item.alvo, parametros: item.parametros || {} });
  };
  const guardarEsta = async (nome) => {
    if (!rascunho?.pode || !nome) return false;
    setAGuardar(true); setErroGuardar('');
    try {
      const d = await prospApi('/pesquisas/guardadas', { method: 'POST', body: { nome, fonte: rascunho.fonte, alvo: rascunho.alvo || alvo, marca: marca || undefined, parametros: rascunho.parametros } });
      setGuardadas(lista => [d.row, ...lista.filter(x => x.id !== d.row.id)]);
      setAberta(d.row.id);
      return true;
    } catch (e) { setErroGuardar(e.message); return false; }
    finally { setAGuardar(false); }
  };
  const actualizarGuardada = async (id, nome) => {
    if (!rascunho?.pode || !nome) return false;
    setAGuardar(true); setErroGuardar('');
    try {
      const d = await prospApi(`/pesquisas/guardadas/${id}`, { method: 'PATCH', body: { nome, fonte: rascunho.fonte, alvo: rascunho.alvo || alvo, marca: marca || undefined, parametros: rascunho.parametros } });
      setGuardadas(lista => lista.map(x => x.id === d.row.id ? d.row : x));
      setAberta(d.row.id);
      return true;
    } catch (e) { setErroGuardar(e.message); return false; }
    finally { setAGuardar(false); }
  };
  const apagarGuardada = async (id) => {
    setGuardadas(lista => lista.filter(x => x.id !== id));
    if (aberta === id) setAberta(null);
    try { await prospApi(`/pesquisas/guardadas/${id}`, { method: 'DELETE' }); }
    catch (e) { setErroGuardar(e.message); prospApi('/pesquisas/guardadas').then(d => setGuardadas(d.rows || [])).catch(() => {}); }
  };
  const caixa = { alvo, onAlvo: setAlvo, nota: notaMarca, activo: aberto ? grupo : '', onCanal: escolher, onRascunho, pedido, guardadas: { rows: guardadas, aberta, rascunho, aGuardar, erro: erroGuardar, onAbrir: abrirGuardada, onGuardar: guardarEsta, onActualizar: actualizarGuardada, onApagar: apagarGuardada }, extra: grupo === 'redes' ? (
    <>
      <ProspSeparadores items={PROSP_REDES} activo={fonte} onChange={escolher} />
      <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{redeActual?.nota} Só a página pública. Sem seguidores nem publicações.</div>
    </>
  ) : null };
  const aviso = msg ? <ProspMsg msg={msg} /> : null;
  const tabela = <ProspTabelaRun run={run} rows={rows} alvo={alvo} onOpen={onOpen} aCarregar={aLer} />;
  const canalPessoas = alvo === 'contactos' && (fonte === 'google' || redeActual);
  return (
    <>
      {fonte === 'maps' && <ProspFormMaps busy={busy} alvo={alvo} caixa={caixa} resultados={<>{aviso}{tabela}</>} onRun={(b) => correr(() => prospApi('/pesquisas/apify', { method: 'POST', body: comMarca(b) }))} />}
      {fonte === 'google' && !canalPessoas && <ProspFormGoogle busy={busy} caixa={caixa} resultados={<>{aviso}{tabela}</>} onRun={(b) => correr(() => prospApi('/pesquisas/apify', { method: 'POST', body: comMarca({ ...b, modo: 'google' }) }))} />}
      {redeActual && !canalPessoas && <ProspFormRede rede={redeActual} busy={busy} caixa={caixa} resultados={<>{aviso}{tabela}</>} onRun={(b) => correr(() => prospApi('/pesquisas/apify', { method: 'POST', body: comMarca({ ...b, modo: redeActual.id }) }))} />}
      {canalPessoas && <ProspColunas caixa={caixa} resultados={<>{aviso}{tabela}</>} filtros={<ProspCanaisPessoa onIr={escolher} />} />}
      {fonte === 'apollo' && alvo === 'contactos' && <ProspApolloPessoas busy={busy} setBusy={setBusy} setMsg={setMsg} onDone={onLancada} marca={marca} caixa={caixa} aviso={aviso} />}
      {fonte === 'apollo' && alvo !== 'contactos' && <ProspApollo busy={busy} setBusy={setBusy} setMsg={setMsg} onDone={onLancada} marca={marca} caixa={caixa} aviso={aviso} />}
      {fonte === 'pagina' && <ProspDirectorio busy={aLer} caixa={caixa} resultados={<>{aviso}{tabela}</>} onRun={(b) => correr(() => prospApi('/pesquisas/pagina', { method: 'POST', body: comMarca(b) }), 'A ler a página…')} />}
    </>
  );
}

const prospLinhas = { display: 'flex', flexDirection: 'column', gap: 12 };

function ProspColunas({ caixa, filtros, resultados, alvos }) {
  const [overAlvo, setOverAlvo] = React.useState('');
  const separadores = alvos || [{ id: 'empresas', label: 'Empresas' }, { id: 'contactos', label: 'Contactos' }];
  const alvoBtn = (id, label) => {
    const on = caixa.alvo === id;
    const hover = overAlvo === id && !on;
    return (
      <button key={id} type="button" onClick={() => caixa.onAlvo(id)}
        onMouseEnter={() => setOverAlvo(id)} onMouseLeave={() => setOverAlvo('')}
        style={{
          flex: 1, border: `1px solid ${on || hover ? 'var(--ai-500)' : 'var(--border)'}`, borderRadius: 6,
          background: on ? 'color-mix(in oklch, var(--ai-500, #3859D0) 12%, #fff)' : (hover ? '#f4f7ff' : '#fff'),
          color: on ? 'var(--ai-500)' : 'var(--text)', padding: '8px 10px', cursor: 'pointer',
          fontSize: 13, fontWeight: 650, fontFamily: 'inherit',
          transition: 'background .12s, color .12s, border-color .12s',
        }}>{label}</button>
    );
  };
  const unico = !alvos && PROSP_FONTES_PESQUISA.length === 1;
  return (
    <div style={{ display: 'flex', gap: 20, alignItems: 'flex-start' }}>
      <aside style={{ width: 360, flexShrink: 0, display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 16, display: 'flex', flexDirection: 'column', gap: 16 }}>
          <div style={{ display: 'flex', gap: 8 }}>
            {separadores.map(s => alvoBtn(s.id, s.label))}
          </div>
          {caixa.nota && <div style={{ fontSize: 12, lineHeight: 1.45, color: 'var(--text-muted)' }}>{caixa.nota}</div>}
          {alvos ? (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>{filtros}</div>
          ) : unico ? (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
              {caixa.extra}
              {filtros}
            </div>
          ) : (
            <ProspMenuFontes activo={caixa.activo} onChange={caixa.onCanal} filtros={
              <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
                {caixa.extra}
                {filtros}
              </div>
            } />
          )}
        </div>
        {!alvos && caixa.guardadas && <ProspPesquisasGuardadas g={caixa.guardadas} />}
      </aside>
      <div style={{ flex: 1, minWidth: 0 }}>{resultados}</div>
    </div>
  );
}

function ProspSpin({ size = 16 }) {
  return <span style={{ width: size, height: size, borderRadius: '50%', border: '2px solid var(--border)', borderTopColor: 'var(--ai-500)', animation: 'spin .8s linear infinite', display: 'inline-block', flexShrink: 0 }} />;
}

function ProspTabelaRun({ run, rows, alvo, onOpen, aCarregar = false }) {
  const caixa = { background: '#fff', border: '1px solid var(--border)', borderRadius: 10, minHeight: 280, overflow: 'auto' };
  const pessoas = alvo === 'contactos';
  const cols = pessoas ? 6 : 5;
  const erro = run?.estado === 'erro';
  const vazio = run?.fonte === 'validacao'
    ? (run.notas || 'Validação concluída. O estado actualiza na lista.')
    : (run?.estado === 'concluido' && run?.notas) || 'Sem resultados.';
  const site = (r) => r.website || (r.dominio ? `https://${r.dominio}` : '');
  return (
    <div style={caixa}>
      {aCarregar && rows.length > 0 && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '14px 16px', borderBottom: '1px solid var(--border)' }}>
          <ProspSpin />
          <span style={{ fontSize: 13, color: 'var(--text)' }}>{run?.notas || 'A pesquisar…'}</span>
        </div>
      )}
      {erro && (
        <div style={{ padding: '28px 16px', textAlign: 'center', color: '#b91c1c', fontSize: 13, lineHeight: 1.45 }}>{run.notas || 'A leitura falhou.'}</div>
      )}
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead>
          <tr>
            {pessoas ? (
              <><th style={prospTh}>Contacto</th><th style={prospTh}>Cargo</th><th style={prospTh}>Empresa</th><th style={prospTh}>Email</th><th style={prospTh}>Telemóvel</th><th style={prospTh}>LinkedIn</th></>
            ) : (
              <><th style={prospTh}>Empresa</th><th style={prospTh}>Website</th><th style={prospTh}>Telefone</th><th style={prospTh}>Local</th><th style={prospTh}>Sector</th></>
            )}
          </tr>
        </thead>
        <tbody>
          {run && run.estado !== 'erro' && run.fonte !== 'validacao' && (pessoas ? rows.map(r => (
            <tr key={r.id} className="prosp-row" onClick={() => onOpen?.({ id: r.empresa_id, nome: r.empresa_nome, pais: r.pais, fonte: r.fonte, estado: r.empresa_estado })} style={{ cursor: 'pointer' }}>
              <td style={prospTd}><div style={{ fontWeight: 650 }}>{r.nome_completo || [r.nome, r.apelido].filter(Boolean).join(' ') || '—'}</div></td>
              <td style={prospTd}>{r.cargo || '—'}</td>
              <td style={prospTd}>{r.empresa_nome || '—'}</td>
              <td style={prospTd}>{r.email || '—'}</td>
              <td style={prospTd}>{r.telemovel_e164 || r.telemovel || '—'}</td>
              <td style={prospTd}>{r.linkedin_url ? <a href={r.linkedin_url} target="_blank" rel="noreferrer" onClick={ev => ev.stopPropagation()} style={{ color: 'var(--ai-500)', textDecoration: 'none' }}>Perfil</a> : '—'}</td>
            </tr>
          )) : rows.map(r => (
            <tr key={r.id} className="prosp-row" onClick={() => onOpen?.(r)} style={{ cursor: 'pointer' }}>
              <td style={prospTd}><div style={{ fontWeight: 650 }}>{r.nome}</div></td>
              <td style={prospTd}>{site(r) ? <a href={site(r)} target="_blank" rel="noreferrer" onClick={ev => ev.stopPropagation()} style={{ color: 'var(--ai-500)', textDecoration: 'none' }}>{r.dominio || r.website}</a> : '—'}</td>
              <td style={prospTd}>{r.telefone_e164 || r.telefone || '—'}</td>
              <td style={prospTd}>{[r.cidade, r.pais].filter(Boolean).join(', ') || '—'}</td>
              <td style={prospTd}>{r.industria || '—'}</td>
            </tr>
          )))}
          {aCarregar && !rows.length && (
            <tr><td colSpan={cols} style={{ ...prospTd, padding: '48px 16px' }}>
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
                <ProspSpin size={22} />
                <span style={{ fontSize: 13, color: 'var(--text)' }}>{run?.notas || 'A pesquisar…'}</span>
              </div>
            </td></tr>
          )}
          {!aCarregar && !erro && (!run || run.fonte === 'validacao' || !rows.length) && (
            <tr><td colSpan={cols} style={{ ...prospTd, textAlign: 'center', color: 'var(--text-muted)', padding: 28 }}>{vazio}</td></tr>
          )}
        </tbody>
      </table>
    </div>
  );
}

function ProspCanaisPessoa({ onIr }) {
  return (
    <>
      <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Este canal encontra a página ou o site da empresa. Para pessoas, usa um canal que as traz.</div>
      <ProspEscolha on={false} label="Apollo" hint="Cargo, email, telemóvel e LinkedIn." onClick={() => onIr('apollo')} />
      <ProspEscolha on={false} label="Google Maps" hint="Decisores e emails do website." onClick={() => onIr('maps')} />
    </>
  );
}

function ProspTrilho({ segmentos, nota, extra }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', background: '#fff', borderRadius: 8, border: '1px solid var(--border)', boxShadow: '0 1px 4px rgba(40,41,61,0.04), 0 4px 16px rgba(96,97,112,0.08)', flexWrap: 'wrap' }}>
      {segmentos.map((seg, i) => {
        const ultimo = i === segmentos.length - 1;
        return (
          <React.Fragment key={i}>
            {seg.onClick && !ultimo ? (
              <button type="button" onClick={seg.onClick} style={{ background: 'transparent', border: 0, cursor: 'pointer', padding: 0, fontSize: 12, color: 'var(--ai-500)' }}>{seg.label}</button>
            ) : (
              <span style={{ fontSize: 12, color: 'var(--text)', fontWeight: ultimo ? 700 : 400 }}>{seg.label}</span>
            )}
            {!ultimo && <span style={{ color: 'var(--text-dim)', fontSize: 12 }}>›</span>}
          </React.Fragment>
        );
      })}
      {nota}
      {extra && <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 8 }}>{extra}</div>}
    </div>
  );
}

const MAPS_DEPTS = [
  { id: 'c_suite', label: 'Direcção' },
  { id: 'sales', label: 'Comercial' },
  { id: 'marketing', label: 'Marketing' },
  { id: 'operations', label: 'Produção' },
  { id: 'finance', label: 'Financeiro' },
];

function ProspFormMaps({ busy, onRun, caixa, resultados, alvo }) {
  const [b, setB] = React.useState({ pesquisas: '', localizacao: '', pais: 'PT', max_por_pesquisa: 50, extrair_contactos: false, leads: false, leads_por_empresa: 2, leads_departamentos: [], max_custo_usd: 5 });
  const s = (k) => (ev) => setB(p => ({ ...p, [k]: ev.target.type === 'checkbox' ? ev.target.checked : ev.target.value }));
  const n = b.pesquisas.split(/[,;\n]/).filter(x => x.trim()).length;
  const toggleDept = (id) => setB(p => ({ ...p, leads_departamentos: p.leads_departamentos.includes(id) ? p.leads_departamentos.filter(x => x !== id) : [...p.leads_departamentos, id] }));
  return (
    <ProspColunas caixa={caixa} resultados={resultados} filtros={
      <>
        <div style={prospLinhas}>
          <ProspField label="O que procurar" hint="Separa por vírgulas — ex.: gráfica, empresa de reclamos, decoração de interiores"><input style={prospInput} value={b.pesquisas} onChange={s('pesquisas')} /></ProspField>
          <ProspField label="Onde" hint='Ex.: "Braga, Portugal" ou "Madrid, Spain"'><input style={prospInput} value={b.localizacao} onChange={s('localizacao')} /></ProspField>
          <ProspDrop label="País" value={b.pais} onChange={v => setB(p => ({ ...p, pais: v }))} options={PROSP_PAISES} />
          <ProspField label="Máximo por pesquisa" hint="Até 500 no total"><input type="number" min="1" max="500" style={prospInput} value={b.max_por_pesquisa} onChange={s('max_por_pesquisa')} /></ProspField>
          <ProspField label="Limite de custo (USD)" hint="A Apify pára quando atinge este valor"><input type="number" min="0.5" max="20" step="0.5" style={prospInput} value={b.max_custo_usd} onChange={s('max_custo_usd')} /></ProspField>
        </div>
        {alvo === 'contactos' && <div style={{ fontSize: 11, fontWeight: 650, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-muted)' }}>Pessoa</div>}
        <ProspEscolha on={b.extrair_contactos} label="Emails do website" hint="Custo extra" onClick={() => setB(p => ({ ...p, extrair_contactos: !p.extrair_contactos }))} />
        <ProspEscolha on={b.leads} label="Decisores" hint="Nome, cargo, email e LinkedIn. Custa mais, por pessoa." onClick={() => setB(p => ({ ...p, leads: !p.leads }))} />
        {b.leads && (
          <>
            <ProspField label="Decisores por empresa" hint="Máximo 5"><input type="number" min="1" max="5" style={prospInput} value={b.leads_por_empresa} onChange={s('leads_por_empresa')} /></ProspField>
            {MAPS_DEPTS.map(c => <ProspEscolha key={c.id} on={b.leads_departamentos.includes(c.id)} label={c.label} onClick={() => toggleDept(c.id)} />)}
            <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Sem departamento seleccionado, traz de todos. Sobe o limite de custo: cada pessoa é cobrada à parte.</div>
          </>
        )}
        <div><button type="button" className="btn btn-ai" disabled={busy || !n || !b.localizacao.trim() || (alvo === 'contactos' && !b.extrair_contactos && !b.leads)} onClick={() => onRun(b)}>{busy ? 'A lançar…' : (alvo === 'contactos' ? 'Pesquisar contactos' : `Pesquisar ${n || ''} termo${n === 1 ? '' : 's'}`)}</button></div>
      </>
    } />
  );
}

function ProspFormRede({ rede, busy, onRun, caixa, resultados }) {
  const [b, setB] = React.useState({ pesquisas: '', localizacao: '', pais: 'PT', max_resultados: 20, max_custo_usd: 3 });
  const s = (k) => (ev) => setB(p => ({ ...p, [k]: ev.target.value }));
  const n = b.pesquisas.split(/[,;\n]/).filter(x => x.trim()).length;
  return (
    <ProspColunas caixa={caixa} resultados={resultados} filtros={
      <>
        <div style={prospLinhas}>
          <ProspField label="Segmento" hint="Separa por vírgulas — ex.: decoração de interiores, empresa de reclamos"><input style={prospInput} value={b.pesquisas} onChange={s('pesquisas')} /></ProspField>
          <ProspField label="Zona" hint="Opcional. Ex.: Braga, Porto, Madrid"><input style={prospInput} value={b.localizacao} onChange={s('localizacao')} /></ProspField>
          <ProspDrop label="País" value={b.pais} onChange={v => setB(p => ({ ...p, pais: v }))} options={PROSP_PAISES} />
          <ProspField label="Máximo" hint={rede.id === 'facebook' ? 'Até 50 no total' : 'Até 50 por termo'}><input type="number" min="1" max="50" style={prospInput} value={b.max_resultados} onChange={s('max_resultados')} /></ProspField>
          <ProspField label="Limite de custo (USD)" hint="A Apify pára quando atinge este valor"><input type="number" min="0.5" max="20" step="0.5" style={prospInput} value={b.max_custo_usd} onChange={s('max_custo_usd')} /></ProspField>
        </div>
        <div><button type="button" className="btn btn-ai" disabled={busy || !n} onClick={() => onRun(b)}>{busy ? 'A lançar…' : `Pesquisar ${n || ''} termo${n === 1 ? '' : 's'}`}</button></div>
      </>
    } />
  );
}

function ProspFormGoogle({ busy, onRun, caixa, resultados }) {
  const [b, setB] = React.useState({ pesquisas: '', localizacao: '', pais: 'PT', max_paginas: 1, max_custo_usd: 2 });
  const s = (k) => (ev) => setB(p => ({ ...p, [k]: ev.target.value }));
  const n = b.pesquisas.split(/[,;\n]/).filter(x => x.trim()).length;
  return (
    <ProspColunas caixa={caixa} resultados={resultados} filtros={
      <>
        <div style={prospLinhas}>
          <ProspField label="O que procurar" hint="Um termo por linha ou separados por vírgulas — até 10."><textarea style={{ ...prospInput, minHeight: 72, resize: 'vertical' }} value={b.pesquisas} onChange={s('pesquisas')} /></ProspField>
          <ProspField label="Zona" hint="Acrescentada a cada termo. Ex.: Braga"><input style={prospInput} value={b.localizacao} onChange={s('localizacao')} /></ProspField>
          <ProspDrop label="País" value={b.pais} onChange={v => setB(p => ({ ...p, pais: v }))} options={PROSP_PAISES} />
          <ProspField label="Páginas por termo" hint="Cerca de 10 resultados por página, até 3"><input type="number" min="1" max="3" style={prospInput} value={b.max_paginas} onChange={s('max_paginas')} /></ProspField>
          <ProspField label="Limite de custo (USD)" hint="A Apify pára quando atinge este valor"><input type="number" min="0.5" max="20" step="0.5" style={prospInput} value={b.max_custo_usd} onChange={s('max_custo_usd')} /></ProspField>
        </div>
        <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Uma empresa por site, sem redes sociais nem directórios.</div>
        <div><button type="button" className="btn btn-ai" disabled={busy || !n} onClick={() => onRun(b)}>{busy ? 'A lançar…' : `Pesquisar ${n || ''} termo${n === 1 ? '' : 's'}`}</button></div>
      </>
    } />
  );
}

const APOLLO_TIPOS = [
  { id: 'direccao', label: 'Direcção', hint: 'Gerência e administração' },
  { id: 'comercial', label: 'Comercial', hint: 'Vendas' },
  { id: 'compras', label: 'Compras', hint: 'Aprovisionamento' },
  { id: 'marketing', label: 'Marketing', hint: 'Marketing e comunicação' },
  { id: 'producao', label: 'Produção', hint: 'Operações' },
  { id: 'financeiro', label: 'Financeiro', hint: 'Finanças' },
];
const APOLLO_EMPREGADOS = [
  { id: '1,10', label: '1–10' },
  { id: '11,20', label: '11–20' },
  { id: '21,50', label: '21–50' },
  { id: '51,100', label: '51–100' },
  { id: '101,200', label: '101–200' },
  { id: '201,500', label: '201–500' },
  { id: '501,1000', label: '501–1.000' },
  { id: '1001,2000', label: '1.001–2.000' },
];
const APOLLO_SENIORIDADES = [
  { id: 'owner', label: 'Dono' },
  { id: 'c_suite', label: 'C-level' },
  { id: 'vp', label: 'VP' },
  { id: 'director', label: 'Director' },
  { id: 'manager', label: 'Manager' },
  { id: 'senior', label: 'Sénior' },
];
const GESTOR_CAMPOS = [
  { id: 'website', label: 'Website' },
  { id: 'morada', label: 'Morada' },
  { id: 'codigo_postal', label: 'Código postal' },
  { id: 'cidade', label: 'Cidade' },
  { id: 'nome', label: 'Nome oficial' },
];

function ProspEscolha({ on, label, hint, onClick }) {
  return (
    <button type="button" onClick={onClick} className="prosp-chip" style={{
      textAlign: 'left', padding: '10px 12px', borderRadius: 8, cursor: 'pointer', fontFamily: 'inherit',
      width: '100%', border: `1px solid ${on ? 'var(--ai-500)' : 'var(--border)'}`,
      background: on ? 'color-mix(in oklch, var(--ai-500, #3859D0) 10%, #fff)' : '#fff', color: 'var(--text)',
      transition: 'background .12s, border-color .12s',
    }}>
      <div style={{ fontSize: 13, fontWeight: 650, color: on ? 'var(--ai-500)' : 'var(--text)' }}>{label}</div>
      {hint && <div style={{ fontSize: 12, lineHeight: 1.4, color: 'var(--text-muted)', marginTop: 3 }}>{hint}</div>}
    </button>
  );
}

function ProspPais({ value, onChange }) {
  return (
    <ProspField label="País">
      <select style={prospInput} value={value} onChange={ev => onChange(ev.target.value)}>
        {PROSP_PAISES.map(p => <option key={p.value} value={p.value}>{p.label}</option>)}
      </select>
    </ProspField>
  );
}

function ProspApolloPessoas({ busy, setBusy, setMsg, onDone, marca, caixa, aviso }) {
  const [tarifa, setTarifa] = React.useState(null);
  React.useEffect(() => { prospApi('/apollo/custo').then(setTarifa).catch(() => {}); }, []);
  const [b, setB] = React.useState({ pais: 'PT', localizacoes: '', palavras_chave: '', max: 25 });
  const [tipos, setTipos] = React.useState([]);
  const [senioridades, setSenioridades] = React.useState([]);
  const [res, setRes] = React.useState(null);
  const [sel, setSel] = React.useState([]);
  const [dados, setDados] = React.useState({ linkedin: true, email: false, telemovel: false });
  const s = (k) => (ev) => setB(p => ({ ...p, [k]: ev.target.value }));
  const toggle = (lista, setLista, id) => setLista(lista.includes(id) ? lista.filter(x => x !== id) : [...lista, id]);
  const reportar = caixa.onRascunho;
  React.useEffect(() => {
    const pode = tipos.length > 0 || Boolean((b.palavras_chave || '').trim() || (b.localizacoes || '').trim());
    reportar?.({
      fonte: 'apollo', alvo: 'contactos', pode,
      parametros: { ...b, tipos, senioridades },
      rotulo: (b.palavras_chave || '').trim() || (b.localizacoes || '').trim() || 'Apollo · contactos',
    });
  }, [b, tipos, senioridades, reportar]);
  React.useEffect(() => {
    const p = caixa.pedido;
    if (!p || p.fonte !== 'apollo' || p.alvo !== 'contactos') return;
    const f = p.parametros || {};
    setB({ pais: f.pais || 'PT', localizacoes: f.localizacoes || '', palavras_chave: f.palavras_chave || '', max: f.max || 25 });
    setTipos(Array.isArray(f.tipos) ? f.tipos : []);
    setSenioridades(Array.isArray(f.senioridades) ? f.senioridades : []);
  }, [caixa.pedido && caixa.pedido.n]);
  const procurar = async () => {
    setBusy(true); setMsg(null); setRes(null); setSel([]);
    try {
      const d = await prospApi('/pesquisas/apollo/pessoas/preview', { method: 'POST', body: { filtros: { ...b, tipos, senioridades }, max: Number(b.max) || 25 } });
      setRes(d);
      setSel(d.pessoas.map((_, i) => i));
    } catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
    finally { setBusy(false); }
  };
  const guardar = async () => {
    const pessoas = sel.map(i => res.pessoas[i]).filter(Boolean);
    if (!pessoas.length) return;
    setBusy(true); setMsg(null);
    try {
      const d = await prospApi('/pesquisas/apollo/pessoas', { method: 'POST', body: { filtros: b, pessoas, dados, marca: marca || undefined } });
      setMsg({ tipo: 'ok', texto: `${d.contactos} contactos guardados, ${d.empresas} empresas (${d.empresasNovas} novas, ${d.jaNoGestor} já no Gestor).` });
      setRes(null); setSel([]);
      onDone?.();
    } catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
    finally { setBusy(false); }
  };
  const todas = res && sel.length === res.pessoas.length;
  const nome = (p) => p.nome_completo || [p.nome, p.apelido].filter(Boolean).join(' ') || '—';
  const pessoas = res?.pessoas || [];
  const tabela = (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, minHeight: 280, overflow: 'auto' }}>
      {res && <div style={{ padding: '12px 14px', fontSize: 13, color: 'var(--text-muted)' }}>A Apollo tem {prospNum(res.total)} pessoas. Estás a ver {prospNum(pessoas.length)}. {sel.length} escolhidas. Esta procura não gastou créditos. O endereço e o número só aparecem depois de gravar, e só se forem válidos.</div>}
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead>
          <tr>
            <th style={{ ...prospTh, width: 36 }}>{res && <input type="checkbox" checked={todas} onChange={() => setSel(todas ? [] : pessoas.map((_, i) => i))} />}</th>
            <th style={prospTh}>Contacto</th>
            <th style={prospTh}>Cargo</th>
            <th style={prospTh}>Empresa</th>
            <th style={prospTh}>Email</th>
            <th style={prospTh}>Telemóvel</th>
            <th style={prospTh}>LinkedIn</th>
          </tr>
        </thead>
        <tbody>
          {pessoas.map((p, i) => (
            <tr key={p.apollo_id || nome(p) + i}>
              <td style={prospTd}><input type="checkbox" checked={sel.includes(i)} onChange={() => toggle(sel, setSel, i)} /></td>
              <td style={prospTd}><div style={{ fontWeight: 650 }}>{nome(p)}</div></td>
              <td style={prospTd}>{p.cargo || '—'}</td>
              <td style={prospTd}>{p.empresa?.nome || '—'}</td>
              <td style={prospTd}>{p.has_email ? 'Disponível' : '—'}</td>
              <td style={prospTd}>{p.has_telemovel ? 'Disponível' : '—'}</td>
              <td style={prospTd}>{p.linkedin_url ? <a href={p.linkedin_url} target="_blank" rel="noreferrer" style={{ color: 'var(--ai-500)', textDecoration: 'none' }}>Perfil</a> : '—'}</td>
            </tr>
          ))}
          {!pessoas.length && <tr><td colSpan={7} style={{ ...prospTd, textAlign: 'center', color: 'var(--text-muted)', padding: 28 }}>{busy ? 'A procurar…' : 'Sem resultados.'}</td></tr>}
        </tbody>
      </table>
    </div>
  );
  return (
    <ProspColunas caixa={caixa} resultados={<>{aviso}{tabela}</>} filtros={
      <>
        <ProspSecao titulo="Onde">
          <ProspPais value={b.pais} onChange={v => setB(p => ({ ...p, pais: v }))} />
          <ProspField label="Localizações" hint="Opcional. Ex.: Porto, Braga"><input style={prospInput} value={b.localizacoes} onChange={s('localizacoes')} /></ProspField>
          <ProspField label="Sector" hint="Ex.: printing, signage, interior design"><input style={prospInput} value={b.palavras_chave} onChange={s('palavras_chave')} /></ProspField>
          <ProspField label="Quantas ver" hint="Máximo 100. Ainda não grava."><input type="number" min="1" max="100" style={prospInput} value={b.max} onChange={s('max')} /></ProspField>
        </ProspSecao>
        <ProspSecao titulo="Cargo">
          <ProspGrelha>
            {APOLLO_TIPOS.map(t => <ProspChip key={t.id} on={tipos.includes(t.id)} label={t.label} title={t.hint} onClick={() => toggle(tipos, setTipos, t.id)} />)}
          </ProspGrelha>
        </ProspSecao>
        <ProspSecao titulo="Senioridade">
          <ProspGrelha>
            {APOLLO_SENIORIDADES.map(t => <ProspChip key={t.id} on={senioridades.includes(t.id)} label={t.label} onClick={() => toggle(senioridades, setSenioridades, t.id)} />)}
          </ProspGrelha>
          <span style={{ fontSize: 12, lineHeight: 1.4, color: 'var(--text-dim)' }}>Opcional. Sem escolha, entram todos os níveis.</span>
        </ProspSecao>
        <ProspAviso>Esta procura não gasta créditos. Email e telemóvel não aparecem.</ProspAviso>
        <ProspBotao disabled={busy || !tipos.length} onClick={procurar}>{busy && !res ? 'A procurar…' : 'Procurar contactos'}</ProspBotao>
        {res && (
          <ProspSecao titulo="Gravar na base" separador>
            <ProspEscolha on={dados.linkedin} label="LinkedIn" onClick={() => setDados(d => ({ ...d, linkedin: !d.linkedin }))} />
            <ProspEscolha on={dados.email} label="Email" hint="1 crédito por pessoa. Só entra email verified." onClick={() => setDados(d => ({ ...d, email: !d.email }))} />
            <ProspEscolha on={dados.telemovel} label="Telemóvel" hint="8 créditos por número válido." onClick={() => setDados(d => ({ ...d, telemovel: !d.telemovel }))} />
            {dados.email && <ProspAviso>Até {prospCreditos(sel.length * (tarifa?.email ?? 1), tarifa?.eur_por_credito)}. Só entra email verified.</ProspAviso>}
            {dados.telemovel && <ProspAviso>Até {prospCreditos(sel.length * (tarifa?.telemovel ?? 8), tarifa?.eur_por_credito)}. O número chega depois e só entra se for válido.{tarifa && !tarifa.telemovel_webhook ? ' Falta APOLLO_WEBHOOK_TOKEN no servidor.' : ''}</ProspAviso>}
            <ProspBotao disabled={busy || !sel.length} onClick={guardar}>{busy ? 'A guardar…' : `Guardar ${sel.length} contactos${dados.email || dados.telemovel ? ` · até ${prospCreditos((dados.email ? sel.length * (tarifa?.email ?? 1) : 0) + (dados.telemovel ? sel.length * (tarifa?.telemovel ?? 8) : 0), tarifa?.eur_por_credito)}` : ''}`}</ProspBotao>
          </ProspSecao>
        )}
      </>
    } />
  );
}

function ProspApollo({ busy, setBusy, setMsg, onDone, marca, caixa, aviso }) {
  const [tarifa, setTarifa] = React.useState(null);
  React.useEffect(() => { prospApi('/apollo/custo').then(setTarifa).catch(() => {}); }, []);
  const [b, setB] = React.useState({ pais: 'PT', localizacoes: '', palavras_chave: '', nome: '', empregados: [], max: 25 });
  const [res, setRes] = React.useState(null);
  const [sel, setSel] = React.useState([]);
  const [tipos, setTipos] = React.useState([]);
  const [dados, setDados] = React.useState({ linkedin: true, email: false, telemovel: false });
  const [porEmpresa, setPorEmpresa] = React.useState(3);
  const [gestorOn, setGestorOn] = React.useState(false);
  const [gestorCampos, setGestorCampos] = React.useState(['website', 'morada', 'codigo_postal', 'cidade']);
  const s = (k) => (ev) => setB(p => ({ ...p, [k]: ev.target.value }));
  const toggle = (lista, setLista, id) => setLista(lista.includes(id) ? lista.filter(x => x !== id) : [...lista, id]);
  const reportar = caixa.onRascunho;
  React.useEffect(() => {
    const pode = Boolean((b.palavras_chave || '').trim() || (b.nome || '').trim() || (b.localizacoes || '').trim() || (b.empregados || []).length);
    reportar?.({
      fonte: 'apollo', alvo: 'empresas', pode,
      parametros: { pais: b.pais, localizacoes: b.localizacoes, palavras_chave: b.palavras_chave, nome: b.nome, empregados: b.empregados, max: b.max },
      rotulo: [(b.palavras_chave || '').trim(), (b.nome || '').trim(), (b.localizacoes || '').trim()].filter(Boolean).join(' · ') || 'Apollo · empresas',
    });
  }, [b, reportar]);
  React.useEffect(() => {
    const p = caixa.pedido;
    if (!p || p.fonte !== 'apollo' || p.alvo === 'contactos') return;
    const f = p.parametros || {};
    setB({
      pais: f.pais || 'PT',
      localizacoes: f.localizacoes || '',
      palavras_chave: f.palavras_chave || '',
      nome: f.nome || '',
      empregados: Array.isArray(f.empregados) ? f.empregados : [],
      max: f.max || 25,
    });
  }, [caixa.pedido && caixa.pedido.n]);

  const procurar = async () => {
    setBusy(true); setMsg(null); setRes(null); setSel([]); setTipos([]);
    try {
      const { max, ...filtros } = b;
      const d = await prospApi('/pesquisas/apollo/preview', { method: 'POST', body: { filtros, max: Number(max) || 25 } });
      setRes(d);
      setSel(d.empresas.map((_, i) => i));
    } catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
    finally { setBusy(false); }
  };
  const guardar = async () => {
    const empresas = sel.map(i => res.empresas[i]).filter(Boolean);
    if (!empresas.length) return;
    setBusy(true); setMsg(null);
    try {
      const d = await prospApi('/pesquisas/apollo', {
        method: 'POST',
        body: {
          filtros: b,
          creditos_pagina: res.creditos,
          empresas,
          contactos: { tipos, dados, por_empresa: porEmpresa },
          gestor: { activo: gestorOn, campos: gestorCampos },
          marca: marca || undefined,
        },
      });
      setMsg({ tipo: 'ok', texto: `${d.empresas} empresas guardadas (${d.empresasNovas} novas, ${d.jaNoGestor} já no Gestor), ${d.contactos} contactos, ${d.enriquecidas} completadas com o Gestor pelo NIF.` });
      setRes(null); setSel([]);
      onDone?.();
    } catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
    finally { setBusy(false); }
  };

  const todas = res && sel.length === res.empresas.length;
  const empresas = res?.empresas || [];
  const tabela = (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, minHeight: 280, overflow: 'auto' }}>
      {res && <div style={{ padding: '12px 14px', fontSize: 13, color: 'var(--text-muted)' }}>A Apollo tem {prospNum(res.total)} empresas. Estás a ver {prospNum(empresas.length)}. {sel.length} escolhidas. Esta vista gastou {prospCreditos(res.creditos ?? 0, tarifa?.eur_por_credito)}.</div>}
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead>
          <tr>
            <th style={{ ...prospTh, width: 36 }}>{res && <input type="checkbox" checked={todas} onChange={() => setSel(todas ? [] : empresas.map((_, i) => i))} />}</th>
            <th style={prospTh}>Empresa</th>
            <th style={prospTh}>Website</th>
            <th style={prospTh}>Telefone</th>
            <th style={prospTh}>Local</th>
            <th style={prospTh}>Sector</th>
            <th style={prospTh}>Empregados</th>
          </tr>
        </thead>
        <tbody>
          {empresas.map((e, i) => (
            <tr key={e.apollo_org_id || e.nome + i}>
              <td style={prospTd}><input type="checkbox" checked={sel.includes(i)} onChange={() => toggle(sel, setSel, i)} /></td>
              <td style={prospTd}><div style={{ fontWeight: 650 }}>{e.nome}</div></td>
              <td style={prospTd}>{e.dominio || e.website || '—'}</td>
              <td style={prospTd}>{e.telefone || '—'}</td>
              <td style={prospTd}>{[e.cidade, e.pais].filter(Boolean).join(', ') || '—'}</td>
              <td style={prospTd}>{e.industria || '—'}</td>
              <td style={prospTd}>{e.funcionarios ?? '—'}</td>
            </tr>
          ))}
          {!empresas.length && <tr><td colSpan={7} style={{ ...prospTd, textAlign: 'center', color: 'var(--text-muted)', padding: 28 }}>{busy ? 'A procurar…' : 'Sem resultados.'}</td></tr>}
        </tbody>
      </table>
    </div>
  );
  return (
    <ProspColunas caixa={caixa} resultados={<>{aviso}{tabela}</>} filtros={
      <>
        <ProspSecao titulo="Onde">
          <ProspPais value={b.pais} onChange={v => setB(p => ({ ...p, pais: v }))} />
          <ProspField label="Localizações" hint="Opcional. Ex.: Porto, Braga"><input style={prospInput} value={b.localizacoes} onChange={s('localizacoes')} /></ProspField>
        </ProspSecao>
        <ProspSecao titulo="Empresa">
          <ProspField label="Sector" hint="Ex.: printing, signage, interior design"><input style={prospInput} value={b.palavras_chave} onChange={s('palavras_chave')} /></ProspField>
          <ProspField label="Nome contém"><input style={prospInput} value={b.nome} onChange={s('nome')} /></ProspField>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <span style={{ fontSize: 12, fontWeight: 650 }}>Empregados</span>
            <ProspGrelha>
              {APOLLO_EMPREGADOS.map(t => <ProspChip key={t.id} on={b.empregados.includes(t.id)} label={t.label} onClick={() => setB(p => ({ ...p, empregados: p.empregados.includes(t.id) ? p.empregados.filter(x => x !== t.id) : [...p.empregados, t.id] }))} />)}
            </ProspGrelha>
          </div>
          <ProspField label="Quantas ver" hint="Máximo 100."><input type="number" min="1" max="100" style={prospInput} value={b.max} onChange={s('max')} /></ProspField>
        </ProspSecao>
        <ProspAviso>Ver {b.max || 0} empresas gasta {prospCreditos(Math.max(1, Math.ceil((Number(b.max) || 1) / (tarifa?.por_pagina || 100))) * (tarifa?.pagina_empresas ?? 1), tarifa?.eur_por_credito)}. Ainda não grava.</ProspAviso>
        <ProspBotao disabled={busy} onClick={procurar}>{busy && !res ? 'A procurar…' : 'Procurar empresas'}</ProspBotao>
        {res && (
          <ProspSecao titulo={`Contactos · ${sel.length} empresas`} separador>
            <ProspGrelha>
              {APOLLO_TIPOS.map(t => <ProspChip key={t.id} on={tipos.includes(t.id)} label={t.label} title={t.hint} onClick={() => toggle(tipos, setTipos, t.id)} />)}
            </ProspGrelha>
            {tipos.length > 0 && (
              <>
                <ProspEscolha on={dados.linkedin} label="LinkedIn" onClick={() => setDados(d => ({ ...d, linkedin: !d.linkedin }))} />
                <ProspEscolha on={dados.email} label="Email" hint="1 crédito por pessoa. Só entra email verified." onClick={() => setDados(d => ({ ...d, email: !d.email }))} />
                <ProspEscolha on={dados.telemovel} label="Telemóvel" hint="8 créditos por número válido." onClick={() => setDados(d => ({ ...d, telemovel: !d.telemovel }))} />
                <ProspField label="Por empresa">
                  <select style={prospInput} value={porEmpresa} onChange={ev => setPorEmpresa(Number(ev.target.value))}>
                    {[1, 2, 3, 5].map(n => <option key={n} value={n}>{n}</option>)}
                  </select>
                </ProspField>
                {dados.email && <ProspAviso>Até {prospCreditos(Math.min(sel.length * porEmpresa, 100) * (tarifa?.email ?? 1), tarifa?.eur_por_credito)}. Só entra email verified.</ProspAviso>}
                {dados.telemovel && <ProspAviso>Até {prospCreditos(Math.min(sel.length * porEmpresa, 100) * (tarifa?.telemovel ?? 8), tarifa?.eur_por_credito)}. O número chega depois e só entra se for válido.{tarifa && !tarifa.telemovel_webhook ? ' Falta APOLLO_WEBHOOK_TOKEN no servidor.' : ''}</ProspAviso>}
              </>
            )}
            <ProspEscolha on={gestorOn} label="Usar dados do Gestor" hint="Só quando o NIF é o mesmo." onClick={() => setGestorOn(v => !v)} />
            {gestorOn && (
              <ProspGrelha>
                {GESTOR_CAMPOS.map(c => <ProspChip key={c.id} on={gestorCampos.includes(c.id)} label={c.label} onClick={() => toggle(gestorCampos, setGestorCampos, c.id)} />)}
              </ProspGrelha>
            )}
            <ProspBotao disabled={busy || !sel.length} onClick={guardar}>{busy ? 'A guardar…' : (() => {
              const pessoas = tipos.length ? Math.min(sel.length * porEmpresa, 100) : 0;
              const extra = (dados.email ? pessoas * (tarifa?.email ?? 1) : 0) + (dados.telemovel ? pessoas * (tarifa?.telemovel ?? 8) : 0);
              if (extra) return `Guardar ${sel.length} · até ${prospCreditos(extra, tarifa?.eur_por_credito)}`;
              return tipos.length ? `Guardar ${sel.length} e ir buscar contactos` : `Guardar ${sel.length} empresas`;
            })()}</ProspBotao>
          </ProspSecao>
        )}
      </>
    } />
  );
}

function ProspFormFicheiro({ busy, setBusy, setMsg, onDone, marca, caixa, aviso, alvo }) {
  const [file, setFile] = React.useState(null);
  const [prev, setPrev] = React.useState(null);
  const [mapping, setMapping] = React.useState({});
  const [pais, setPais] = React.useState('PT');
  const [descricao, setDescricao] = React.useState('');

  const carregar = async (f) => {
    setFile(f); setPrev(null); setMsg(null);
    if (!f) return;
    const form = new FormData(); form.append('file', f);
    setBusy(true);
    try { const d = await prospApi('/import/preview', { method: 'POST', form }); setPrev(d); setMapping(d.sugestao || {}); }
    catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
    finally { setBusy(false); }
  };
  const importar = async () => {
    const form = new FormData();
    form.append('file', file); form.append('mapping', JSON.stringify(mapping)); form.append('pais', pais);
    if (marca) form.append('marca', marca);
    if (descricao) form.append('descricao', descricao);
    setBusy(true); setMsg(null);
    try {
      const d = await prospApi('/import', { method: 'POST', form });
      setMsg({ tipo: 'ok', texto: `${d.linhas} linhas lidas → ${d.empresas} empresas (${d.empresasNovas} novas, ${d.jaNoGestor} já no Gestor) e ${d.contactos} contactos.` });
      setPrev(null); setFile(null); onDone?.();
    } catch (e) { setMsg({ tipo: 'erro', texto: e.message }); }
    finally { setBusy(false); }
  };

  const amostra = !prev ? (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, minHeight: 280, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--text-muted)', fontSize: 13, padding: 24, textAlign: 'center' }}>A amostra do ficheiro aparece aqui.</div>
  ) : (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, overflow: 'auto' }}>
      <div style={{ padding: '12px 14px', fontSize: 13 }}><strong>{prev.nome}</strong> · folha {prev.folha} · {prospNum(prev.total)} linhas</div>
      <table style={{ borderCollapse: 'collapse', fontSize: 12 }}>
        <thead><tr>{prev.cabecalhos.map(h => <th key={h} style={prospTh}>{h}</th>)}</tr></thead>
        <tbody>{prev.amostra.map((r, i) => <tr key={i}>{prev.cabecalhos.map(h => <td key={h} style={{ ...prospTd, fontSize: 12, whiteSpace: 'nowrap' }}>{String(r[h] ?? '')}</td>)}</tr>)}</tbody>
      </table>
    </div>
  );
  return (
    <ProspColunas caixa={caixa} resultados={<>{aviso}{amostra}</>} filtros={
      <>
        <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{alvo === 'contactos' ? 'Mapeia nome, cargo, email e telemóvel. A coluna Empresa continua a ser obrigatória: cada pessoa fica ligada a uma empresa.' : 'Mapeia a empresa. Nome, cargo, email e telemóvel entram se o ficheiro os tiver.'}</div>
        <div style={prospLinhas}>
          <ProspField label="Ficheiro" hint=".xlsx, .xls ou .csv — até 20 000 linhas"><input type="file" accept=".xlsx,.xls,.csv" onChange={ev => carregar(ev.target.files?.[0] || null)} /></ProspField>
          <ProspDrop label="País" value={pais} onChange={setPais} options={PROSP_PAISES} />
          <ProspField label="Origem da lista" hint="Ex.: Feira FESPA 2026"><input style={prospInput} value={descricao} onChange={ev => setDescricao(ev.target.value)} /></ProspField>
          {prev && prev.campos.map(c => (
            <ProspField key={c.key} label={c.label + (c.key === 'empresa.nome' ? ' *' : '')}>
              <select style={prospInput} value={mapping[c.key] || ''} onChange={ev => setMapping(m => ({ ...m, [c.key]: ev.target.value || undefined }))}>
                <option value="">— ignorar —</option>
                {prev.cabecalhos.map(h => <option key={h} value={h}>{h}</option>)}
              </select>
            </ProspField>
          ))}
        </div>
        {prev && <div><button type="button" className="btn btn-ai" disabled={busy || !mapping['empresa.nome']} onClick={importar}>{busy ? 'A importar…' : `Importar ${prospNum(prev.total)} linhas`}</button></div>}
      </>
    } />
  );
}

function ProspFormValidar({ busy, onRun, caixa, aviso, resultados, alvo }) {
  const [b, setB] = React.useState({ estado: 'novo', limite: 100, so_por_validar: true });
  return (
    <ProspColunas caixa={caixa} resultados={<>{aviso}{resultados}</>} filtros={
      <>
        <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>
          Verifica o NIF e o telefone da empresa, e o email e o telemóvel de cada contacto. Empresa com um canal válido passa a Validado.
        </div>
        <div style={prospLinhas}>
          <ProspField label="Estado"><select style={prospInput} value={b.estado} onChange={ev => setB(p => ({ ...p, estado: ev.target.value }))}><option value="">Todos</option>{PROSP_ESTADOS.map(e => <option key={e.id} value={e.id}>{e.label}</option>)}</select></ProspField>
          <ProspField label="Quantas empresas" hint="Até 300 por execução"><input type="number" min="1" max="300" style={prospInput} value={b.limite} onChange={ev => setB(p => ({ ...p, limite: ev.target.value }))} /></ProspField>
        </div>
        <ProspEscolha on={b.so_por_validar} label="Só por validar" hint="Ignora empresas que já passaram por esta verificação." onClick={() => setB(p => ({ ...p, so_por_validar: !p.so_por_validar }))} />
        <div><button type="button" className="btn btn-ai" disabled={busy} onClick={() => onRun({ ...b, limite: Number(b.limite) || 100 })}>Validar</button></div>
      </>
    } />
  );
}

// ── Execuções ─────────────────────────────────────────────────────────────────

function ProspExecucoes({ tick, desde, ate, marca }) {
  const [rows, setRows] = React.useState([]);
  const [erro, setErro] = React.useState('');
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    prospApi('/runs', { query: { desde, ate, marca } }).then(d => { setRows(d.rows); setErro(''); }).catch(e => setErro(e.message));
  }, [tick, t, desde, ate, marca]);
  const aCorrer = rows.some(r => r.estado === 'a_correr');
  React.useEffect(() => {
    if (!aCorrer) return;
    const id = setInterval(() => setT(x => x + 1), 8000);
    return () => clearInterval(id);
  }, [aCorrer]);
  const cor = { a_correr: '#d97706', concluido: '#16a34a', erro: '#b91c1c' };
  return (
    <ProspCard style={{ padding: 0, overflow: 'auto' }}>
      {erro && <div style={{ padding: 12 }}><ProspMsg msg={{ tipo: 'erro', texto: erro }} /></div>}
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>{['#', 'Fonte', 'O quê', 'Estado', 'Empresas', 'Contactos', 'Custo', 'Por', 'Início', 'Resultado'].map(h => <th key={h} style={prospTh}>{h}</th>)}</tr></thead>
        <tbody>
          {rows.map(r => (
            <tr key={r.id}>
              <td style={prospTd}>{r.id}</td>
              <td style={prospTd}>{PROSP_FONTES[r.fonte] || r.fonte}</td>
              <td style={{ ...prospTd, maxWidth: 280 }}>{r.referencia || '—'}</td>
              <td style={{ ...prospTd, color: cor[r.estado], fontWeight: 600, whiteSpace: 'nowrap' }}>{r.estado === 'a_correr' ? 'A correr…' : r.estado === 'erro' ? 'Erro' : 'Concluído'}</td>
              <td style={prospTd}>{r.n_empresas ?? '—'}</td>
              <td style={prospTd}>{r.n_contactos ?? '—'}</td>
              <td style={prospTd}>{prospUsd(r.custo_usd)}</td>
              <td style={{ ...prospTd, fontSize: 12 }}>{r.criado_por || '—'}</td>
              <td style={{ ...prospTd, fontSize: 12, whiteSpace: 'nowrap' }}>{prospData(r.iniciado_em)}</td>
              <td style={{ ...prospTd, fontSize: 12, color: r.estado === 'erro' ? '#b91c1c' : 'var(--text-muted)', maxWidth: 360 }}>{r.notas || ''}</td>
            </tr>
          ))}
          {!rows.length && <tr><td colSpan={10} style={{ ...prospTd, color: 'var(--text-muted)', textAlign: 'center', padding: 30 }}>Ainda sem execuções.</td></tr>}
        </tbody>
      </table>
    </ProspCard>
  );
}

// ── Ecrã ──────────────────────────────────────────────────────────────────────

function prospIsoDia(d) {
  const x = new Date(d);
  if (Number.isNaN(x.getTime())) return '';
  return `${x.getFullYear()}-${String(x.getMonth() + 1).padStart(2, '0')}-${String(x.getDate()).padStart(2, '0')}`;
}

function ProspIcone({ children, onClick, activo, label }) {
  return (
    <button type="button" aria-label={label} onMouseDown={e => e.stopPropagation()} onClick={onClick} style={{
      width: 30, height: 30, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
      border: `1px solid ${activo ? 'var(--ai-500)' : 'var(--border)'}`, borderRadius: 6,
      background: activo ? 'color-mix(in oklch, var(--ai-500) 10%, #fff)' : '#fff',
      color: activo ? 'var(--ai-500)' : 'var(--text)', cursor: 'pointer', padding: 0,
    }}>{children}</button>
  );
}

function ProspMenu({ items, activo, onOpen }) {
  const [open, setOpen] = React.useState(false);
  const [foco, setFoco] = React.useState(-1);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onClick = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('mousedown', onClick);
    document.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('mousedown', onClick); document.removeEventListener('keydown', onKey); };
  }, [open]);
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <ProspIcone label="Menu" activo={open} onClick={() => { setOpen(v => !v); setFoco(-1); onOpen?.(); }}>
        <svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"><path d="M2.5 4h11M2.5 8h11M2.5 12h11" /></svg>
      </ProspIcone>
      {open && (
        <div role="menu" style={{
          position: 'absolute', top: 'calc(100% + 6px)', right: 0, zIndex: 70,
          background: '#fff', border: '1px solid var(--border)', borderRadius: 8,
          boxShadow: '0 12px 32px rgba(17,41,84,0.14)', minWidth: 260, padding: 4,
        }}>
          {items.map((it, i) => (
            <button key={it.id} type="button" role="menuitem"
              onClick={() => { setOpen(false); it.onClick(); }}
              onMouseEnter={() => setFoco(i)} onMouseLeave={() => setFoco(-1)}
              style={{
                display: 'flex', alignItems: 'center', gap: 8, width: '100%', textAlign: 'left',
                background: foco === i ? 'color-mix(in oklch, var(--ai-500) 10%, #fff)' : 'transparent',
                color: activo === it.id || foco === i ? 'var(--ai-500)' : 'var(--text)',
                border: 'none', padding: '8px 10px', borderRadius: 6, cursor: 'pointer', fontFamily: 'inherit',
              }}>
              <span style={{ flex: 1, minWidth: 0 }}>
                <span style={{ display: 'block', fontSize: 13, fontWeight: 650 }}>{it.label}</span>
                {it.sub && <span style={{ display: 'block', fontSize: 11, color: 'var(--text-muted)', fontWeight: 400, marginTop: 1 }}>{it.sub}</span>}
              </span>
              {activo === it.id && <span style={{ color: 'var(--ai-500)' }}>✓</span>}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function ProspBusca({ marca, desde, ate, onOpen, onClose }) {
  const [q, setQ] = React.useState('');
  const [rows, setRows] = React.useState([]);
  const [foco, setFoco] = React.useState(0);
  const [loading, setLoading] = React.useState(false);
  const inputRef = React.useRef(null);
  React.useEffect(() => { inputRef.current?.focus(); }, []);
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [onClose]);
  React.useEffect(() => {
    const termo = q.trim();
    if (termo.length < 2) { setRows([]); setLoading(false); return; }
    let stop = false;
    setLoading(true);
    const t = setTimeout(() => {
      Promise.all([
        prospApi('/empresas', { query: { q: termo, marca, desde, ate, limit: 6, ordem: 'nome' } }),
        prospApi('/contactos', { query: { q: termo, marca, desde, ate, limit: 6, ordem: 'nome' } }),
      ]).then(([emp, pes]) => {
        if (stop) return;
        const empresas = (emp.rows || []).map(r => ({ ...r, tipo: 'empresa' }));
        const contactos = (pes.rows || []).map(r => ({ ...r, tipo: 'contacto' }));
        setRows([...empresas, ...contactos]);
        setFoco(0);
      }).catch(() => { if (!stop) setRows([]); })
        .finally(() => { if (!stop) setLoading(false); });
    }, 180);
    return () => { stop = true; clearTimeout(t); };
  }, [q, marca, desde, ate]);
  const abrir = (r) => {
    if (!r) return;
    onOpen(r.tipo === 'contacto' ? { id: r.empresa_id, nome: r.empresa_nome, pais: r.pais, fonte: r.fonte, estado: r.empresa_estado } : r);
    onClose();
  };
  const onKeyDown = (e) => {
    if (e.key === 'ArrowDown') { e.preventDefault(); setFoco(i => Math.min(rows.length - 1, i + 1)); }
    if (e.key === 'ArrowUp') { e.preventDefault(); setFoco(i => Math.max(0, i - 1)); }
    if (e.key === 'Enter') { e.preventDefault(); abrir(rows[foco]); }
  };
  const termo = q.trim();
  return (
    <div role="dialog" aria-label="Procurar empresas e contactos" onMouseDown={onClose} style={{
      position: 'fixed', inset: 0, zIndex: 9999, background: 'rgba(0,0,0,.78)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24,
    }}>
      <button type="button" aria-label="Fechar" onMouseDown={e => e.stopPropagation()} onClick={onClose} style={{
        position: 'absolute', top: 18, right: 22, width: 36, height: 36, border: 'none', background: 'transparent',
        color: '#fff', fontSize: 26, lineHeight: 1, cursor: 'pointer', fontFamily: 'inherit',
      }}>×</button>
      <div onMouseDown={e => e.stopPropagation()} style={{ width: 'min(920px, 100%)' }}>
        <style>{'.prosp-procurar::placeholder{color:rgba(255,255,255,.65)}'}</style>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16, borderBottom: '1px solid rgba(255,255,255,.85)', paddingBottom: 8 }}>
          <input ref={inputRef} className="prosp-procurar" value={q} onChange={e => setQ(e.target.value)} onKeyDown={onKeyDown}
            placeholder="Procurar" aria-label="Procurar"
            style={{ flex: 1, height: 48, border: 'none', outline: 'none', background: 'transparent', color: '#fff', fontSize: 22, fontFamily: 'inherit', fontWeight: 400 }} />
          <svg width="22" height="22" viewBox="0 0 16 16" fill="none" stroke="#fff" strokeWidth="1.6" strokeLinecap="round" aria-hidden="true"><circle cx="7" cy="7" r="4.25" /><path d="M10.5 10.5L13.5 13.5" /></svg>
        </div>
        {termo.length >= 2 && (
          <div style={{ marginTop: 8 }}>
            {loading && !rows.length && <div style={{ padding: '12px 4px', fontSize: 14, color: 'rgba(255,255,255,.75)' }}>A procurar…</div>}
            {!loading && !rows.length && <div style={{ padding: '12px 4px', fontSize: 14, color: 'rgba(255,255,255,.75)' }}>Nenhuma empresa nem contacto.</div>}
            {rows.map((r, i) => (
              <button key={`${r.tipo}-${r.id}`} type="button" onMouseEnter={() => setFoco(i)} onClick={() => abrir(r)} style={{
                display: 'flex', width: '100%', textAlign: 'left', gap: 12, alignItems: 'baseline',
                background: i === foco ? 'rgba(255,255,255,.14)' : 'transparent',
                border: 'none', borderRadius: 6, padding: '10px 8px', cursor: 'pointer', fontFamily: 'inherit', color: '#fff',
              }}>
                <span style={{ fontSize: 11, fontWeight: 650, letterSpacing: '.04em', textTransform: 'uppercase', color: 'rgba(255,255,255,.6)', minWidth: 72 }}>{r.tipo === 'contacto' ? 'Contacto' : 'Empresa'}</span>
                <span style={{ fontSize: 16, fontWeight: 600 }}>{r.tipo === 'contacto' ? (r.nome_completo || [r.nome, r.apelido].filter(Boolean).join(' ') || '—') : r.nome}</span>
                <span style={{ fontSize: 13, color: 'rgba(255,255,255,.72)' }}>{r.tipo === 'contacto' ? [r.cargo, r.empresa_nome, r.email].filter(Boolean).join(' · ') : [r.dominio, r.cidade, r.pais].filter(Boolean).join(' · ')}</span>
              </button>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

const prospNorm = (s) => String(s || '').normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase().replace(/\s+/g, ' ').trim();

function prospOrdemMarca(nomes) {
  const tabs = (window.MKT_BRANDS || [
    { nome: 'Mimaki' }, { nome: 'BIOND' }, { nome: 'Decal' },
  ]).map(b => prospNorm(b.nome || b.name));
  return [...nomes].sort((a, b) => {
    const ia = tabs.indexOf(prospNorm(a));
    const ib = tabs.indexOf(prospNorm(b));
    return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib) || String(a).localeCompare(String(b), 'pt');
  });
}

function prospRotuloContrato(v) {
  const n = prospNorm(v);
  if (n === 'gold') return 'Gold';
  if (n === 'platino') return 'Platino';
  return v || '';
}

function prospEmails(p) {
  return Array.isArray(p?.emails) ? p.emails.filter(Boolean) : [];
}

function prospIdPartner(p) {
  return `${p.id}|${p.marca || ''}`;
}

const PROSP_ZONAS = {
  PT: ['Açores', 'Aveiro', 'Beja', 'Braga', 'Bragança', 'Castelo Branco', 'Coimbra', 'Évora', 'Faro', 'Guarda', 'Leiria', 'Lisboa', 'Madeira', 'Portalegre', 'Porto', 'Santarém', 'Setúbal', 'Viana do Castelo', 'Vila Real', 'Viseu'],
  ES: ['Andalucía', 'Aragón', 'Asturias', 'Canarias', 'Cantabria', 'Castilla y León', 'Castilla-La Mancha', 'Cataluña', 'Ceuta', 'Comunidad de Madrid', 'Comunidad Valenciana', 'Extremadura', 'Galicia', 'Illes Balears', 'La Rioja', 'Melilla', 'Navarra', 'País Vasco (Euskadi)', 'Región de Murcia'],
};
const PROSP_MARCAS_MERCADO = ['Mimaki', 'BIOND', 'Decal', 'AllDecor', 'Sensek', 'NetScreen'];

function ProspMercadoCats({ items, value, onChange }) {
  return (
    <div style={{ display: 'flex', gap: 12 }}>
      {items.map(k => {
        const on = value === k.id;
        return (
          <button key={k.id} type="button" onClick={() => onChange(k.id)} style={{ flex: '1 1 0', textAlign: 'left', background: '#fff', border: `1px solid ${on ? k.accent : 'var(--border)'}`, borderRadius: 8, padding: '12px 16px 0', cursor: 'pointer', fontFamily: 'inherit', display: 'flex', flexDirection: 'column', gap: 4, overflow: 'hidden' }}>
            <div style={{ fontSize: 9.5, fontWeight: 600, letterSpacing: '0.10em', textTransform: 'uppercase', color: on ? k.accent : 'var(--text-muted)', fontFamily: 'var(--font-mono)' }}>{k.label}</div>
            <div style={{ fontSize: 22, fontWeight: 700, fontFamily: 'var(--font-display)', color: k.accent, lineHeight: 1, paddingBottom: 10 }}>{prospNum(k.n)}</div>
            <div style={{ height: 3, background: 'var(--bg-sunken)', overflow: 'hidden' }}><div style={{ height: '100%', width: on ? '100%' : '0%', background: k.accent }} /></div>
          </button>
        );
      })}
    </div>
  );
}

function ProspZonaBtn({ zona, on, admin, mostrarMarca, mostrarEquipa, onClick }) {
  return (
    <button type="button" onClick={onClick} disabled={!admin} title={zona.detalhe || zona.zona} style={{
      textAlign: 'left', borderRadius: 8, padding: '7px 10px', cursor: admin ? 'pointer' : 'default', fontFamily: 'inherit', maxWidth: 320,
      border: `1px solid ${on ? 'var(--ai-500)' : 'var(--border)'}`,
      background: on ? 'color-mix(in oklch, var(--ai-500, #3859D0) 10%, #fff)' : '#fff',
      color: 'var(--text)',
    }}>
      <div style={{ fontSize: 12.5, fontWeight: 650 }}>{zona.zona}</div>
      {zona.detalhe ? <div style={{ fontSize: 11, lineHeight: 1.35, color: 'var(--text-muted)', marginTop: 2 }}>{zona.detalhe}</div> : null}
      {(mostrarMarca || mostrarEquipa) && (
        <div style={{ fontSize: 10, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-dim)', marginTop: 4 }}>{[mostrarMarca ? zona.marca : '', mostrarEquipa ? zona.equipa_code : '', zona.pais].filter(Boolean).join(' · ')}</div>
      )}
    </button>
  );
}

function prospPessoasDe(rows) {
  const mapa = new Map();
  rows.forEach(r => {
    if (!mapa.has(r.pessoa_nome)) mapa.set(r.pessoa_nome, { nome: r.pessoa_nome, email: '', equipas: new Set(), zs: [] });
    const p = mapa.get(r.pessoa_nome);
    if (r.colaborador_email) p.email = r.colaborador_email;
    if (r.equipa_code) p.equipas.add(r.equipa_code);
    p.zs.push(r);
  });
  return [...mapa.values()].map(p => ({
    nome: p.nome,
    email: p.email,
    equipas: [...p.equipas],
    zs: [...p.zs].sort((a, b) => a.zona.localeCompare(b.zona, 'pt') || String(a.marca).localeCompare(String(b.marca), 'pt')),
  })).sort((a, b) => a.nome.localeCompare(b.nome, 'pt'));
}

function prospRankMarca(nome) {
  const i = PROSP_MARCAS_MERCADO.findIndex(m => prospNorm(m) === prospNorm(nome));
  return i < 0 ? 99 : i;
}

function ProspMercados({ marca, marcaLabel, filtroSlot, admin }) {
  const [cat, setCat] = React.useState('equipas');
  const [pais, setPais] = React.useState('');
  const [marcaLocal, setMarcaLocal] = React.useState('');
  const [q, setQ] = React.useState('');
  const [territorios, setTerritorios] = React.useState([]);
  const [partners, setPartners] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [erro, setErro] = React.useState('');
  const [aviso, setAviso] = React.useState('');
  const [edicao, setEdicao] = React.useState(null);
  const [aGravar, setAGravar] = React.useState(false);
  const [confirmar, setConfirmar] = React.useState(false);

  const carregar = React.useCallback(() => {
    setLoading(true);
    return Promise.all([prospApi('/mercados/territorios'), prospApi('/mercados/partners')])
      .then(([t, p]) => { setTerritorios(t.rows || []); setPartners(p.rows || []); setErro(''); })
      .catch(e => setErro(e.message))
      .finally(() => setLoading(false));
  }, []);
  React.useEffect(() => { carregar(); }, [carregar]);
  React.useEffect(() => { setEdicao(null); setConfirmar(false); }, [marca, cat]);

  const marcaUsada = marcaLabel || marcaLocal;
  const qn = prospNorm(q);
  const baseTerr = React.useMemo(() => territorios.filter(r => {
    if (marcaUsada && prospNorm(r.marca) !== prospNorm(marcaUsada)) return false;
    if (pais && r.pais !== pais) return false;
    if (qn && ![r.pessoa_nome, r.zona, r.detalhe, r.equipa_code, r.colaborador_email, r.marca].some(v => prospNorm(v).includes(qn))) return false;
    return true;
  }), [territorios, marcaUsada, pais, qn]);
  const pessoas = React.useMemo(() => prospPessoasDe(baseTerr), [baseTerr]);
  const equipas = React.useMemo(() => {
    const mapa = new Map();
    baseTerr.forEach(r => {
      const code = r.equipa_code || 'Sem equipa';
      if (!mapa.has(code)) mapa.set(code, []);
      mapa.get(code).push(r);
    });
    return [...mapa.entries()].map(([code, zs]) => {
      const marcas = [...new Set(zs.map(z => z.marca))];
      const paises = [...new Set(zs.map(z => z.pais))];
      const partidas = [];
      const porZona = new Map();
      zs.forEach(z => {
        const k = `${z.pais}|${z.zona}`;
        if (!porZona.has(k)) porZona.set(k, []);
        if (!porZona.get(k).includes(z.pessoa_nome)) porZona.get(k).push(z.pessoa_nome);
      });
      porZona.forEach((nomes, k) => { if (nomes.length > 1) partidas.push({ zona: k.split('|')[1], nomes }); });
      return { code, marcas, paises, pessoas: prospPessoasDe(zs), partidas, nZonas: zs.length };
    }).sort((a, b) => prospRankMarca(a.marcas[0]) - prospRankMarca(b.marcas[0]) || a.code.localeCompare(b.code, 'pt'));
  }, [baseTerr]);
  const baseP = React.useMemo(() => partners.filter(p => {
    if (marcaUsada && prospNorm(p.marca) !== prospNorm(marcaUsada)) return false;
    if (pais && p.pais !== pais) return false;
    if (qn && ![p.nome, p.territorio, p.segmento, p.contrato, p.marca, ...(prospEmails(p))].some(v => prospNorm(v).includes(qn))) return false;
    return true;
  }), [partners, marcaUsada, pais, qn]);
  const gruposPartner = React.useMemo(() => {
    const mapa = new Map();
    baseP.forEach(p => {
      const marcaNome = p.marca || 'Sem marca';
      if (!mapa.has(marcaNome)) mapa.set(marcaNome, []);
      mapa.get(marcaNome).push(p);
    });
    return prospOrdemMarca([...mapa.keys()]).map(nome => {
      const rows = mapa.get(nome).slice().sort((a, b) => String(a.pais).localeCompare(String(b.pais)) || a.nome.localeCompare(b.nome, 'pt'));
      const porPais = new Map();
      rows.forEach(r => {
        if (!porPais.has(r.pais)) porPais.set(r.pais, []);
        porPais.get(r.pais).push(r);
      });
      return { nome, paises: [...porPais.entries()] };
    });
  }, [baseP]);

  const marcasOpcoes = React.useMemo(() => {
    const nomes = new Set([...territorios.map(r => r.marca), ...partners.map(p => p.marca)].filter(Boolean));
    PROSP_MARCAS_MERCADO.forEach(m => nomes.add(m));
    return prospOrdemMarca([...nomes]);
  }, [territorios, partners]);

  const abrirZona = (r, ancora) => {
    if (!admin) return;
    setAviso(''); setConfirmar(false); setErro('');
    setEdicao({
      tipo: 'zona', id: r.id, ancora, marca: r.marca, pais: r.pais, zona: r.zona, detalhe: r.detalhe || '',
      pessoa_nome: r.pessoa_nome, colaborador_email: r.colaborador_email || '', equipa_code: r.equipa_code || '',
    });
  };
  const novaZona = (pessoa, equipaCode, ancora) => {
    if (!admin) return;
    setAviso(''); setConfirmar(false); setErro('');
    const amostra = pessoa?.zs?.[0];
    setEdicao({
      tipo: 'zona', id: null, ancora: ancora || '',
      marca: marcaUsada || amostra?.marca || 'Mimaki',
      pais: pais || amostra?.pais || 'PT',
      zona: '', detalhe: '',
      pessoa_nome: pessoa?.nome || '',
      colaborador_email: pessoa?.email || '',
      equipa_code: equipaCode || pessoa?.equipas?.[0] || '',
    });
  };
  const abrirPartner = (r) => {
    if (!admin || !r.marca_id) return;
    setAviso(''); setConfirmar(false); setErro('');
    setEdicao({
      tipo: 'partner', id: r.marca_id, nome: r.nome, marca: r.marca || '', pais: r.pais,
      territorio: r.territorio || '', contrato: r.contrato || '', segmento: r.segmento || '',
    });
  };
  const setCampo = (k, v) => { setConfirmar(false); setEdicao(p => (p ? { ...p, [k]: v } : p)); };
  const gravar = async () => {
    if (!edicao) return;
    setAGravar(true); setErro(''); setAviso('');
    try {
      if (edicao.tipo === 'partner') {
        await prospApi(`/mercados/partners/${edicao.id}`, { method: 'PATCH', body: { territorio: edicao.territorio, contrato: edicao.contrato, segmento: edicao.segmento } });
        setAviso('Território do partner actualizado.');
      } else {
        const body = {
          marca: edicao.marca, pais: edicao.pais, zona: edicao.zona, detalhe: edicao.detalhe,
          pessoa_nome: edicao.pessoa_nome, colaborador_email: edicao.colaborador_email, equipa_code: edicao.equipa_code,
        };
        await prospApi(edicao.id ? `/mercados/territorios/${edicao.id}` : '/mercados/territorios', { method: edicao.id ? 'PATCH' : 'POST', body });
        setAviso(edicao.id ? 'Território actualizado.' : 'Território criado.');
      }
      setEdicao(null);
      await carregar();
    } catch (e) { setErro(e.message); }
    finally { setAGravar(false); }
  };
  const retirar = async () => {
    if (!edicao?.id || edicao.tipo !== 'zona') return;
    if (!confirmar) { setConfirmar(true); return; }
    setAGravar(true); setErro('');
    try {
      await prospApi(`/mercados/territorios/${edicao.id}`, { method: 'DELETE' });
      setEdicao(null); setConfirmar(false);
      setAviso('Zona retirada.');
      await carregar();
    } catch (e) { setErro(e.message); }
    finally { setAGravar(false); }
  };

  const zonasDoPais = PROSP_ZONAS[edicao?.pais] || PROSP_ZONAS.PT;
  const formulario = edicao && edicao.tipo === 'zona' && (
    <div style={{ marginTop: 12, padding: 12, borderRadius: 8, background: '#f8fafc', border: '1px solid var(--border)', display: 'flex', flexDirection: 'column', gap: 12 }}>
      <div style={{ fontWeight: 650 }}>{edicao.id ? `${edicao.pessoa_nome} · ${edicao.zona || 'zona'}` : 'Nova zona'}</div>
      <ProspGrelha>
        <ProspField label="Comercial"><input style={prospInput} list="prosp-comerciais" value={edicao.pessoa_nome} onChange={e => setCampo('pessoa_nome', e.target.value)} /></ProspField>
        <ProspField label="Email"><input style={prospInput} value={edicao.colaborador_email} onChange={e => setCampo('colaborador_email', e.target.value)} /></ProspField>
        <ProspField label="Equipa"><input style={prospInput} list="prosp-equipas" value={edicao.equipa_code} onChange={e => setCampo('equipa_code', e.target.value)} /></ProspField>
        <ProspField label="Marca">
          <select style={prospInput} value={edicao.marca} onChange={e => setCampo('marca', e.target.value)}>
            {PROSP_MARCAS_MERCADO.map(m => <option key={m} value={m}>{m}</option>)}
          </select>
        </ProspField>
        <ProspField label="País">
          <select style={prospInput} value={edicao.pais} onChange={e => setEdicao(p => ({ ...p, pais: e.target.value, zona: (PROSP_ZONAS[e.target.value] || []).includes(p.zona) ? p.zona : '' }))}>
            <option value="PT">Portugal</option>
            <option value="ES">Espanha</option>
          </select>
        </ProspField>
        <ProspField label="Zona">
          <select style={prospInput} value={edicao.zona} onChange={e => setCampo('zona', e.target.value)}>
            <option value="">Escolher…</option>
            {zonasDoPais.map(z => <option key={z} value={z}>{z}</option>)}
          </select>
        </ProspField>
        <ProspField label="Detalhe"><input style={prospInput} value={edicao.detalhe} onChange={e => setCampo('detalhe', e.target.value)} placeholder="Parte do distrito, se for dividida" /></ProspField>
      </ProspGrelha>
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
        <button type="button" className="btn btn-sm btn-ai" disabled={aGravar} onClick={gravar}>{aGravar ? 'A gravar…' : 'Guardar'}</button>
        {edicao.id && <button type="button" className="btn btn-sm" disabled={aGravar} onClick={retirar}>{confirmar ? 'Confirmar e retirar' : 'Retirar zona'}</button>}
        <button type="button" className="btn btn-sm btn-ghost" disabled={aGravar} onClick={() => { setEdicao(null); setConfirmar(false); }}>Cancelar</button>
      </div>
    </div>
  );
  const formAqui = (ancora) => (edicao?.tipo === 'zona' && edicao.ancora === ancora ? formulario : null);

  const blocoPessoa = (pessoa, equipaCode, ancoraBase) => {
    const ancora = `${ancoraBase}|${pessoa.nome}`;
    return (
      <div key={ancora} style={{ padding: '14px 16px', borderTop: '1px solid var(--border)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'flex-start' }}>
          <div>
            <div style={{ fontWeight: 650 }}>{pessoa.nome}</div>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>{pessoa.email || 'Sem email no Gestor'}</div>
          </div>
          {admin && <button type="button" className="btn btn-sm btn-ghost" onClick={() => novaZona(pessoa, equipaCode, ancora)}>+ Zona</button>}
        </div>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 10 }}>
          {pessoa.zs.map(z => (
            <ProspZonaBtn key={z.id} zona={z} admin={admin} on={edicao?.tipo === 'zona' && edicao.id === z.id}
              mostrarMarca={!marcaUsada && new Set(pessoa.zs.map(x => x.marca)).size > 1}
              mostrarEquipa={!equipaCode && pessoa.equipas.length > 1}
              onClick={() => abrirZona(z, ancora)} />
          ))}
        </div>
        {formAqui(ancora)}
      </div>
    );
  };

  const vazio = (texto) => (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 28, textAlign: 'center', color: 'var(--text-muted)', fontSize: 13 }}>{texto}</div>
  );

  const painelEquipas = loading && !territorios.length ? vazio('A carregar…') : !equipas.length ? vazio(q ? 'Nenhuma equipa corresponde à procura.' : 'Sem equipas com estes filtros.') : (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {formAqui('')}
      {equipas.map(eq => (
        <section key={eq.code} style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, overflow: 'hidden' }}>
          <header style={{ padding: '14px 16px', display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'center' }}>
            <div>
              <div style={{ fontSize: 15, fontWeight: 700, fontFamily: 'var(--font-display)' }}>{eq.code}</div>
              <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 3 }}>
                {[eq.marcas.join(', '), eq.paises.map(p => (p === 'PT' ? 'Portugal' : p === 'ES' ? 'Espanha' : p)).join(', '), `${eq.pessoas.length} ${eq.pessoas.length === 1 ? 'comercial' : 'comerciais'}`, `${eq.nZonas} ${eq.nZonas === 1 ? 'zona' : 'zonas'}`].join(' · ')}
              </div>
            </div>
          </header>
          {eq.partidas.length > 0 && (
            <div style={{ padding: '0 16px 12px', fontSize: 12, color: 'var(--text-muted)' }}>
              Zonas partilhadas: {eq.partidas.map(z => `${z.zona} (${z.nomes.join(', ')})`).join(' · ')}
            </div>
          )}
          {eq.pessoas.map(p => blocoPessoa(p, eq.code, `eq:${eq.code}`))}
        </section>
      ))}
    </div>
  );

  const painelComerciais = loading && !territorios.length ? vazio('A carregar…') : !pessoas.length ? vazio(q ? 'Nenhum comercial corresponde à procura.' : 'Sem comerciais com estes filtros.') : (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 12 }}>
      {edicao?.tipo === 'zona' && edicao.ancora === '' && <div style={{ gridColumn: '1 / -1' }}>{formulario}</div>}
      {pessoas.map(p => {
        const ancora = `ps:${p.nome}`;
        const aberto = edicao?.tipo === 'zona' && edicao.ancora === ancora;
        return (
          <section key={p.nome} style={{ gridColumn: aberto ? '1 / -1' : undefined, background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 14 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'flex-start' }}>
              <div>
                <div style={{ fontWeight: 650 }}>{p.nome}</div>
                <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>{p.email || 'Sem email no Gestor'}</div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
                  {p.equipas.map(code => <span key={code} style={{ fontSize: 10, fontWeight: 650, letterSpacing: '.04em', textTransform: 'uppercase', color: '#0891b2', background: '#ecfeff', borderRadius: 999, padding: '3px 8px' }}>{code}</span>)}
                </div>
              </div>
              {admin && <button type="button" className="btn btn-sm btn-ghost" onClick={() => novaZona(p, p.equipas[0] || '', ancora)}>+ Zona</button>}
            </div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 12 }}>
              {p.zs.map(z => (
                <ProspZonaBtn key={z.id} zona={z} admin={admin} on={edicao?.tipo === 'zona' && edicao.id === z.id}
                  mostrarMarca={!marcaUsada}
                  mostrarEquipa={p.equipas.length > 1}
                  onClick={() => abrirZona(z, ancora)} />
              ))}
            </div>
            {formAqui(ancora)}
          </section>
        );
      })}
    </div>
  );

  const formPartner = (r) => edicao?.tipo === 'partner' && edicao.id === r.marca_id && (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 12 }} onClick={e => e.stopPropagation()}>
      <ProspField label="Território"><input style={prospInput} value={edicao.territorio} onChange={e => setCampo('territorio', e.target.value)} /></ProspField>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
        <ProspField label="Contrato"><input style={prospInput} value={edicao.contrato} onChange={e => setCampo('contrato', e.target.value)} placeholder="Gold, Platino…" /></ProspField>
        <ProspField label="Segmento"><input style={prospInput} value={edicao.segmento} onChange={e => setCampo('segmento', e.target.value)} /></ProspField>
      </div>
      <div style={{ display: 'flex', gap: 8 }}>
        <button type="button" className="btn btn-sm btn-ai" disabled={aGravar} onClick={gravar}>{aGravar ? 'A gravar…' : 'Guardar'}</button>
        <button type="button" className="btn btn-sm btn-ghost" disabled={aGravar} onClick={() => setEdicao(null)}>Cancelar</button>
      </div>
    </div>
  );

  const painelPartners = loading && !partners.length ? vazio('A carregar…') : !gruposPartner.length ? vazio(q ? 'Nenhum partner corresponde à procura.' : 'Sem partners com estes filtros.') : (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
      {gruposPartner.map(g => (
        <section key={g.nome} style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          <div style={{ fontSize: 11, fontWeight: 650, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-dim)' }}>{g.nome}</div>
          {g.paises.map(([paisCode, rows]) => (
            <div key={paisCode} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{paisCode === 'PT' ? 'Portugal' : paisCode === 'ES' ? 'Espanha' : paisCode}</div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 10 }}>
                {rows.map(r => {
                  const aberto = edicao?.tipo === 'partner' && edicao.id === r.marca_id;
                  const emails = prospEmails(r);
                  return (
                    <div key={r.marca_id || prospIdPartner(r)} onClick={() => abrirPartner(r)} style={{ gridColumn: aberto ? '1 / -1' : undefined, background: '#fff', border: `1px solid ${aberto ? 'var(--ai-500)' : 'var(--border)'}`, borderRadius: 10, padding: 14, cursor: admin && r.marca_id ? 'pointer' : 'default' }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'flex-start' }}>
                        <div style={{ fontWeight: 650 }}>{r.nome}</div>
                        {r.contrato ? <span style={{ fontSize: 10, fontWeight: 650, letterSpacing: '.04em', textTransform: 'uppercase', color: '#7c3aed', background: '#f5f3ff', borderRadius: 999, padding: '3px 8px', flexShrink: 0 }}>{prospRotuloContrato(r.contrato)}</span> : null}
                      </div>
                      <div style={{ fontSize: 13, marginTop: 8, lineHeight: 1.4 }}>{r.territorio || 'Sem território definido'}</div>
                      {r.segmento ? <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 6, lineHeight: 1.4 }}>{r.segmento}</div> : null}
                      {emails.length > 0 && <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 8 }}>{emails.join(' · ')}</div>}
                      {formPartner(r)}
                    </div>
                  );
                })}
              </div>
            </div>
          ))}
        </section>
      ))}
    </div>
  );

  const notas = {
    equipas: 'Cada equipa, com os comerciais e as zonas que cobrem. Clica numa zona para a editar.',
    comerciais: 'Os mesmos territórios, vistos a partir de cada comercial.',
    partners: 'Território, contrato e segmento de cada partner, por marca e país.',
  };
  const barra = (
    <>
      {!marca && (
        <ProspDrop label="Marca" value={marcaUsada} onChange={setMarcaLocal} options={[{ value: '', label: 'Todas' }, ...marcasOpcoes.map(m => ({ value: m, label: m }))]} />
      )}
      <ProspDrop label="País" value={pais} onChange={setPais} options={[{ value: '', label: 'Ambos' }, { value: 'PT', label: 'Portugal' }, { value: 'ES', label: 'Espanha' }]} />
      <input value={q} onChange={e => setQ(e.target.value)} placeholder="Procurar comercial, zona ou partner" style={{ border: '1px solid var(--border)', borderRadius: 6, padding: '6px 10px', fontSize: 12, background: '#fff', color: 'var(--text)', minWidth: 220, fontFamily: 'inherit' }} />
    </>
  );

  return (
    <>
      {filtroSlot && ReactDOM.createPortal(barra, filtroSlot)}
      <datalist id="prosp-comerciais">{[...new Set(territorios.map(r => r.pessoa_nome))].map(n => <option key={n} value={n} />)}</datalist>
      <datalist id="prosp-equipas">{[...new Set(territorios.map(r => r.equipa_code).filter(Boolean))].map(n => <option key={n} value={n} />)}</datalist>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        {erro && <ProspMsg msg={{ tipo: 'erro', texto: erro }} />}
        {aviso && <ProspMsg msg={{ tipo: 'ok', texto: aviso }} />}
        <ProspMercadoCats value={cat} onChange={(id) => { setCat(id); setAviso(''); }} items={[
          { id: 'equipas', label: 'Equipas', n: equipas.length, accent: '#0891b2' },
          { id: 'comerciais', label: 'Comerciais', n: pessoas.length, accent: '#3859D0' },
          { id: 'partners', label: 'Partners', n: baseP.length, accent: '#7c3aed' },
        ]} />
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
          <div style={{ fontSize: 13, color: 'var(--text-muted)', lineHeight: 1.4 }}>{notas[cat]}</div>
          {admin && cat !== 'partners' && <button type="button" className="btn btn-sm btn-ai" onClick={() => novaZona(null, '', '')}>Nova zona</button>}
        </div>
        {cat === 'equipas' && painelEquipas}
        {cat === 'comerciais' && painelComerciais}
        {cat === 'partners' && painelPartners}
      </div>
    </>
  );
}

function MktProspeccaoScreen() {
  const brandApi = window.useMktBrand ? window.useMktBrand() : { brand: 'todas', setBrand: () => {} };
  const brand = brandApi.brand || 'todas';
  const setBrand = brandApi.setBrand || (() => {});
  const marca = brand !== 'todas' ? brand : '';
  const [tab, setTab] = React.useState('base');
  const [fonte, setFonte] = React.useState('apollo');
  const [rede, setRede] = React.useState('facebook');
  const [empresa, setEmpresa] = React.useState(null);
  const [resumo, setResumo] = React.useState(null);
  const [erro, setErro] = React.useState('');
  window.useMktZoneLoading(resumo == null && !erro);
  const [tick, setTick] = React.useState(0);
  const [vendedores, setVendedores] = React.useState([]);
  const [busca, setBusca] = React.useState(false);
  const [f, setF] = React.useState({ estado: '', pais: '', fonte: '', com_email: '', com_telefone: '', ordem: 'recentes' });
  const [vista, setVista] = React.useState('empresas');
  const [cFiltro, setCFiltro] = React.useState('');
  const [filtroMercados, setFiltroMercados] = React.useState(null);
  const [periodo, setPeriodo] = React.useState(() => {
    const today = new Date();
    return { preset: 'all', start: new Date(today.getFullYear(), 0, 1), end: today };
  });
  const intervalo = periodo.preset === 'all' ? {} : { desde: prospIsoDia(periodo.start), ate: prospIsoDia(periodo.end) };
  const fecharBusca = React.useCallback(() => setBusca(false), []);

  React.useEffect(() => {
    prospApi('/resumo', { query: { marca, ...intervalo } }).then(d => { setResumo(d); setErro(''); }).catch(e => setErro(e.message));
  }, [tick, marca, intervalo.desde, intervalo.ate]);
  React.useEffect(() => { prospApi('/vendedores').then(d => setVendedores(d.rows)).catch(() => {}); }, []);

  const admin = !!resumo?.admin;
  const mudarTab = (id) => {
    setEmpresa(null); setBusca(false); setTab(id);
    if (id === 'contactos') {
      setVista('contactos');
      if (tab !== 'contactos') setF(p => (p.ordem === 'recentes' ? { ...p, ordem: 'nome' } : p));
    }
    if (id === 'base') setVista('empresas');
  };
  const escolherFonte = (id) => {
    const next = id === 'redes' ? rede : id;
    setFonte(next);
    if (['facebook', 'instagram', 'tiktok'].includes(next)) setRede(next);
  };
  React.useEffect(() => {
    if (resumo && !resumo.admin && tab === 'pesquisa') setTab('base');
  }, [resumo, tab]);
  const marcasNav = [{ id: 'todas', nome: 'Todas' }, ...((window.MKT_BRANDS || [
    { id: 'mimaki', nome: 'Mimaki' }, { id: 'biond', nome: 'BIOND' }, { id: 'decal', nome: 'Decal' },
    { id: 'alldecor', nome: 'AllDecor' }, { id: 'sensek', nome: 'Sensek' }, { id: 'netscreen', nome: 'NetScreen' },
  ]).filter(b => b.id !== 'todas'))];
  const tabBtn = (b) => {
    const active = b.id === brand;
    return (
      <button key={b.id} type="button" onClick={() => setBrand(b.id)} style={{
        background: 'none', border: 'none', outline: 'none',
        borderBottom: `2px solid ${active ? 'var(--ai-500)' : 'transparent'}`,
        color: active ? 'var(--text)' : 'var(--text-muted)',
        fontSize: 13, fontWeight: active ? 600 : 500,
        fontFamily: 'var(--font-display)', letterSpacing: '.01em',
        padding: '10px 18px 12px', cursor: 'pointer', whiteSpace: 'nowrap',
      }}>{b.nome || b.name}</button>
    );
  };
  const Periodo = window.BriefingDateRangePicker;
  const marcaLabel = marca ? (marcasNav.find(b => b.id === brand)?.nome || marca) : '';
  const sair = () => { setBusca(false); setEmpresa(null); setTab('base'); };
  const canalId = ['facebook', 'instagram', 'tiktok'].includes(fonte) ? 'redes' : fonte;
  const segmentos = empresa
    ? [{ label: 'Prospeção', onClick: sair }, { label: empresa.nome }]
    : tab === 'pesquisa'
      ? [{ label: 'Prospeção', onClick: sair }, { label: PROSP_FONTES_PESQUISA.find(p => p.id === canalId)?.label || 'Pesquisar' }, ...(PROSP_REDES.find(r => r.id === fonte) ? [{ label: PROSP_REDES.find(r => r.id === fonte).label }] : [])]
      : tab === 'execucoes'
        ? [{ label: 'Prospeção', onClick: sair }, { label: 'Histórico' }]
        : null;
  const vistas = [
    { id: 'base', label: 'Empresas', sub: 'Lista de empresas já recolhidas' },
    { id: 'contactos', label: 'Contactos', sub: 'Pessoas ligadas às empresas' },
    { id: 'mercados', label: 'Mercados', sub: 'Territórios de comerciais, equipas e partners' },
    ...(admin ? [{ id: 'pesquisa', label: 'Pesquisar', sub: 'Apollo ou uma página' }] : []),
    { id: 'execucoes', label: 'Histórico', sub: 'Pesquisas e importações já feitas' },
  ];
  const menu = (
    <ProspMenu activo={empresa ? '' : tab} onOpen={() => setBusca(false)} items={vistas.map(t => ({ ...t, onClick: () => mudarTab(t.id) }))} />
  );
  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0, background: 'var(--bg)' }}>
      <div style={{ background: 'var(--bg-elev)', borderBottom: '1px solid var(--border)', padding: '20px 40px 0', flexShrink: 0 }}>
        <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: '0.07em', color: 'var(--text-muted)', textTransform: 'uppercase', marginBottom: 6, fontFamily: 'var(--font-mono)' }}>
          MARKETING · PROSPEÇÃO
        </div>
        <h1 style={{ margin: 0, fontSize: 21, fontWeight: 700, color: 'var(--text)', fontFamily: 'var(--font-display)', letterSpacing: '-0.01em', lineHeight: 1.2 }}>
          Prospeção
        </h1>
        <div style={{ height: 1, background: 'var(--border)', margin: '16px -40px 0' }} />
        <div style={{ display: 'flex', gap: 0, overflowX: 'auto' }}>{marcasNav.map(tabBtn)}</div>
      </div>

      <div className="scrollbar" style={{ overflowY: 'auto', flex: 1, minHeight: 0, padding: '28px 40px 64px', background: 'var(--bg)', display: 'flex', flexDirection: 'column', gap: 18 }}>
        {erro && <ProspMsg msg={{ tipo: 'erro', texto: erro }} />}
        {!empresa && (
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
              {(tab === 'base' || tab === 'contactos') && (
                <>
                  {tab === 'base' && <ProspDrop label="Estado" value={f.estado} onChange={v => setF(p => ({ ...p, estado: v }))} options={[{ value: '', label: 'Todos' }, ...PROSP_ESTADOS.map(e => ({ value: e.id, label: e.label }))]} />}
                  <ProspDrop label="País" value={f.pais} onChange={v => setF(p => ({ ...p, pais: v }))} options={[{ value: '', label: 'Todos' }, ...(resumo?.paises || []).map(p => ({ value: p.pais, label: `${p.pais} · ${prospNum(p.n)}` }))]} />
                  <ProspDrop label="Fonte" value={f.fonte} onChange={v => setF(p => ({ ...p, fonte: v }))} options={[{ value: '', label: 'Todas' }, ...['apollo', 'apify', 'pagina', 'import', 'excel'].map(k => ({ value: k, label: PROSP_FONTES[k] }))]} />
                  {tab === 'base' && <ProspDrop label="Contacto" value={f.com_email === '1' ? 'email' : f.com_telefone === '1' ? 'telefone' : ''} onChange={v => setF(p => ({ ...p, com_email: v === 'email' ? '1' : '', com_telefone: v === 'telefone' ? '1' : '' }))} options={[{ value: '', label: 'Todos' }, { value: 'email', label: 'Com email' }, { value: 'telefone', label: 'Com telefone' }]} />}
                  {tab === 'contactos' && <ProspDrop label="Contacto" value={cFiltro} onChange={setCFiltro} options={[{ value: '', label: 'Todos' }, { value: 'email', label: 'Com email' }, { value: 'telemovel', label: 'Com telemóvel' }]} />}
                  <ProspDrop label="Ordem" value={f.ordem} onChange={v => setF(p => ({ ...p, ordem: v }))} options={tab === 'contactos' ? [{ value: 'recentes', label: 'Recentes' }, { value: 'nome', label: 'Nome' }] : [{ value: 'recentes', label: 'Recentes' }, { value: 'actualizadas', label: 'Actualizadas' }, { value: 'nome', label: 'Nome' }, { value: 'score', label: 'Score' }]} />
                  {Periodo && <Periodo value={periodo} onChange={setPeriodo} />}
                </>
              )}
              {tab === 'execucoes' && Periodo && <Periodo value={periodo} onChange={setPeriodo} />}
              {tab === 'mercados' && <div ref={setFiltroMercados} style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }} />}
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginLeft: 'auto' }}>
              <ProspIcone label="Procurar empresas e contactos" activo={busca} onClick={() => setBusca(v => !v)}>
                <svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"><circle cx="7" cy="7" r="4.25" /><path d="M10.5 10.5L13.5 13.5" /></svg>
              </ProspIcone>
              {menu}
            </div>
          </div>
        )}
        {!empresa && <ProspKpis resumo={resumo} tab={tab} admin={admin} onIr={mudarTab} />}
        {segmentos && (
          <ProspTrilho segmentos={segmentos} extra={empresa ? menu : null} nota={empresa && (
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8, fontSize: 12, color: 'var(--text-muted)' }}>
              {empresa.pais && <span style={{ color: 'var(--ai-500)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em', fontSize: 10, fontFamily: 'var(--font-mono)' }}>{empresa.pais}</span>}
              {empresa.fonte && <span>{PROSP_FONTES[empresa.fonte] || empresa.fonte}</span>}
              {empresa.estado && <ProspBadge estado={empresa.estado} />}
            </span>
          )} />
        )}
        {empresa && <ProspFicha id={empresa.id} admin={admin} vendedores={vendedores} onClose={() => setEmpresa(null)} onChanged={() => setTick(t => t + 1)} onLoaded={(e) => setEmpresa(prev => (prev && prev.id === e.id ? { ...prev, ...e } : prev))} />}
        {!empresa && tab === 'base' && <ProspBase resumo={resumo} admin={admin} vendedores={vendedores} marca={marca} desde={intervalo.desde} ate={intervalo.ate} f={f} setF={setF} vista="empresas" cFiltro={cFiltro} onVista={(id) => mudarTab(id === 'contactos' ? 'contactos' : 'base')} onCFiltro={setCFiltro} onOpen={setEmpresa} onChanged={() => setTick(t => t + 1)} />}
        {!empresa && tab === 'contactos' && <ProspBase resumo={resumo} admin={admin} vendedores={vendedores} marca={marca} desde={intervalo.desde} ate={intervalo.ate} f={f} setF={setF} vista="contactos" cFiltro={cFiltro} onVista={(id) => mudarTab(id === 'contactos' ? 'contactos' : 'base')} onCFiltro={setCFiltro} onOpen={setEmpresa} onChanged={() => setTick(t => t + 1)} />}
        {!empresa && tab === 'mercados' && <ProspMercados marca={marca} marcaLabel={marcaLabel} filtroSlot={filtroMercados} admin={admin} />}
        {!empresa && tab === 'pesquisa' && admin && <ProspPesquisa fonte={fonte} onFonte={escolherFonte} onLancada={() => setTick(t => t + 1)} onOpen={setEmpresa} marca={marca} marcaLabel={marcaLabel} />}
        {!empresa && tab === 'execucoes' && <ProspExecucoes tick={tick} desde={intervalo.desde} ate={intervalo.ate} marca={marca} />}
      </div>
      {busca && <ProspBusca marca={marca} desde={intervalo.desde} ate={intervalo.ate} onOpen={(r) => { setTab('base'); setEmpresa(r); }} onClose={fecharBusca} />}
    </div>
  );
}

window.MktProspeccaoScreen = MktProspeccaoScreen;
