/* Marketing · Leads — cartões por campanha e lista de pessoas. */

const LEADS_ESTADO_LABEL = {
  nova: 'Nova',
  em_qualificacao: 'Em qualificação',
  qualificada: 'Qualificada',
  atribuida: 'Atribuída',
  nurture: 'Nurture',
  descartada: 'Descartada',
};
const LEADS_PERIODOS = [
  { id: 'hoje', label: 'Hoje' },
  { id: '7d', label: '7 dias' },
  { id: '30d', label: '30 dias' },
  { id: '90d', label: '90 dias' },
  { id: '2026', label: '2026' },
  { id: 'tudo', label: 'Tudo' },
];

function leadsQs(extra) {
  const p = new URLSearchParams(extra || {});
  const email = window.currentUser?.email || '';
  if (email && !p.get('email')) p.set('email', email);
  return p.toString();
}

function leadsActor() {
  const u = window.currentUser || {};
  return { actor_nome: u.nome_apresentar || u.nome || '', actor_email: u.email || '' };
}

async function leadsPost(url, body) {
  const r = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ...leadsActor(), ...(body || {}) }),
  });
  const d = await r.json().catch(() => ({}));
  if (!r.ok || d.error) throw new Error(d.error || 'Não foi possível gravar');
  return d;
}

function leadsAgo(iso) {
  if (!iso) return '';
  const ms = Date.now() - new Date(iso).getTime();
  if (!Number.isFinite(ms) || ms < 0) return '';
  const h = Math.floor(ms / 3600000);
  if (h < 1) return 'agora';
  if (h < 24) return `há ${h}h`;
  const d = Math.floor(h / 24);
  return d < 30 ? `há ${d}d` : new Date(iso).toLocaleDateString('pt-PT');
}

function leadsBrand(marca) {
  if (typeof listaMarca === 'function') return listaMarca({ marca });
  return null;
}

function leadsPedidoLabel(pedido) {
  if (pedido === 'amostras') return 'Pedido de amostras';
  if (pedido === 'reuniao') return 'Pedido de reunião';
  if (pedido === 'outro') return 'Resposta';
  return '';
}

function leadsCanalLabel(catalogo, id) {
  return (catalogo || []).find(c => c.id === id)?.label || id || 'Canal';
}

function leadsNome(nome) {
  const n = String(nome || '').trim();
  if (!n || /^\[.*\]$/.test(n) || /your-name/i.test(n)) return 'Sem nome';
  return n;
}

function leadsDestinoLabel(destino) {
  const map = {
    wp_form: 'Formulário do site',
    form_nativo: 'Formulário Meta',
    wa_digi: 'WhatsApp',
    ctwa: 'WhatsApp',
    typeform: 'Typeform',
  };
  return map[destino] || destino || '—';
}

function leadsScoreNumero(score) {
  if (score == null || score === '') return 0;
  const n = Number(score);
  return Number.isFinite(n) ? n : 0;
}

function leadsData(iso) {
  if (!iso) return '—';
  const d = new Date(iso);
  return Number.isFinite(d.getTime()) ? d.toLocaleDateString('pt-PT') : '—';
}

function leadFormNome(lead) {
  for (const en of lead?.entradas || []) {
    const form = en?.form_nome || en?.origem?.form;
    if (form) return String(form);
  }
  return '';
}

const LEADS_TEMA_COR_DEFAULT = '#3859D0';

function leadsTemaInfo(catalogo, id) {
  return (catalogo || []).find(t => t.id === id) || null;
}

function leadsTemaLabel(catalogo, id) {
  if (!id) return 'Sem tema';
  return leadsTemaInfo(catalogo, id)?.label || id;
}

function leadsEur(n) {
  const v = Number(n || 0);
  if (!v) return '';
  return `${Math.round(v).toLocaleString('pt-PT')} €`;
}

function LeadsTemaBadge({ catalogo, tema, small }) {
  if (!tema) return null;
  const info = leadsTemaInfo(catalogo, tema);
  const cor = info?.cor || LEADS_TEMA_COR_DEFAULT;
  return <span style={{ fontSize: small ? 10 : 11, fontWeight: 650, color: cor, background: `${cor}14`, border: `1px solid ${cor}33`, borderRadius: 99, padding: small ? '1px 7px' : '2px 8px', whiteSpace: 'nowrap' }}>{info?.label || tema}</span>;
}

function LeadsInternaBadge({ interna }) {
  if (!interna) return null;
  return <span title="Telefone ou email de colaborador Digidelta" style={{ fontSize: 10, fontWeight: 700, letterSpacing: '.04em', textTransform: 'uppercase', color: '#9f1239', background: '#fff1f2', border: '1px solid #fecdd3', borderRadius: 99, padding: '1px 7px' }}>Interna</span>;
}

// Lead que também falou com a Digi no WhatsApp (ligação por telefone/email do formulário)
function LeadsWaBadge({ n, small }) {
  return <span title="Conversa WhatsApp com a Digi AI" style={{ fontSize: small ? 9 : 10, fontWeight: 700, letterSpacing: '.04em', textTransform: 'uppercase', color: '#15803d', background: '#f0fdf4', border: '1px solid #bbf7d0', borderRadius: 99, padding: '1px 7px', whiteSpace: 'nowrap' }}>WA Digi{n ? ` · ${n}` : ''}</span>;
}

function LeadsConversaDigiResumo({ conversa, onVer, compacto }) {
  if (!conversa) return null;
  const c = conversa;
  const ligacao = c.ligacao === 'telefone' ? 'ligada pelo telefone do formulário' : c.ligacao === 'email' ? 'ligada pelo email do formulário' : c.ligacao === 'contacto' ? 'ligada ao contacto' : '';
  return (
    <div style={{ fontSize: 13, display: 'flex', flexDirection: 'column', gap: 6, ...(compacto ? { background: '#f0fdf4', border: '1px solid #bbf7d0', borderRadius: 10, padding: '10px 14px' } : {}) }}>
      <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
        <LeadsWaBadge n={c.n_msgs} />
        <span style={{ color: 'var(--text-muted)' }}>{c.n_lead ?? 0} da lead · {c.n_digi ?? 0} da Digi{c.ultima ? ` · última ${new Date(c.ultima).toLocaleString('pt-PT')}` : ''}</span>
        {c.classification && <span style={{ fontSize: 11, fontWeight: 650 }}>{c.classification}{c.lead_score != null ? ` · score ${c.lead_score}` : ''}</span>}
        {ligacao && <span style={{ fontSize: 11, color: 'var(--text-dim)' }}>{ligacao}</span>}
      </div>
      {c.campanha && <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Campanha: {c.campanha}{c.marca ? ` · ${c.marca}` : ''}</div>}
      {!compacto && c.ultima_msg?.texto && <div style={{ fontSize: 12, color: 'var(--text)', background: 'var(--bg-sunken)', borderRadius: 8, padding: '8px 10px', fontStyle: 'italic' }}><span style={{ color: 'var(--text-muted)', fontStyle: 'normal' }}>{c.ultima_msg.role === 'lead' ? 'Lead' : 'Digi'}: </span>{c.ultima_msg.texto}</div>}
      {!compacto && onVer && <div><button type="button" className="btn" style={{ fontSize: 12 }} onClick={onVer}>Ver conversa completa</button></div>}
    </div>
  );
}

// Campos do formulário: lista [{campo,label,valor}] ou objecto {campo: valor} → linhas legíveis.
function leadsCamposLista(campos, labels) {
  if (!campos) return [];
  if (Array.isArray(campos)) return campos.filter(c => c && c.valor);
  return Object.entries(campos).filter(([, v]) => v).map(([campo, valor]) => ({ campo, label: (labels || {})[campo] || campo.replace(/[-_]+/g, ' ').replace(/^\w/, c => c.toUpperCase()), valor }));
}

function LeadsGrelha({ children }) {
  return <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: '14px 22px' }}>{children}</div>;
}

function LeadsCampo({ label, valor, mono, vazio }) {
  const tem = valor != null && String(valor) !== '';
  if (!tem && vazio == null) return null;
  const isUrl = tem && /^https?:\/\//i.test(String(valor));
  return (
    <div style={{ minWidth: 0 }}>
      <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-dim)' }}>{label}</div>
      <div style={{ marginTop: 2, fontSize: 13, fontWeight: tem ? 650 : 450, lineHeight: 1.35, color: tem ? 'var(--text)' : 'var(--text-dim)', fontStyle: tem ? 'normal' : 'italic', overflowWrap: 'anywhere', fontFamily: mono && tem ? 'var(--font-mono)' : 'var(--font-body, Inter, sans-serif)' }}>
        {tem
          ? (isUrl
            ? <a href={valor} target="_blank" rel="noopener noreferrer" style={{ color: 'var(--ai-500)', fontWeight: 600 }}>{String(valor).replace(/^https?:\/\//, '')}</a>
            : valor)
          : vazio}
      </div>
    </div>
  );
}

// campanha_id e outros *_id vêm do tracking / da Meta, não são respostas que a pessoa escreveu.
function leadsCampoTecnico(c) {
  const k = String(c?.campo || '').toLowerCase();
  return k === 'campanha_id' || /(?:^|_)id$/.test(k);
}

function LeadsCampos({ campos, labels, ficheiros }) {
  const linhas = leadsCamposLista(campos, labels).filter(c => !leadsCampoTecnico(c));
  const files = (ficheiros || []).filter(f => f?.url && !linhas.some(c => c.valor === f.url));
  if (!linhas.length && !files.length) return <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Sem dados do formulário.</div>;
  return (
    <LeadsGrelha>
      {linhas.map(c => <LeadsCampo key={c.campo} label={c.label} valor={c.valor} />)}
      {files.map((f, i) => <LeadsCampo key={`f${i}`} label={f.label || f.campo} valor={<a href={f.url} target="_blank" rel="noopener noreferrer" style={{ color: 'var(--ai-500)' }}>abrir</a>} />)}
    </LeadsGrelha>
  );
}

function leadsRespostasFormulario(campos, labels) {
  return leadsCamposLista(campos, labels).filter(c => !leadsCampoTecnico(c));
}

function LeadsContacto({ detalhe, camposLabels, metaForm, anuncio, entrada }) {
  const respostas = leadsRespostasFormulario(detalhe?.dados_formulario, camposLabels);
  const portalId = (leadsCamposLista(detalhe?.dados_formulario, camposLabels).find(c => String(c.campo || '').toLowerCase() === 'campanha_id')?.valor)
    || entrada?.campanha_portal_id
    || detalhe?.campanha_portal_id
    || null;
  const tecnicos = [
    ['ID da lead', detalhe?.leadgen_id || entrada?.meta_leadgen_id],
    ['ID do formulário', anuncio?.form_id],
    ['ID do anúncio', anuncio?.ad_id],
    ['ID do conjunto', anuncio?.adset_id],
    ['ID da campanha na Meta', anuncio?.campanha_meta_id],
    ['ID da campanha no portal', portalId],
    ['Plataforma', anuncio?.platform ? leadsPlataforma(anuncio.platform) : ''],
  ].filter(([, v]) => v != null && String(v) !== '');
  if (!respostas.length && !tecnicos.length) {
    return <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>{metaForm ? (detalhe?.formulario_meta?.motivo || 'Os campos submetidos no formulário Meta ainda não estão gravados nesta lead.') : 'Sem dados de contacto.'}</div>;
  }
  const titulo = { fontSize: 10, fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-dim)', marginBottom: 10 };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {respostas.length > 0 && <div>
        <div style={titulo}>Formulário</div>
        <LeadsGrelha>
          {respostas.map(c => <LeadsCampo key={c.campo} label={c.label} valor={c.valor} />)}
        </LeadsGrelha>
      </div>}
      {tecnicos.length > 0 && <div>
        <div style={titulo}>Dados técnicos</div>
        <LeadsGrelha>
          {tecnicos.map(([label, valor]) => <LeadsCampo key={label} label={label} valor={valor} mono={label !== 'Plataforma'} />)}
        </LeadsGrelha>
      </div>}
    </div>
  );
}

function LeadsPageHeader({ breadcrumb, title, sub, extra, tabs, compact }) {
  return (
    <div style={{ background: '#fff', 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)' }}>
        {(breadcrumb || []).map((b, i) => (
          <span key={i}>
            {i > 0 && <span style={{ margin: '0 6px' }}>·</span>}
            {b.onClick
              ? <button type="button" onClick={b.onClick} style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer', color: 'var(--text-muted)', font: 'inherit', letterSpacing: 'inherit', textTransform: 'inherit' }}>{b.label}</button>
              : b.label}
          </span>
        ))}
      </div>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16 }}>
        <div>
          <h1 style={{ margin: 0, fontSize: compact ? 13 : 21, fontWeight: compact ? 650 : 700, color: 'var(--text)', fontFamily: compact ? 'var(--font-body, Inter, sans-serif)' : 'var(--font-display)', letterSpacing: compact ? 'normal' : '-0.01em', lineHeight: compact ? 1.35 : 1.2 }}>{title}</h1>
          {sub && <div style={{ marginTop: compact ? 2 : 6, fontSize: 11, color: 'var(--text-muted)' }}>{sub}</div>}
        </div>
        {extra && <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexShrink: 0, marginTop: 2 }}>{extra}</div>}
      </div>
      <div style={{ height: 1, background: 'var(--border)', margin: '16px -40px 0' }} />
      {tabs}
    </div>
  );
}

function LeadsShell({ 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',
    }}>{children}</div>
  );
}

const LEADS_FUNIL_LABEL = { lead: 'Lead', qualificada: 'Qualificada', oportunidade: 'Oportunidade', venda: 'Venda' };
const LEADS_FUNIL_COR = { lead: '#3859D0', qualificada: '#0891b2', oportunidade: '#d97706', venda: '#15803d' };
const LEADS_CRM_LABEL = { confirmado: 'Na BD', forte: 'Na BD', possivel: 'Possível', ambiguo: 'Ambíguo', sem_match: 'Não está na BD' };

function leadsEhFormMeta(en) {
  return en?.canal === 'meta_ads' && (en?.destino === 'form_nativo' || en?.form_nome === 'Formulário Meta Ads' || en?.fonte === 'meta_leadgen' || !!en?.anuncio?.form_id);
}

function leadsTemConversaWa(en) {
  return !!(en?.conversa_digi || en?.visitor_id);
}

function leadsMeioOrigem(en) {
  if (!en) return '—';
  if (leadsEhFormMeta(en) || (en.destino === 'form_nativo' && en.canal === 'meta_ads')) return 'Formulário nativo';
  if (en.canal === 'meta_ads') return leadsTemConversaWa(en) ? 'WhatsApp' : 'Anúncio';
  return leadsDestinoLabel(en.destino);
}

function leadsAnuncioVisivel(...fontes) {
  const out = {};
  const take = (k, v) => { if (out[k] == null || out[k] === '') { if (v != null && v !== '') out[k] = v; } };
  for (const f of fontes) {
    if (!f) continue;
    const a = f.anuncio && typeof f.anuncio === 'object' ? f.anuncio : null;
    take('ad_id', a?.ad_id || f.ad_id);
    take('ad_name', a?.ad_name || f.ad_headline || f.ad_name);
    take('adset_id', a?.adset_id || f.adset_id);
    take('adset_name', a?.adset_name || f.adset_name);
    take('campanha_meta_id', a?.campanha_meta_id || f.campanha_meta_id);
    take('campanha_meta_nome', a?.campanha_meta_nome || f.campanha_meta_nome);
    take('platform', a?.platform || f.platform);
    take('form_id', a?.form_id || f.form_id || f.meta_form_id);
  }
  for (const f of fontes) {
    const c = f?.criativo || f?.anuncio?.criativo;
    if (!c) continue;
    const ad = String(f?.anuncio?.ad_id || f?.ad_id || '');
    if (!out.criativo || (ad && ad === String(out.ad_id || ''))) out.criativo = c;
  }
  return Object.keys(out).length ? out : null;
}

function leadsPlataforma(p) {
  const map = { fb: 'Facebook', facebook: 'Facebook', ig: 'Instagram', instagram: 'Instagram', an: 'Audience Network', audience_network: 'Audience Network' };
  const key = String(p || '').toLowerCase();
  return map[key] || p || '';
}

function leadsFormMeta(lead) {
  if (leadsEhFormMeta(lead) || lead?.form_nome === 'Formulário Meta Ads') return true;
  return (lead?.entradas || []).some(en => leadsEhFormMeta(en) || en?.form_nome === 'Formulário Meta Ads');
}

function leadsOrigem(lead, catalogo) {
  const anuncio = leadsAnuncioVisivel(lead);
  if (leadsFormMeta(lead)) {
    return ['Meta Ads', anuncio?.ad_name || 'Formulário nativo', 'Iniciado por Lead'].filter(Boolean).join(' · ');
  }
  const canal = leadsCanalLabel(catalogo, lead.canal);
  const extra = lead?.canal === 'meta_ads'
    ? (anuncio?.ad_name || leadsMeioOrigem(lead))
    : (leadFormNome(lead) || lead.ad_headline || leadsDestinoLabel(lead.destino));
  const iniciado = lead.iniciado_por || (lead.direccao === 'outbound' ? 'Digidelta' : 'Lead');
  return [canal, extra, `Iniciado por ${iniciado}`].filter(Boolean).join(' · ');
}

function LeadsContactoEstado({ contacto, quando }) {
  if (!contacto?.label) return <span style={{ color: 'var(--text-dim)' }}>—</span>;
  const cor = {
    por_contactar: '#b45309',
    primeiro_contacto: '#1d4ed8',
    followup_2: '#1d4ed8',
    followup_3: '#1d4ed8',
    followup_4: '#1d4ed8',
    em_conversa: '#0891b2',
    lida: '#15803d',
    entregue: '#1d4ed8',
    falhou: '#9f1239',
    qualificado: '#15803d',
    potencial: '#b45309',
    nurture: '#b45309',
    baixa: '#9f1239',
    nao_qualificado: '#9f1239',
    optout: '#9f1239',
    sem_whatsapp: '#9f1239',
  }[contacto.codigo] || 'var(--text)';
  return (
    <div>
      <div style={{ fontSize: 12, fontWeight: 650, color: cor }}>{contacto.label}</div>
      {quando ? <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{leadsData(quando)}</div> : null}
    </div>
  );
}

function leadsTituloOrigem(en) {
  if (leadsEhFormMeta(en)) return 'Formulário Meta Ads';
  if (en?.canal === 'meta_ads' && !leadsTemConversaWa(en)) return anuncioNomeCurto(en) || 'Anúncio Meta Ads';
  if (en?.form_nome) return en.form_nome;
  if (en?.origem?.form) return en.origem.form;
  if (en?.conversa_digi || en?.visitor_id) return 'Conversa WhatsApp com a Digi';
  return leadsDestinoLabel(en?.destino);
}

function anuncioNomeCurto(en) {
  const nome = en?.anuncio?.ad_name || en?.ad_headline || en?.ad_name;
  return nome ? `Anúncio ${nome}` : '';
}

function LeadsAnuncioPreview({ criativo }) {
  if (!criativo || (!criativo.imagem && !criativo.texto && !criativo.titulo)) return null;
  const bloco = (label, valor, forte) => !valor ? null : (
    <div>
      <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-muted)' }}>{label}</div>
      <div style={{ marginTop: 4, fontSize: 13, fontWeight: forte ? 650 : 400, lineHeight: 1.45, whiteSpace: 'pre-wrap' }}>{valor}</div>
    </div>
  );
  return (
    <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start', flexWrap: 'wrap', marginBottom: 14 }}>
      {criativo.imagem ? (
        <img src={criativo.imagem} alt={criativo.titulo || 'Anúncio'} style={{ width: 220, maxWidth: '100%', borderRadius: 8, border: '1px solid var(--border)', display: 'block', background: '#F4F6F8' }} />
      ) : null}
      <div style={{ flex: '1 1 240px', minWidth: 0, display: 'flex', flexDirection: 'column', gap: 10 }}>
        {bloco('Texto', criativo.texto)}
        {bloco('Título', criativo.titulo, true)}
        {bloco('Descrição', criativo.descricao)}
        {criativo.cta ? <div style={{ alignSelf: 'flex-start', fontSize: 12, fontWeight: 650, border: '1px solid var(--border)', borderRadius: 999, padding: '4px 10px' }}>{criativo.cta}</div> : null}
      </div>
    </div>
  );
}

function LeadsAnuncioBloco({ anuncio, campanha, ids = true, leadgenId, campanhaPortalId }) {
  if (!anuncio && !leadgenId && !campanhaPortalId) return null;
  const nomeMeta = anuncio?.campanha_meta_nome && anuncio.campanha_meta_nome !== campanha ? anuncio.campanha_meta_nome : '';
  const campos = [
    ['Anúncio', anuncio?.ad_name, false],
    ...(ids ? [['ID do anúncio', anuncio?.ad_id, true]] : []),
    ['Conjunto de anúncios', anuncio?.adset_name, false],
    ...(ids ? [['ID do conjunto', anuncio?.adset_id, true]] : []),
    ['Campanha na Meta', nomeMeta, false],
    ...(ids ? [
      ['ID da campanha na Meta', anuncio?.campanha_meta_id, true],
      ['ID da lead', leadgenId, true],
      ['ID da campanha no portal', campanhaPortalId, true],
    ] : []),
    ['Plataforma', leadsPlataforma(anuncio?.platform), false],
    ...(ids ? [['ID do formulário', anuncio?.form_id, true]] : []),
  ].filter(([, v]) => v);
  if (!anuncio?.criativo && !campos.length) return null;
  return (
    <div>
      <LeadsAnuncioPreview criativo={anuncio?.criativo} />
      {campos.length ? <LeadsGrelha>{campos.map(([label, valor, mono]) => <LeadsCampo key={label} label={label} valor={valor} mono={mono} />)}</LeadsGrelha> : null}
    </div>
  );
}

const LEADS_CLASS_LABEL = { HOT: 'Hot', QUALIFICADO: 'Qualificado', POTENCIAL: 'Potencial', NURTURE: 'Nurture', BAIXA: 'Baixa prioridade', NAO_QUALIFICADO: 'Não qualificado' };
const LEADS_CRIT_TEXTO = {
  problema_impacto_real: 'dor',
  volume_producao_conhecido: 'volume',
  timing_ate_6m: 'timing',
  equipamento_atual_identificado: 'equipamento',
  capacidade_orcamento: 'orcamento',
};

function leadsTextoCriterio(id, q, detalhe, atingido) {
  if (id === 'aceita_demo' || id === 'aceitou_rolo' || id === 'interesse_testar' || id === 'usa_categoria') {
    if (atingido === true) return 'Sim';
    if (atingido === false) return 'Não';
    if (detalhe?.aceita_demo == null) return '';
    return detalhe.aceita_demo ? 'Sim' : 'Não';
  }
  const key = LEADS_CRIT_TEXTO[id];
  return key ? String(q?.[key] || '') : '';
}

const LEADS_RUBRICA = [
  ['necessidade_identificada', 'Necessidade', 20],
  ['problema_impacto_real', 'Dor', 15],
  ['interesse_solucao', 'Interesse', 15],
  ['timing_ate_6m', 'Timing', 15],
  ['volume_producao_conhecido', 'Volume', 10],
  ['equipamento_atual_identificado', 'Equipamento', 10],
  ['capacidade_orcamento', 'Orçamento', 10],
  ['aceita_demo', 'Aceita demo', 5],
];

function leadsCriteriosPainel(q) {
  const vindos = Array.isArray(q?.criterios) ? q.criterios : [];
  if (vindos.length) {
    return vindos.map(c => ({
      id: c.id,
      label: c.label,
      peso: Number(c.peso) || 0,
      pontos: Number(c.pontos) || 0,
      atingido: !!c.atingido,
      avaliado: !!c.avaliado,
    }));
  }
  return LEADS_RUBRICA.map(([id, label, peso]) => ({ id, label, peso, pontos: 0, atingido: false, avaliado: false }));
}

function LeadsScorePainel({ detalhe }) {
  const q = detalhe?.qualificacao || {};
  const criterios = leadsCriteriosPainel(q);
  const scoreEscrito = detalhe?.score == null || detalhe.score === '' ? null : Number(detalhe.score);
  const avaliado = criterios.some(c => c.avaliado);
  const semScore = (scoreEscrito == null || !Number.isFinite(scoreEscrito)) && !avaliado;
  const estado = detalhe?.qualificacao_estado?.label || '';
  if (semScore) {
    return (
      <div>
        {estado ? <div style={{ fontSize: 14, fontWeight: 650, marginBottom: 6 }}>{estado}</div> : null}
        <div style={{ fontSize: 13, color: 'var(--text-muted)', lineHeight: 1.45 }}>Ainda sem Digi. O score aparece quando a lead responde e a conversa é classificada.</div>
      </div>
    );
  }
  const pontos = criterios.reduce((s, c) => s + (Number(c.pontos) || 0), 0);
  const valor = scoreEscrito != null && Number.isFinite(scoreEscrito) ? scoreEscrito : pontos;
  const consumiveis = q.rubrica === 'consumiveis';
  const cor = valor >= 80 ? '#15803d' : valor >= 60 ? (consumiveis ? '#d97706' : '#15803d') : valor >= 40 ? '#d97706' : '#9f1239';
  const faixaNumerica = consumiveis
    ? (valor >= 80 ? 'Hot' : valor >= 60 ? 'Potencial' : valor >= 40 ? 'Nurture' : 'Baixa prioridade')
    : (valor >= 80 ? 'Hot' : valor >= 60 ? 'Qualificado' : valor >= 40 ? 'Nurture' : 'Não qualificado');
  const faixa = LEADS_CLASS_LABEL[detalhe?.classification] || detalhe?.classification || faixaNumerica;
  const actualizado = detalhe?.score_updated_at ? new Date(detalhe.score_updated_at) : null;
  return (
    <div>
      {estado ? <div style={{ fontSize: 13, fontWeight: 650, marginBottom: 8 }}>{estado}</div> : null}
      <div style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
        <div style={{ width: 64, height: 64, borderRadius: 12, border: `2px solid ${cor}`, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, fontSize: 22, fontWeight: 700, color: cor, fontFamily: 'var(--font-display)' }}>{valor}</div>
        <div>
          <div style={{ fontSize: 14, fontWeight: 650 }}>{faixa}</div>
          <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 4, lineHeight: 1.45 }}>
            {`${valor} pontos. ${consumiveis ? 'Grelha de consumíveis.' : 'Grelha de equipamento.'}`}
            {actualizado && Number.isFinite(actualizado.getTime()) ? ` Actualizado ${actualizado.toLocaleString('pt-PT')}.` : ''}
          </div>
        </div>
      </div>
      <div style={{ marginTop: 16 }}>
        <LeadsGrelha>
          {criterios.map(c => {
            const texto = c.avaliado ? leadsTextoCriterio(c.id, q, detalhe, c.atingido) : '';
            return (
              <div key={c.id} style={{ minWidth: 0 }}>
                <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-dim)' }}>{c.label}</div>
                <div style={{ marginTop: 2, fontSize: 13, fontWeight: 650, fontFamily: 'var(--font-mono)', color: c.atingido ? '#15803d' : 'var(--text)' }}>{c.pontos} / {c.peso}</div>
                {texto ? <div style={{ marginTop: 4, fontSize: 13, lineHeight: 1.35, color: 'var(--text)' }}>{texto}</div> : null}
              </div>
            );
          })}
        </LeadsGrelha>
      </div>
    </div>
  );
}

function LeadsFunilBadge({ estado }) {
  const cor = LEADS_FUNIL_COR[estado] || '#3859D0';
  return <span style={{ fontSize: 11, fontWeight: 650, color: cor }}>{LEADS_FUNIL_LABEL[estado] || 'Lead'}</span>;
}

function leadsOrdenar(rows, sort) {
  const dir = sort?.dir === 'asc' ? 1 : -1;
  const ord = (row) => {
    if (sort?.key === 'nome') return leadsNome(row.nome);
    if (sort?.key === 'score') return leadsScoreNumero(row.score);
    if (sort?.key === 'estado_funil') return row.estado_funil || '';
    if (sort?.key === 'contacto') return row.contacto?.label || '';
    if (sort?.key === 'n_submissoes') return row.n_submissoes || 0;
    if (sort?.key === 'tema') return `${row.tema || 'zz'} ${row.produto || ''}`;
    if (sort?.key === 'crm' || sort?.key === 'entidade') return row.crm_entidade || row.crm_nivel || '';
    if (sort?.key === 'abertas') return row.gestor?.abertas || 0;
    if (sort?.key === 'ganhas') return row.gestor?.ganhas || 0;
    if (sort?.key === 'perdidas') return row.gestor?.perdidas || 0;
    return new Date(row.at || 0).getTime();
  };
  return rows.slice().sort((a, b) => {
    const va = ord(a);
    const vb = ord(b);
    if (va < vb) return -1 * dir;
    if (va > vb) return 1 * dir;
    return 0;
  });
}

function LeadsGrupoCards({ items, active, onPick }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))', gap: 12 }}>
      {items.map(k => {
        const on = active === k.id;
        return (
          <div key={k.id} onClick={() => onPick(on ? 'all' : k.id)} style={{ background: '#fff', border: `1px solid ${on ? k.accent : 'var(--border)'}`, borderRadius: 8, padding: '12px 16px 14px', cursor: 'pointer' }}>
            <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, marginTop: 6 }}>{Number(k.value).toLocaleString('pt-PT')}</div>
          </div>
        );
      })}
    </div>
  );
}

function LeadsPessoas({ rows, catalogo, temasCatalogo, mostrarTema, onOpen, sort, onSort }) {
  const th = { textAlign: 'left', fontSize: 10, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-dim)', padding: '8px 10px', borderBottom: '1px solid var(--border)', fontWeight: 600, cursor: 'pointer', background: 'none', overflowWrap: 'anywhere' };
  const td = { padding: '10px', borderBottom: '1px solid var(--border)', fontSize: 12, verticalAlign: 'top', overflowWrap: 'anywhere' };
  const mark = (id) => sort?.key === id ? (sort.dir === 'asc' ? ' ↑' : ' ↓') : '';
  const largura = { nome: '18%', estado_funil: '8%', contacto: '13%', score: '6%', tema: '12%', origem: '18%', n_submissoes: '7%', at: '9%', crm: '17%' };
  if (!rows.length) return <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 28, color: 'var(--text-muted)', fontSize: 12 }}>Sem pessoas neste grupo.</div>;
  const colunas = [['nome', 'Nome'], ['estado_funil', 'Estado'], ['contacto', 'Contacto'], ['score', 'Score']];
  if (mostrarTema) colunas.push(['tema', 'Tema / produto']);
  colunas.push(['origem', 'Origem'], ['n_submissoes', 'Submissões'], ['at', 'Última entrada'], ['crm', 'CRM']);
  return (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, minWidth: 0, maxWidth: '100%' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse', tableLayout: 'fixed' }}>
        <thead>
          <tr>
            {colunas.map(([id, label]) => (
              <th key={id} style={{ ...th, width: largura[id] }} onClick={() => onSort(id)}>{label}{mark(id)}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map(lead => (
            <tr key={lead.chave || lead.ref} onClick={() => onOpen(lead)} style={{ cursor: 'pointer', opacity: lead.interna ? 0.7 : 1 }}>
              <td style={td}>
                <div style={{ fontWeight: 650, fontSize: 13, display: 'flex', gap: 6, alignItems: 'center', flexWrap: 'wrap' }}>{leadsNome(lead.nome)}<LeadsInternaBadge interna={lead.interna} />{lead.conversa_digi && <LeadsWaBadge n={lead.wa_digi?.n_msgs || lead.n_msgs} small />}</div>
                {lead.empresa && lead.empresa !== lead.nome && <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{lead.empresa}{lead.cargo ? ` · ${lead.cargo}` : ''}</div>}
                {leadsPedidoLabel(lead.pedido) && <div style={{ fontSize: 11, color: '#9a3412', marginTop: 2 }}>{leadsPedidoLabel(lead.pedido)}</div>}
                {!lead.nome || lead.nome === 'Sem nome' ? <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>{lead.email || lead.telefone_mask || ''}</div> : null}
              </td>
              <td style={td}><LeadsFunilBadge estado={lead.estado_funil} /></td>
              <td style={td}><LeadsContactoEstado contacto={lead.contacto} quando={lead.contacto_em} /></td>
              <td style={td}>{(() => {
                const n = leadsScoreNumero(lead.score);
                const cor = n >= 70 ? '#15803d' : n >= 50 ? '#d97706' : '#9f1239';
                return <span style={{ fontWeight: 650, fontVariantNumeric: 'tabular-nums', color: cor }}>{n}</span>;
              })()}</td>
              {mostrarTema && <td style={td}>
                <LeadsTemaBadge catalogo={temasCatalogo} tema={lead.tema} small />
                {(lead.produto || lead.sub_tema || lead.valor_proposta) && <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 4 }}>{[lead.produto || lead.sub_tema, leadsEur(lead.valor_proposta)].filter(Boolean).join(' · ')}</div>}
              </td>}
              <td style={td}>{leadsOrigem(lead, catalogo)}</td>
              <td style={td}>{lead.n_submissoes || (lead.entradas || []).length || 1}{lead.n_repetidas ? <span title="Submissões repetidas em poucos segundos (duplo clique)" style={{ color: 'var(--text-dim)', fontSize: 11 }}> +{lead.n_repetidas} rep.</span> : null}</td>
              <td style={{ ...td, color: 'var(--text-muted)', fontSize: 11 }}>{leadsData(lead.at)}</td>
              <td style={td}>
                <div style={{ fontSize: 11, color: lead.crm_nivel === 'forte' || lead.crm_nivel === 'confirmado' ? '#15803d' : lead.crm_nivel === 'sem_match' ? 'var(--text-dim)' : '#b45309' }}>{LEADS_CRM_LABEL[lead.crm_nivel] || 'Não está na BD'}</div>
                {lead.crm_entidade && <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{lead.crm_entidade}</div>}
                {!lead.crm_entidade && (lead.crm_candidatos || []).length > 0 && <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{lead.crm_candidatos.slice(0, 2).map(c => c.nome).filter(Boolean).join(' · ')}</div>}
                {lead.gestor && (lead.gestor.abertas || lead.gestor.ganhas || lead.gestor.perdidas) ? <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{[lead.gestor.abertas ? `${lead.gestor.abertas} abertas` : '', lead.gestor.ganhas ? `${lead.gestor.ganhas} ganhas` : '', lead.gestor.perdidas ? `${lead.gestor.perdidas} perdidas` : ''].filter(Boolean).join(' · ')}</div> : null}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function LeadsFunilLista({ rows, onOpen }) {
  const th = { textAlign: 'left', fontSize: 10, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-dim)', padding: '8px 10px', borderBottom: '1px solid var(--border)', fontWeight: 600 };
  const td = { padding: '10px', borderBottom: '1px solid var(--border)', fontSize: 12, verticalAlign: 'top', overflowWrap: 'anywhere' };
  return (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, minWidth: 0, maxWidth: '100%' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse', tableLayout: 'fixed' }}>
        <thead>
          <tr>
            <th style={{ ...th, width: '34%' }}>Pessoa</th>
            <th style={{ ...th, width: '22%' }}>Etapa</th>
            <th style={{ ...th, width: '22%' }}>Entrada</th>
            <th style={{ ...th, width: '22%' }}>Empresa no formulário</th>
          </tr>
        </thead>
        <tbody>
          {rows.map(lead => (
            <tr key={lead.chave || lead.ref} onClick={() => onOpen(lead)} style={{ cursor: 'pointer' }}>
              <td style={td}><div style={{ fontWeight: 650, fontSize: 13 }}>{leadsNome(lead.nome)}</div>{leadsPedidoLabel(lead.pedido) && <div style={{ fontSize: 11, color: '#9a3412', marginTop: 2 }}>{leadsPedidoLabel(lead.pedido)}</div>}</td>
              <td style={td}><LeadsFunilBadge estado={lead.estado_funil} /></td>
              <td style={{ ...td, color: 'var(--text-muted)' }}>{leadsData(lead.at)}</td>
              <td style={td}>{lead.empresa && lead.empresa !== lead.nome ? lead.empresa : ''}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function LeadsCrmTabela({ rows, onOpen, sort, onSort }) {
  const th = { textAlign: 'left', fontSize: 10, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-dim)', padding: '8px 10px', borderBottom: '1px solid var(--border)', fontWeight: 600, cursor: 'pointer', background: 'none', overflowWrap: 'anywhere' };
  const td = { padding: '10px', borderBottom: '1px solid var(--border)', fontSize: 12, verticalAlign: 'top', overflowWrap: 'anywhere' };
  const mark = (id) => sort?.key === id ? (sort.dir === 'asc' ? ' ↑' : ' ↓') : '';
  const colunas = [['nome', 'Pessoa', '22%'], ['entidade', 'Entidade no Gestor', '28%'], ['abertas', 'Abertas', '12%'], ['ganhas', 'Ganhas', '20%'], ['perdidas', 'Perdidas', '18%']];
  if (!rows.length) return <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 28, color: 'var(--text-muted)', fontSize: 12 }}>Sem pessoas neste grupo.</div>;
  return (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, minWidth: 0, maxWidth: '100%' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse', tableLayout: 'fixed' }}>
        <thead>
          <tr>
            {colunas.map(([id, label, width]) => (
              <th key={id} style={{ ...th, width }} onClick={() => onSort(id)}>{label}{mark(id)}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map(lead => {
            const g = lead.gestor || {};
            const naBd = lead.crm_nivel === 'forte' || lead.crm_nivel === 'confirmado';
            const entidade = lead.crm_entidade || (lead.crm_candidatos || []).slice(0, 2).map(c => c.nome).filter(Boolean).join(' · ');
            return (
              <tr key={lead.chave || lead.ref} onClick={() => onOpen(lead)} style={{ cursor: 'pointer' }}>
                <td style={td}>
                  <div style={{ fontWeight: 650, fontSize: 13 }}>{leadsNome(lead.nome)}</div>
                  {lead.empresa && lead.empresa !== lead.nome ? <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{lead.empresa}</div> : null}
                </td>
                <td style={td}>
                  <div style={{ fontSize: 11, color: naBd ? '#15803d' : lead.crm_nivel === 'sem_match' || !lead.crm_nivel ? 'var(--text-dim)' : '#b45309' }}>{LEADS_CRM_LABEL[lead.crm_nivel] || 'Não está na BD'}{lead.crm_tenant ? ` · ${lead.crm_tenant}` : ''}</div>
                  {entidade ? <div style={{ marginTop: 2 }}>{entidade}</div> : null}
                  {lead.crm_contacto ? <div style={{ marginTop: 2, fontSize: 11, color: 'var(--text-muted)' }}>{lead.crm_contacto}</div> : null}
                </td>
                <td style={td}>{naBd ? (g.abertas || 0) : ''}</td>
                <td style={td}>{naBd ? `${g.ganhas || 0}${g.valor_ganho ? ` · ${leadsEur(g.valor_ganho)}` : ''}` : ''}</td>
                <td style={td}>{naBd ? (g.perdidas || 0) : ''}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function parseLeadsHash() {
  const q = new URLSearchParams((window.location.hash || '').replace(/^#/, ''));
  return { lista: q.get('lista') || '', pessoa: q.get('pessoa') || '', tab: q.get('tab') || 'resumo', vista: q.get('vista') || 'pessoas', periodo: q.get('periodo') || '' };
}

function setLeadsHash(patch) {
  const m = { ...parseLeadsHash(), ...patch };
  const p = new URLSearchParams();
  p.set('screen', 'marketing');
  const subActual = new URLSearchParams((window.location.hash || '').replace(/^#/, '')).get('sub');
  const modulo = m.modulo || (subActual === 'leads-inbound' ? 'inbound' : 'outbound');
  p.set('sub', modulo === 'inbound' ? 'leads-inbound' : 'leads-outbound');
  if (m.periodo) p.set('periodo', m.periodo);
  if (m.vista && m.vista !== 'pessoas') p.set('vista', m.vista);
  if (m.lista) p.set('lista', m.lista);
  if (m.pessoa) p.set('pessoa', m.pessoa);
  if (m.pessoa && m.tab) p.set('tab', m.tab);
  const next = p.toString();
  if ((window.location.hash || '').replace(/^#/, '') !== next) window.location.hash = next;
}

function LeadsKpis({ funil, active, onPick }) {
  const items = [
    { id: 'leads', label: 'Leads', value: funil.geradas ?? 0, accent: '#3859D0', fill: 1 },
    { id: 'qualificadas', label: 'Leads qualificadas', value: funil.qualificadas ?? 0, accent: '#0891b2', fill: funil.geradas ? (funil.qualificadas || 0) / funil.geradas : 0 },
    { id: 'oportunidades', label: 'Oportunidades', value: funil.oportunidades ?? 0, accent: '#d97706', fill: funil.qualificadas ? (funil.oportunidades || 0) / funil.qualificadas : 0 },
    { id: 'vendas', label: 'Vendas', value: funil.vendas ?? 0, accent: '#15803d', fill: funil.oportunidades ? (funil.vendas || 0) / funil.oportunidades : 0 },
  ];
  return (
    <div style={{ display: 'flex', gap: 12 }}>
      {items.map(k => {
        const on = active === k.id;
        return (
          <div key={k.id} onClick={() => onPick(on ? 'all' : 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 }}>{Number(k.value).toLocaleString('pt-PT')}</div>
            <div style={{ height: 3, background: 'var(--bg-sunken)', overflow: 'hidden' }}><div style={{ height: '100%', width: `${Math.min(100, (k.fill || 0) * 100)}%`, background: k.accent }} /></div>
          </div>
        );
      })}
    </div>
  );
}

function LeadsCard({ c, catalogo, temasCatalogo, onOpen }) {
  if (c.tipo === 'tema') {
    const cor = c.cor || LEADS_TEMA_COR_DEFAULT;
    const naoComercial = c.comercial === false;
    return (
      <button type="button" onClick={() => onOpen(c)} title={c.descricao || ''} style={{ textAlign: 'left', background: '#fff', border: '1px solid var(--border)', borderBottom: `3px solid ${cor}`, borderRadius: 10, padding: 14, cursor: 'pointer', opacity: naoComercial ? 0.85 : 1 }}>
        <div style={{ fontSize: 11, color: 'var(--text-dim)', letterSpacing: '.04em', textTransform: 'uppercase' }}>Tema{naoComercial ? ' · fora do funil' : ''}{(c.sites || []).length ? ` · ${c.sites.map(s => String(s).toUpperCase()).join(' + ')}` : ''}</div>
        <div style={{ fontSize: 15, fontWeight: 700, marginTop: 4, color: cor }}>{c.titulo}</div>
        <div style={{ fontSize: 12, color: 'var(--text)', marginTop: 8 }}>{c.total || 0} pessoas · {c.qualificadas || 0} qualificadas · {c.oportunidades || 0} oportunidades · {c.vendas || 0} vendas</div>
        <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 4 }}>
          {c.valor_propostas ? `${leadsEur(c.valor_propostas)} em propostas · ` : ''}{c.na_bd || 0} na BD CRM{c.internas ? ` · ${c.internas} internas` : ''}
        </div>
        {(c.produtos || []).length > 0 && <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 6 }}>{c.produtos.slice(0, 4).map(p => `${p.produto} (${p.n})`).join(' · ')}</div>}
        {!(c.produtos || []).length && (c.sub_temas || []).length > 0 && <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 6 }}>{c.sub_temas.slice(0, 4).map(p => `${p.sub_tema} (${p.n})`).join(' · ')}</div>}
        {(!naoComercial || c.qualificadas || c.oportunidades || c.vendas) ? <div style={{ display: 'flex', height: 4, borderRadius: 99, overflow: 'hidden', marginTop: 10, background: 'var(--bg-sunken)' }}>
          {[['lead', '#3859D0', Math.max(0, (c.total || 0) - (c.qualificadas || 0) - (c.oportunidades || 0) - (c.vendas || 0))], ['qualificada', '#0891b2', c.qualificadas || 0], ['oportunidade', '#d97706', c.oportunidades || 0], ['venda', '#15803d', c.vendas || 0]].map(([id, color, n]) => (
            <div key={id} style={{ width: `${c.total ? (n / c.total) * 100 : 0}%`, background: color }} />
          ))}
        </div> : null}
      </button>
    );
  }
  const cor = c.vendas ? '#15803d' : c.oportunidades ? '#d97706' : c.qualificadas ? '#0891b2' : (c.tipo === 'site' ? '#112954' : '#3859D0');
  const tipo = c.tipo === 'site' ? `Site · ${c.mercado}` : c.tipo === 'canal' ? 'Canal' : (c.tipo === 'anuncios-sem-campanha' || c.tipo === 'outbound-sem-campanha') ? 'Sem campanha' : `Campanha · ${(c.canais || []).map(id => leadsCanalLabel(catalogo, id)).join(' · ') || 'Sem canal'}`;
  const temasCard = Object.entries(c.temas || {}).filter(([k]) => k !== 'sem_tema').sort((a, b) => b[1] - a[1]).slice(0, 4);
  return (
    <button type="button" onClick={() => onOpen(c)} title={c.tipo === 'site' ? 'Submissões sem UTM de campanha' : ''} style={{ textAlign: 'left', background: '#fff', border: '1px solid var(--border)', borderBottom: `3px solid ${cor}`, borderRadius: 10, padding: 14, cursor: 'pointer' }}>
      {typeof BrandMark === 'function' && <BrandMark brand={leadsBrand(c.marca_nome || c.marca)} empty="" />}
      <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 6, letterSpacing: '.04em', textTransform: 'uppercase' }}>{tipo}</div>
      <div style={{ fontSize: 15, fontWeight: 700, marginTop: 4 }}>{c.titulo}</div>
      <div style={{ fontSize: 12, color: 'var(--text)', marginTop: 8 }}>{c.total || 0} pessoas · {c.qualificadas || 0} qualificadas · {c.oportunidades || 0} oportunidades · {c.vendas || 0} vendas</div>
      {(c.amostras || c.reunioes) ? <div style={{ fontSize: 11, color: '#9a3412', marginTop: 4 }}>{[c.amostras ? `${c.amostras} pedidos de amostras` : '', c.reunioes ? `${c.reunioes} pedidos de reunião` : ''].filter(Boolean).join(' · ')}</div> : null}
      {c.meta_activa && <div style={{ fontSize: 11, color: '#15803d', marginTop: 4 }}>ACTIVE no Facebook · as leads do formulário entram nesta lista</div>}
      <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 4 }}>{c.na_bd || 0} na BD CRM · {c.possiveis || 0} possíveis{c.nao_comerciais ? ` · ${c.nao_comerciais} fora do funil` : ''}</div>
      {temasCard.length > 0 && <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 6 }}>{temasCard.map(([t, n]) => `${leadsTemaLabel(temasCatalogo, t)} ${n}`).join(' · ')}</div>}
      <div style={{ display: 'flex', height: 4, borderRadius: 99, overflow: 'hidden', marginTop: 10, background: 'var(--bg-sunken)' }}>
        {[['lead', '#3859D0', Math.max(0, (c.total || 0) - (c.qualificadas || 0) - (c.oportunidades || 0) - (c.vendas || 0))], ['qualificada', '#0891b2', c.qualificadas || 0], ['oportunidade', '#d97706', c.oportunidades || 0], ['venda', '#15803d', c.vendas || 0]].map(([id, color, n]) => (
          <div key={id} style={{ width: `${c.total ? (n / c.total) * 100 : 0}%`, background: color }} />
        ))}
      </div>
    </button>
  );
}

function LeadsConversaCaixa({ detalhe, onActualizar }) {
  const msgs = Array.isArray(detalhe?.conversa_fio) ? detalhe.conversa_fio : [];
  const outras = Array.isArray(detalhe?.conversa_outras) ? detalhe.conversa_outras : [];
  const material = detalhe?.conversa_material || null;
  const assumida = detalhe?.conversa_assumida || null;
  const ref = detalhe?.ref;
  const [texto, setTexto] = React.useState('');
  const [erro, setErro] = React.useState('');
  const [aEnviar, setAEnviar] = React.useState(false);
  const [correcaoRef, setCorrecaoRef] = React.useState('');
  const [comentario, setComentario] = React.useState('');
  const [historicoAberto, setHistoricoAberto] = React.useState(null);
  const hora = (iso) => {
    const d = iso ? new Date(iso) : null;
    if (!d || !Number.isFinite(d.getTime())) return '';
    return d.toLocaleString('pt-PT', { timeZone: 'Europe/Lisbon', day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
  };
  const agir = async (fn) => {
    setErro('');
    setAEnviar(true);
    try { await fn(); if (onActualizar) await onActualizar(); }
    catch (e) { setErro(e.message || 'Não foi possível gravar'); }
    finally { setAEnviar(false); }
  };
  const campanha = material?.campanha || (detalhe?.entradas || []).map(e => e.campanha_nome).find(Boolean) || '';
  const fichaConversa = material?.ficha_titulo
    ? `${material.ficha_titulo}${material.ficha_versao != null ? ` v${material.ficha_versao}` : ''}`
    : '';
  const fichaNaMensagem = msgs.some(m => m.ficha);
  const bolha = (m) => {
    const daLead = m.origem === 'lead';
    return (
      <div key={m.ref || m.created_at} style={{ display: 'flex', flexDirection: 'column', alignItems: daLead ? 'flex-start' : 'flex-end', gap: 4 }}>
        <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>{m.autor || (daLead ? 'Lead' : 'Digi AI')}</div>
        <div
          title={m.origem === 'digi' ? 'Clicar para corrigir' : undefined}
          onClick={m.origem === 'digi' ? () => { setCorrecaoRef(correcaoRef === m.ref ? '' : m.ref); setComentario(''); setErro(''); } : undefined}
          style={{
            maxWidth: 'min(78%, 440px)', padding: '10px 12px', fontSize: 14, lineHeight: 1.5, color: 'var(--text)', cursor: m.origem === 'digi' ? 'pointer' : 'default',
            background: daLead ? '#fff' : (m.origem === 'humano' ? '#fff' : 'color-mix(in oklch, var(--ai-500) 16%, #fff)'),
            border: '1px solid var(--border)',
            borderRadius: daLead ? '4px 16px 16px 16px' : '16px 4px 16px 16px',
          }}
        >
          <div style={{ whiteSpace: 'pre-wrap' }}>{m.content}</div>
          {m.created_at && <div style={{ marginTop: 6, fontSize: 11, color: 'var(--text-dim)', textAlign: daLead ? 'left' : 'right' }}>{hora(m.created_at)}</div>}
        </div>
        {(m.correcoes || []).map((c, i) => (
          <div key={i} style={{ maxWidth: 'min(78%, 440px)', fontSize: 12, color: 'var(--text-muted)' }}>{c.autor ? `${c.autor}: ` : ''}{c.comentario}</div>
        ))}
        {m.origem === 'digi' && correcaoRef === m.ref && (
          <div style={{ width: 'min(78%, 440px)', display: 'flex', flexDirection: 'column', gap: 6 }}>
            <textarea value={comentario} onChange={e => setComentario(e.target.value)} rows={3} placeholder="O que a Digi deve corrigir nesta conversa" style={{ width: '100%', fontSize: 13, padding: 8, borderRadius: 8, border: '1px solid var(--border)', resize: 'vertical' }} />
            <div style={{ display: 'flex', gap: 6, justifyContent: 'flex-end' }}>
              <button type="button" className="btn" onClick={() => { setCorrecaoRef(''); setComentario(''); }}>Cancelar</button>
              <button type="button" className="btn" disabled={aEnviar || !comentario.trim()} onClick={() => agir(async () => {
                await leadsPost('/api/marketing/crm/leads/pessoa/' + encodeURIComponent(ref) + '/correcao', { mensagem_ref: m.ref, excerto: m.content, comentario, campanha });
                setCorrecaoRef('');
                setComentario('');
              })}>Guardar</button>
            </div>
          </div>
        )}
      </div>
    );
  };
  const linhaTec = (k, v) => (v == null || String(v) === '') ? null : (
    <div key={k} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, fontSize: 13, lineHeight: 1.4 }}>
      <span style={{ color: 'var(--text-muted)', flexShrink: 0 }}>{k}</span>
      <span style={{ textAlign: 'right' }}>{v}</span>
    </div>
  );
  const dia = (iso) => {
    const d = iso ? new Date(iso) : null;
    if (!d || !Number.isFinite(d.getTime())) return '';
    return d.toLocaleDateString('pt-PT', { timeZone: 'Europe/Lisbon', day: '2-digit', month: 'short', year: 'numeric' });
  };
  const estado = detalhe?.qualificacao_estado?.label || '';
  const tecnicas = (m) => [
    linhaTec('Estado', m.estado),
    linhaTec('Toque', m.toque),
    linhaTec('Hora', hora(m.created_at)),
    linhaTec('Ficha', m.ficha),
    linhaTec('Nota', m.nota == null || m.nota === '' ? '' : m.nota),
    linhaTec('Modelo', m.modelo),
    linhaTec('Custo', m.custo),
  ].filter(Boolean);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
    <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start' }}>
      <div style={{ flex: '1 1 0', minWidth: 0, background: '#fff', border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
      <div style={{ padding: '14px 16px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'flex-start' }}>
        <div>
          <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-muted)' }}>Esta campanha</div>
          <div style={{ fontSize: 13, fontWeight: 650, marginTop: 4 }}>{campanha || 'Conversa'}</div>
        </div>
        {estado ? <div style={{ fontSize: 12, fontWeight: 650, color: 'var(--text)', background: '#F4F6F8', borderRadius: 999, padding: '4px 10px', whiteSpace: 'nowrap' }}>{estado}</div> : null}
      </div>
      <div style={{ background: '#F4F6F8', minHeight: msgs.length ? 480 : 180, padding: '16px 14px 18px', display: 'flex', flexDirection: 'column', gap: 16, flex: 1 }}>
        {!msgs.length && <div style={{ fontSize: 13, color: 'var(--text-muted)', lineHeight: 1.45 }}>A Digi ainda não falou com {detalhe?.nome || 'esta lead'} nesta campanha.</div>}
        {msgs.map(bolha)}
      </div>
      {assumida && (
        <div style={{ padding: 12, borderTop: '1px solid var(--border)', display: 'flex', flexDirection: 'column', gap: 8 }}>
          <textarea value={texto} onChange={e => setTexto(e.target.value)} rows={3} placeholder="Mensagem pelo WhatsApp da Digi" style={{ width: '100%', fontSize: 13, padding: 8, borderRadius: 8, border: '1px solid var(--border)', resize: 'vertical' }} />
          {!detalhe?.janela_24h && <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>O texto livre só sai nas 24 horas a seguir à última mensagem da lead.</div>}
          <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
            <button type="button" className="btn" disabled={aEnviar || !texto.trim()} onClick={() => agir(async () => {
              await leadsPost('/api/marketing/crm/leads/pessoa/' + encodeURIComponent(ref) + '/mensagem', { texto });
              setTexto('');
            })}>Enviar</button>
          </div>
        </div>
      )}
      </div>
      <div style={{ width: 300, flexShrink: 0, position: 'sticky', top: 16, background: '#fff', border: '1px solid var(--border)', borderRadius: 12, padding: 16, display: 'flex', flexDirection: 'column', gap: 14 }}>
        {assumida
          ? <button type="button" className="btn" disabled={aEnviar} onClick={() => agir(() => leadsPost('/api/marketing/crm/leads/pessoa/' + encodeURIComponent(ref) + '/devolver', {}))}>Devolver à Digi</button>
          : <button type="button" className="btn" disabled={aEnviar} onClick={() => agir(() => leadsPost('/api/marketing/crm/leads/pessoa/' + encodeURIComponent(ref) + '/assumir', {}))}>Assumir</button>}
        {assumida && <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Assumida por {assumida.por || 'equipa'}.</div>}
        {fichaConversa && !fichaNaMensagem && linhaTec('Ficha', fichaConversa)}
        {msgs.map((m) => {
          const linhas = tecnicas(m);
          if (!linhas.length) return null;
          return (
            <div key={m.ref || m.created_at} style={{ display: 'flex', flexDirection: 'column', gap: 6, paddingTop: 12, borderTop: '1px solid var(--border)' }}>
              <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>{m.autor || (m.origem === 'lead' ? 'Lead' : 'Digi AI')}</div>
              {linhas}
            </div>
          );
        })}
        {erro && <div style={{ fontSize: 12, color: '#9f1239' }}>{erro}</div>}
      </div>
    </div>
    {outras.length > 0 && (
      <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 12, padding: '14px 16px' }}>
        <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-muted)' }}>Mesmo telemóvel</div>
        <div style={{ fontSize: 13, color: 'var(--text-muted)', marginTop: 6, lineHeight: 1.45 }}>Histórico de outro formulário neste número.</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 12 }}>
          {outras.map((g, gi) => {
            const aberto = historicoAberto === gi;
            const datas = (g.mensagens || []).map(m => m.created_at).filter(Boolean).sort();
            const quando = datas.length ? dia(datas[0]) : '';
            const n = (g.mensagens || []).length;
            return (
              <div key={`${g.campanha}-${gi}`} style={{ border: '1px solid var(--border)', borderRadius: 10, overflow: 'hidden' }}>
                <button type="button" onClick={() => setHistoricoAberto(aberto ? null : gi)} style={{ width: '100%', textAlign: 'left', background: '#fff', border: 'none', padding: '12px 14px', cursor: 'pointer', display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'center' }}>
                  <span>
                    <span style={{ display: 'block', fontSize: 13, fontWeight: 650, color: 'var(--text)' }}>{[g.nome, g.empresa].filter(Boolean).join(' · ') || g.campanha}</span>
                    <span style={{ display: 'block', marginTop: 2, fontSize: 12, color: 'var(--text-muted)' }}>{[g.campanha, quando, n === 1 ? '1 mensagem' : `${n} mensagens`].filter(Boolean).join(' · ')}</span>
                  </span>
                  <span style={{ fontSize: 12, fontWeight: 650, color: 'var(--text-muted)', flexShrink: 0 }}>{aberto ? 'Fechar' : 'Abrir'}</span>
                </button>
                {aberto && (
                  <div style={{ background: '#F4F6F8', padding: '14px', display: 'flex', flexDirection: 'column', gap: 12, borderTop: '1px solid var(--border)' }}>
                    {(g.mensagens || []).map(bolha)}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    )}
    </div>
  );
}

function LeadsNotas({ detalhe, onActualizar }) {
  const [texto, setTexto] = React.useState('');
  const [erro, setErro] = React.useState('');
  const [aGravar, setAGravar] = React.useState(false);
  const notas = detalhe?.notas || [];
  const gravar = async () => {
    const corpo = texto.trim();
    if (!corpo || aGravar) return;
    setErro('');
    setAGravar(true);
    try {
      await leadsPost('/api/marketing/crm/leads/pessoa/' + encodeURIComponent(detalhe?.ref || '') + '/nota', { corpo });
      setTexto('');
      if (onActualizar) await onActualizar();
    } catch (e) {
      setErro(e.message || 'Não foi possível gravar');
    } finally {
      setAGravar(false);
    }
  };
  return (
    <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: '14px 16px' }}>
      <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 10 }}>Notas</div>
      <textarea value={texto} onChange={e => setTexto(e.target.value)} rows={4} placeholder="Nota sobre esta lead" style={{ width: '100%', fontSize: 13, padding: 8, borderRadius: 8, border: '1px solid var(--border)', resize: 'vertical', fontFamily: 'inherit' }} />
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, marginTop: 8 }}>
        <div style={{ fontSize: 12, color: '#9f1239' }}>{erro}</div>
        <button type="button" className="btn" disabled={aGravar || !texto.trim()} onClick={gravar}>Guardar</button>
      </div>
      {notas.length ? (
        <div style={{ marginTop: 14, display: 'flex', flexDirection: 'column', gap: 10 }}>
          {notas.map((n) => (
            <div key={n.id || n.created_at} style={{ borderTop: '1px solid var(--border)', paddingTop: 10 }}>
              <div style={{ fontSize: 13, whiteSpace: 'pre-wrap', lineHeight: 1.45 }}>{n.corpo}</div>
              <div style={{ marginTop: 6, fontSize: 11, color: 'var(--text-dim)' }}>{[n.autor_nome, n.created_at ? new Date(n.created_at).toLocaleString('pt-PT') : ''].filter(Boolean).join(' · ')}</div>
            </div>
          ))}
        </div>
      ) : <div style={{ marginTop: 12, fontSize: 13, color: 'var(--text-muted)' }}>Sem notas.</div>}
    </div>
  );
}

function LeadsFicha({ pessoa, detalhe, tab, onTab, erro, onRetry, onActualizar, catalogo, temasCatalogo, camposLabels }) {
  if (erro) return <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 28 }}><div style={{ fontSize: 13, color: '#9f1239' }}>{erro}</div><button type="button" className="btn" style={{ marginTop: 12 }} onClick={onRetry}>Tentar de novo</button></div>;
  if (!detalhe) return typeof AudCalcProgress === 'function' ? <AudCalcProgress message="A carregar a ficha…" /> : <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>A carregar…</div>;
  const card = (title, children, extra) => <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: '14px 16px' }}><div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}><div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-muted)' }}>{title}</div>{extra}</div>{children}</div>;
  const linha = (k, v) => <LeadsCampo label={k} valor={v} />;
  if (tab === 'origens') {
    // A ficha traz tema e campos por entrada; a lista só traz o resumo. Preferir a ficha quando tem o mesmo número.
    const daFicha = detalhe?.entradas || [];
    const daLista = pessoa?.entradas || [];
    const entradas = daFicha.length >= daLista.length ? daFicha : daLista;
    if (!entradas.length) return card('Origens', <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Sem origem registada.</div>);
    return <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>{entradas.map((en, i) => {
      const metaForm = leadsEhFormMeta(en);
      const anuncioEn = en.canal === 'meta_ads' || en.ad_id || en.ad_headline || en.anuncio
        ? leadsAnuncioVisivel(en, detalhe, pessoa)
        : leadsAnuncioVisivel(en);
      const campos = en.campos || en.origem?.campos;
      const temCampos = Array.isArray(campos) ? campos.length > 0 : campos && Object.keys(campos).length > 0;
      return (
      <div key={i} style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: '14px 16px', fontSize: 13, opacity: en.repetida ? 0.6 : 1 }}>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
          <span style={{ fontWeight: 650 }}>{leadsTituloOrigem(en)}</span>
          <span style={{ fontSize: 10, fontWeight: 700, letterSpacing: '.04em', textTransform: 'uppercase', color: en.modulo === 'outbound' ? '#9a3412' : '#1d4ed8' }}>{en.modulo === 'outbound' ? 'Outbound' : 'Inbound'}</span>
          {en.canal !== 'meta_ads' && (en.conversa_digi || en.visitor_id) && <LeadsWaBadge n={en.n_msgs} />}
          <LeadsTemaBadge catalogo={temasCatalogo} tema={en.tema} small />
          {en.repetida && <span style={{ fontSize: 10, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.04em' }}>Submissão repetida</span>}
          <LeadsInternaBadge interna={en.interna} />
        </div>
        {(() => {
          const campos = Array.isArray(en.campos) ? en.campos : [];
          const valor = (id) => String(campos.find(c => c.campo === id)?.valor || '').trim();
          const pessoaForm = [valor('full_name') || valor('nome'), valor('company_name') || valor('empresa')].filter(Boolean).join(' · ');
          const historico = en.conversa_digi || en.visitor_id ? (detalhe.conversa_outras || []) : [];
          if (!pessoaForm && !historico.length) return null;
          return (
            <div style={{ marginTop: 8, display: 'flex', flexDirection: 'column', gap: 2 }}>
              {pessoaForm ? <div style={{ fontSize: 13, fontWeight: 650 }}>{pessoaForm}</div> : null}
              {historico.map((g, gi) => <div key={gi} style={{ fontSize: 13, color: 'var(--text-muted)' }}>{[g.nome, g.empresa, g.campanha].filter(Boolean).join(' · ')}</div>)}
            </div>
          );
        })()}
        <div style={{ marginTop: 12 }}>
          <LeadsGrelha>
            <LeadsCampo label="Canal" valor={leadsCanalLabel(catalogo, en.canal)} />
            <LeadsCampo label="Entrada" valor={leadsMeioOrigem(en)} />
            <LeadsCampo label="Campanha" valor={en.campanha_nome} />
            <LeadsCampo label="Iniciado por" valor={en.iniciado_por || (en.direccao === 'outbound' ? 'Digidelta' : 'Lead')} />
            <LeadsCampo label="Produto" valor={en.produto || en.sub_tema} />
            <LeadsCampo label="Valor" valor={leadsEur(en.valor_proposta)} />
          </LeadsGrelha>
        </div>
        <div style={{ marginTop: 14 }}><LeadsAnuncioBloco anuncio={anuncioEn} campanha={en.campanha_nome} leadgenId={en.meta_leadgen_id} campanhaPortalId={en.campanha_portal_id} /></div>
        {(en.page_url || en.origem?.page) && <div style={{ marginTop: 6, fontSize: 12, color: 'var(--text-muted)', overflowWrap: 'anywhere' }}>{en.page_url || en.origem.page}</div>}
        {en.origem?.utm && Object.keys(en.origem.utm).length > 0 && <div style={{ marginTop: 4, fontSize: 11, color: 'var(--text-dim)' }}>{Object.entries(en.origem.utm).map(([k, v]) => `${k}=${v}`).join(' · ')}</div>}
        {temCampos && <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px solid var(--border)' }}><LeadsCampos campos={campos} labels={camposLabels} ficheiros={en.ficheiros || en.origem?.ficheiros} /></div>}
        {metaForm && !temCampos && <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px solid var(--border)', fontSize: 13, color: 'var(--text-muted)' }}>{detalhe?.formulario_meta?.motivo || 'Os campos submetidos neste formulário Meta ainda não estão gravados nesta lead.'}</div>}
        <div style={{ marginTop: 8, fontSize: 11, color: 'var(--text-dim)' }}>{en.at ? new Date(en.at).toLocaleString('pt-PT') : ''}</div>
      </div>
      );
    })}</div>;
  }
  if (tab === 'conversa') {
    return <LeadsConversaCaixa detalhe={detalhe} onActualizar={onActualizar} />;
  }
  if (tab === 'notas') {
    return <LeadsNotas detalhe={detalhe} onActualizar={onActualizar} />;
  }
  const crm = detalhe.crm || {};
  const temTema = !!(detalhe.tema || pessoa?.tema);
  const form = detalhe.formulario || null;
  const entradasOrigem = (detalhe.entradas || []).length ? detalhe.entradas : (pessoa?.entradas || []);
  const entradaMeta = entradasOrigem.find(e => e.canal === 'meta_ads' || e.ad_id || e.ad_headline || e.anuncio?.ad_id) || entradasOrigem[0] || null;
  const anuncio = leadsAnuncioVisivel(detalhe, entradaMeta, pessoa, ...(detalhe.entradas || []), ...(pessoa?.entradas || []));
  const metaAds = entradaMeta?.canal === 'meta_ads' || pessoa?.canal === 'meta_ads' || !!(anuncio?.ad_id || anuncio?.ad_name);
  const metaForm = entradasOrigem.some(leadsEhFormMeta) || !!anuncio?.form_id;
  const meio = metaAds ? leadsMeioOrigem({ ...entradaMeta, canal: entradaMeta?.canal || pessoa?.canal || 'meta_ads', anuncio }) : leadsDestinoLabel(entradaMeta?.destino);
  const respostaEmail = (detalhe.entradas || pessoa?.entradas || []).find(en => en.origem?.preview || en.origem?.pedido || en.pedido);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
      {respostaEmail && card('Resposta', <div>
        {leadsPedidoLabel(respostaEmail.origem?.pedido || respostaEmail.pedido) && <div style={{ fontWeight: 650, marginBottom: 6 }}>{leadsPedidoLabel(respostaEmail.origem?.pedido || respostaEmail.pedido)}</div>}
        {respostaEmail.origem?.assunto && <div style={{ fontSize: 13 }}>{respostaEmail.origem.assunto}</div>}
        {respostaEmail.origem?.preview && <div style={{ fontSize: 13, color: 'var(--text-muted)', marginTop: 6, whiteSpace: 'pre-wrap' }}>{respostaEmail.origem.preview}</div>}
      </div>)}
      {card('Contacto', <LeadsContacto detalhe={detalhe} camposLabels={camposLabels} metaForm={metaForm} anuncio={anuncio} entrada={entradaMeta} />, (() => { const n = leadsRespostasFormulario(detalhe.dados_formulario, camposLabels).length; return n > 0 ? <span style={{ fontSize: 11, color: 'var(--text-dim)' }}>{n} campos do formulário</span> : null; })())}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))', gap: 12 }}>
        {card('Origem', <div>
          <LeadsGrelha>
            <LeadsCampo label="Canal" valor={metaAds ? 'Meta Ads' : leadsCanalLabel(catalogo, entradaMeta?.canal)} />
            <LeadsCampo label="Entrada" valor={meio} />
            <LeadsCampo label="Campanha" valor={entradaMeta?.campanha_nome || pessoa?.campanha_nome} />
            <LeadsCampo label="Iniciado por" valor={entradaMeta?.iniciado_por || pessoa?.iniciado_por || 'Lead'} />
          </LeadsGrelha>
          <div style={{ marginTop: 14 }}><LeadsAnuncioBloco anuncio={anuncio} campanha={entradaMeta?.campanha_nome || pessoa?.campanha_nome} ids={false} /></div>
          {metaAds && !anuncio?.ad_name && !anuncio?.ad_id && <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 8 }}>Falta o anúncio: esta lead não tem o nome nem o ID do anúncio gravados.</div>}
        </div>)}
        {card('Qualificação', <LeadsScorePainel detalhe={detalhe} />, <span style={{ fontSize: 11, color: 'var(--text-dim)' }}>{detalhe.qualificacao_estado?.label || ''}{detalhe.score == null || detalhe.score === '' ? '' : `${detalhe.qualificacao_estado?.label ? ' · ' : ''}Score ${detalhe.score}`}</span>)}
      </div>
      {(detalhe.conversa_outras || []).length > 0 && card('Mesmo telemóvel', <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        <div style={{ fontSize: 13, color: 'var(--text-muted)', lineHeight: 1.45 }}>Há histórico de outro formulário neste número.</div>
        {(detalhe.conversa_outras || []).map((g, i) => <div key={i} style={{ fontSize: 13, fontWeight: 650 }}>{[g.nome, g.empresa, g.campanha].filter(Boolean).join(' · ')}</div>)}
        <div><button type="button" className="btn" onClick={() => onTab('conversa')}>Ver histórico</button></div>
      </div>)}
      {temTema && card('Pedido', <div>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', marginBottom: 12 }}>
          <LeadsTemaBadge catalogo={temasCatalogo} tema={detalhe.tema || pessoa?.tema} />
          {detalhe.comercial === false && <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>Fora do funil comercial</span>}
          <LeadsInternaBadge interna={detalhe.interna || pessoa?.interna} />
        </div>
        <LeadsGrelha>
          {linha('Produto', detalhe.produto || pessoa?.produto)}
          {linha('Valor da proposta', leadsEur(detalhe.valor_proposta || pessoa?.valor_proposta))}
          {linha('Formulário', form?.nome)}
          {linha('Site', form?.site ? String(form.site).toUpperCase() : '')}
          {linha('Submetido em', form?.submetido_em ? new Date(form.submetido_em).toLocaleString('pt-PT') : '')}
          {linha('Página', form?.page_url)}
          {linha('Submissões', `${detalhe.n_submissoes ?? pessoa?.n_submissoes ?? 1}${detalhe.n_repetidas ? ` (+${detalhe.n_repetidas} repetidas)` : ''}`)}
        </LeadsGrelha>
      </div>)}
      {detalhe.conversa && card('Conversa WhatsApp com a Digi', <LeadsConversaDigiResumo conversa={detalhe.conversa} onVer={() => onTab('conversa')} />, <span style={{ fontSize: 11, color: 'var(--text-dim)' }}>{detalhe.conversa.n_msgs} mensagens</span>)}
      {card('Gestor', <div>
        <div style={{ fontSize: 13 }}>{LEADS_CRM_LABEL[crm.nivel] || 'Não está na BD'}{crm.motivo ? ` · ${crm.motivo}` : ''}{(detalhe.gestor?.tenant || crm.tenant) ? ` · ${detalhe.gestor?.tenant || crm.tenant}` : ''}</div>
        {(() => {
          const g = detalhe.gestor;
          const ent = g?.entidade;
          const tot = g?.totais;
          return <div style={{ marginTop: 12 }}><LeadsGrelha>
            {linha('Entidade', ent?.nome || crm.entidade)}
            {linha('NIF', ent?.nif || crm.nif)}
            {linha('Cidade', ent?.cidade || crm.cidade)}
            {linha('País', ent?.pais || crm.pais)}
            {linha('Morada', [ent?.morada, ent?.zip].filter(Boolean).join(', '))}
            {linha('Website', ent?.website ? (/^https?:/.test(ent.website) ? ent.website : `https://${ent.website}`) : '')}
            {linha('Contacto', g?.contacto?.nome || crm.contacto)}
            {linha('Cargo no Gestor', g?.contacto?.cargo || crm.cargo)}
            {linha('Email no Gestor', g?.contacto?.email)}
            {linha('Abertas', tot ? `${tot.abertas} · ${leadsEur(tot.valor_aberto) || '0 €'}` : '')}
            {linha('Ganhas', tot ? `${tot.ganhas} · ${leadsEur(tot.valor_ganho) || '0 €'}` : '')}
            {linha('Perdidas', tot ? String(tot.perdidas) : '')}
          </LeadsGrelha></div>;
        })()}
        {(crm.candidatos || []).length > 0 && <div style={{ marginTop: 8, fontSize: 12, color: 'var(--text-muted)' }}>Possíveis no Gestor: {(crm.candidatos || []).map(c => c.nome).filter(Boolean).join(', ')}</div>}
        {(detalhe.oportunidades || []).length > 0 && <div style={{ marginTop: 16, fontSize: 10, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-dim)' }}>Oportunidades</div>}
        {(detalhe.oportunidades || []).map((o, i) => <div key={o.id || i} style={{ marginTop: 10 }}><LeadsGrelha>
          {linha('Produto', o.produto)}
          {linha('Etapa', o.etapa)}
          {linha('Estado', o.estado)}
          {linha('Valor', o.valor ? `${Number(o.valor).toLocaleString('pt-PT')} €` : '')}
          {linha('Equipa', o.equipa)}
          {linha('Início', o.inicio)}
          {linha('Nota', o.placeholder ? 'Valor de teste, não conta como venda' : (o.depois_da_lead ? '' : 'Anterior à lead'))}
        </LeadsGrelha></div>)}
        {!detalhe.gestor && crm.nivel !== 'forte' && crm.nivel !== 'confirmado' && <div style={{ marginTop: 8, fontSize: 12, color: 'var(--text-muted)' }}>Sem entidade confirmada no Gestor.</div>}
      </div>)}
      {card('HandOff e oportunidade', <div>
        {detalhe.handoff ? <div style={{ fontSize: 13 }}>{detalhe.handoff.motivo} · {detalhe.handoff.detectado_em ? new Date(detalhe.handoff.detectado_em).toLocaleString('pt-PT') : ''}</div> : <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Ainda sem HandOff.</div>}
        {detalhe.handoff?.pacote?.pedido && <div style={{ marginTop: 8, fontSize: 13 }}>{detalhe.handoff.pacote.pedido}</div>}
        {detalhe.handoff?.pacote?.rolo_teste && <div style={{ marginTop: 4, fontSize: 13 }}>Rolo de teste · {detalhe.handoff.pacote.rolo_teste}</div>}
        {detalhe.handoff?.pacote?.morada_envio && <div style={{ marginTop: 4, fontSize: 13 }}>Morada de envio · {detalhe.handoff.pacote.morada_envio}</div>}
        <div style={{ marginTop: 8, fontSize: 12, fontWeight: 650 }}>Dados para abrir oportunidade</div>
        {(detalhe.handoff?.checklist || []).map(item => <div key={item.id} style={{ fontSize: 12, marginTop: 4, color: item.ok ? '#15803d' : '#9f1239' }}>{item.ok ? 'OK' : 'Falta'} · {item.label}</div>)}
        <div style={{ marginTop: 12 }}><LeadsGrelha>
          {linha('Comercial previsto', detalhe.comercial_previsto?.nome)}
          {linha('Comercial atribuído', detalhe.comercial_atribuido)}
        </LeadsGrelha></div>
      </div>)}
    </div>
  );
}

function MktLeadsControlScreen({ userName, modulo = 'outbound' }) {
  const brandApi = window.useMktBrand ? window.useMktBrand() : { brand: 'todas', setBrand: () => {} };
  const marca = brandApi.brand || 'todas';
  const hash0 = parseLeadsHash();
  const [periodo, setPeriodo] = React.useState(hash0.periodo || (modulo === 'outbound' ? '2026' : '30d'));
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [erro, setErro] = React.useState('');
  window.useMktZoneLoading(loading && !data);
  const [q, setQ] = React.useState('');
  const [nav, setNav] = React.useState(hash0);
  const [filtroCanal, setFiltroCanal] = React.useState('all');
  const [filtroFunil, setFiltroFunil] = React.useState('all');
  const [filtroMarcaCard, setFiltroMarcaCard] = React.useState('all');
  const [qLista, setQLista] = React.useState('');
  const [filtroForm, setFiltroForm] = React.useState('all');
  const [filtroWa, setFiltroWa] = React.useState('all'); // all | com | sem — conversa WhatsApp com a Digi
  const [filtroEstado, setFiltroEstado] = React.useState('all');
  const [filtroScore, setFiltroScore] = React.useState('all');
  const [filtroCrm, setFiltroCrm] = React.useState('all');
  const [filtroVista, setFiltroVista] = React.useState('all');
  const [filtroIniciado, setFiltroIniciado] = React.useState('all');
  const [filtroTema, setFiltroTema] = React.useState('all');
  const [internas, setInternas] = React.useState('excluir'); // excluir | incluir | so
  const [sort, setSort] = React.useState({ key: 'at', dir: 'desc' });
  const [page, setPage] = React.useState(0);
  const [detalhe, setDetalhe] = React.useState(null);
  const [detalheErro, setDetalheErro] = React.useState('');
  const [detalheTick, setDetalheTick] = React.useState(0);

  const load = React.useCallback(() => {
    setLoading(true);
    setErro('');
    fetch('/api/marketing/crm/leads/inbox?' + leadsQs({ marca, periodo, q, modulo, internas }))
      .then(r => r.json())
      .then(d => { if (d.error) throw new Error(d.error); setData(d); })
      .catch(e => setErro(e.message))
      .finally(() => setLoading(false));
  }, [marca, periodo, q, modulo, internas]);
  React.useEffect(() => { load(); }, [load]);
  React.useEffect(() => {
    const onHash = () => setNav(parseLeadsHash());
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  React.useEffect(() => {
    if (!nav.pessoa) { setDetalhe(null); setDetalheErro(''); return; }
    let stop = false;
    const carregar = (inicial) => {
      if (inicial) { setDetalhe(null); setDetalheErro(''); }
      fetch('/api/marketing/crm/leads/pessoa/' + encodeURIComponent(nav.pessoa) + '?' + leadsQs())
        .then(r => r.json())
        .then(d => { if (stop) return; if (d.error) throw new Error(d.error); setDetalhe(d); if (!inicial) setDetalheErro(''); })
        .catch(e => { if (!stop && inicial) setDetalheErro(e.message || 'Não foi possível carregar a ficha'); });
    };
    carregar(true);
    const timer = setInterval(() => {
      fetch('/api/marketing/crm/leads/pessoa/' + encodeURIComponent(nav.pessoa) + '?' + leadsQs({ parte: 'qualificacao' }))
        .then(r => r.json())
        .then(d => {
          if (stop || d.error || d.score === undefined) return;
          setDetalhe(prev => prev && prev.ref === nav.pessoa ? { ...prev, ...d } : prev);
        })
        .catch(() => {});
    }, 8000);
    return () => { stop = true; clearInterval(timer); };
  }, [nav.pessoa, detalheTick]);

  const funil = data?.funil || {};
  const total = funil.geradas ?? data?.total ?? 0;
  const pctQual = funil.taxa_qualificadas ?? 0;
  const marcaLabel = marca === 'todas' ? 'todas as marcas' : (typeof AUD_BRANDS !== 'undefined' ? (AUD_BRANDS.find(b => b.slug === marca)?.name || marca) : marca);
  const brands = [{ slug: 'todas', name: 'Todas' }, ...((typeof AUD_BRAND_TABS !== 'undefined' ? AUD_BRAND_TABS : []))];
  const temasCatalogo = data?.temas_catalogo || [];
  const camposLabels = data?.campos_labels || {};
  const campanhaAberta = [...(data?.sites || []), ...(data?.canais || []), ...(data?.temas || []), ...(data?.campanhas || [])].find(c => String(c.id) === String(nav.lista));
  const abertoRows = campanhaAberta
    ? (campanhaAberta.tipo === 'tema'
      ? (data?.leads || []).filter(l => l.tema === campanhaAberta.tema)
      : (data?.leads || []).filter(l => String(l.campanha_id || l.campanha_portal_id) === String(campanhaAberta.id)))
    : [];
  const pessoa = (data?.leads || []).find(l => l.ref === nav.pessoa) || null;
  const formsLista = [...new Set(abertoRows.map(leadFormNome).filter(Boolean))].sort();
  const temasLista = [...new Set(abertoRows.map(l => l.tema).filter(Boolean))];
  const scoreOk = (lead) => {
    const s = leadsScoreNumero(lead.score);
    if (filtroScore === 'alto') return lead.score != null && s >= 70;
    if (filtroScore === 'medio') return lead.score != null && s >= 50 && s < 70;
    if (filtroScore === 'baixo') return s < 50;
    if (filtroScore === 'sem') return s == null;
    return true;
  };
  const crmOk = (lead) => {
    if (filtroCrm === 'all') return true;
    if (filtroCrm === 'na_bd') return lead.crm_nivel === 'forte' || lead.crm_nivel === 'confirmado';
    return lead.crm_nivel === filtroCrm;
  };
  const linhasListaBrutas = abertoRows.filter(l => {
    if (filtroForm !== 'all' && leadFormNome(l) !== filtroForm) return false;
    if (filtroTema !== 'all' && (l.tema || 'sem_tema') !== filtroTema) return false;
    if (filtroWa === 'com' && !l.conversa_digi) return false;
    if (filtroWa === 'sem' && l.conversa_digi) return false;
    if (filtroEstado !== 'all' && (l.estado_funil || 'lead') !== filtroEstado) return false;
    if (filtroCanal !== 'all' && l.canal !== filtroCanal) return false;
    if (filtroIniciado !== 'all' && (l.iniciado_por || (l.direccao === 'outbound' ? 'Digidelta' : 'Lead')) !== filtroIniciado) return false;
    if (!scoreOk(l) || !crmOk(l)) return false;
    if (qLista && !`${l.nome} ${l.empresa} ${l.email} ${leadFormNome(l)}`.toLowerCase().includes(qLista.toLowerCase())) return false;
    return true;
  });
  const linhasLista = leadsOrdenar(linhasListaBrutas, sort);
  const pageRows = linhasLista.slice(page * 50, page * 50 + 50);
  const idxPessoa = linhasLista.findIndex(l => l.ref === nav.pessoa);
  const anuncioPessoa = leadsAnuncioVisivel(detalhe, pessoa, ...(detalhe?.entradas || []), ...(pessoa?.entradas || []));

  const campsFiltradas = (data?.campanhas || []).filter(c => {
    if (filtroMarcaCard !== 'all' && (c.marca_nome || c.marca) !== filtroMarcaCard) return false;
    if (filtroCanal !== 'all' && !(c.canais || []).includes(filtroCanal)) return false;
    if (filtroFunil === 'leads') return c.total > 0;
    if (filtroFunil === 'qualificadas') return c.qualificadas > 0;
    if (filtroFunil === 'oportunidades') return (c.oportunidades || 0) > 0;
    if (filtroFunil === 'vendas') return (c.vendas || 0) > 0;
    if (filtroFunil === 'por_qualificar') return (c.novas || 0) > 0;
    if (filtroFunil === 'sem_leads') return !c.total;
    return true;
  });
  const gruposMarca = React.useMemo(() => {
    const map = new Map();
    for (const c of campsFiltradas) {
      const key = c.marca_nome || c.marca || 'Marca';
      if (!map.has(key)) map.set(key, []);
      map.get(key).push(c);
    }
    return [...map.entries()];
  }, [campsFiltradas]);
  const sitesVisiveis = modulo === 'inbound' ? (data?.sites || []).filter(c => filtroMarcaCard === 'all' || (c.marca_nome || c.marca) === filtroMarcaCard) : [];
  const canaisVisiveis = modulo === 'inbound' ? (data?.canais || []).filter(c => filtroCanal === 'all' || (c.canais || []).includes(filtroCanal)) : [];
  const temasVisiveis = modulo === 'inbound' ? (data?.temas || []).filter(c => (filtroTema === 'all' || c.tema === filtroTema) && (filtroCanal === 'all' || filtroCanal === 'site')) : [];

  const abrirLista = (c) => { setPage(0); setQLista(''); setFiltroForm('all'); setFiltroEstado('all'); setFiltroScore('all'); setFiltroCrm('all'); setFiltroIniciado('all'); if (c.tipo !== 'tema') setFiltroTema('all'); if (c.tipo === 'tema' || c.tipo === 'site') setFiltroCanal('all'); setLeadsHash({ lista: c.id, pessoa: '', tab: 'resumo', modulo }); };
  const abrirPessoa = (lead) => setLeadsHash({ lista: nav.lista, pessoa: lead.ref, tab: 'resumo', modulo });
  const mudarPeriodo = (id) => { setPeriodo(id); setLeadsHash({ periodo: id, modulo }); };

  const tabBtn = (id, label) => (
    <button key={id} type="button" onClick={() => setLeadsHash({ tab: id, modulo })} style={{ background: 'none', border: 'none', borderBottom: `2px solid ${nav.tab === id ? 'var(--ai-500)' : 'transparent'}`, color: nav.tab === id ? 'var(--text)' : 'var(--text-muted)', fontSize: 13, fontWeight: nav.tab === id ? 600 : 500, fontFamily: 'var(--font-display)', padding: '10px 18px 12px', cursor: 'pointer' }}>{label}</button>
  );

  const Header = modulo === 'outbound' && window.ActivacaoHeaderNew ? window.ActivacaoHeaderNew : null;
  const voltarInicio = () => setLeadsHash({ lista: '', pessoa: '', vista: 'pessoas', modulo });
  const voltarLista = () => setLeadsHash({ pessoa: '', vista: nav.vista || 'pessoas', modulo });
  let header;
  if (Header && nav.pessoa) {
    header = (
      <Header
        level={3}
        breadcrumb={[{ label: 'Marketing' }, { label: 'Outbound', onClick: voltarInicio }, { label: campanhaAberta?.titulo || 'Campanha', onClick: voltarLista }, { label: leadsNome(detalhe?.nome || pessoa?.nome) }]}
        title={leadsNome(detalhe?.nome || pessoa?.nome)}
        titleStyle={{ fontSize: 13, fontWeight: 650, fontFamily: 'var(--font-body, Inter, sans-serif)', letterSpacing: 'normal' }}
        subInfo={<span style={{ display: 'inline-flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', fontSize: 11, color: 'var(--text-muted)' }}><span>{[detalhe?.empresa || pessoa?.empresa, detalhe?.cargo || pessoa?.cargo].filter(Boolean).join(' · ')}</span><LeadsFunilBadge estado={detalhe?.estado_funil || pessoa?.estado_funil} />{anuncioPessoa?.ad_name ? <span>Anúncio {anuncioPessoa.ad_name}</span> : null}<span>{(detalhe?.score == null || detalhe?.score === '') && (pessoa?.score == null || pessoa?.score === '') ? (detalhe?.qualificacao_estado?.label || 'Ainda sem Digi') : (detalhe?.score ?? pessoa?.score)}</span></span>}
        subNav={[{ id: 'resumo', label: 'Resumo' }, { id: 'origens', label: `Origens (${Math.max((detalhe?.entradas || []).length, (pessoa?.entradas || []).length) || 0})` }, { id: 'conversa', label: `Conversa (${detalhe?.n_msgs || pessoa?.n_msgs || 0})` }, { id: 'notas', label: `Notas (${(detalhe?.notas || []).length || 0})` }]}
        subNavActive={nav.tab || 'resumo'}
        onSubNav={(id) => setLeadsHash({ tab: id, modulo })}
        extraMenu={linhasLista.length > 1 && (
          <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
            <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>{idxPessoa >= 0 ? `${idxPessoa + 1} de ${linhasLista.length}` : ''}</span>
            <button type="button" className="btn" disabled={idxPessoa <= 0} onClick={() => idxPessoa > 0 && abrirPessoa(linhasLista[idxPessoa - 1])}>Anterior</button>
            <button type="button" className="btn" disabled={idxPessoa < 0 || idxPessoa >= linhasLista.length - 1} onClick={() => idxPessoa >= 0 && idxPessoa < linhasLista.length - 1 && abrirPessoa(linhasLista[idxPessoa + 1])}>Seguinte</button>
          </div>
        )}
      />
    );
  } else if (Header && nav.lista) {
    header = (
      <Header
        level={2}
        breadcrumb={[{ label: 'Marketing' }, { label: 'Outbound', onClick: voltarInicio }, { label: campanhaAberta?.titulo || 'Campanha' }]}
        title={campanhaAberta?.titulo || 'Campanha'}
        subInfo={`${linhasLista.length.toLocaleString('pt-PT')} pessoas`}
        subNav={[{ id: 'pessoas', label: 'Pessoas' }, { id: 'funil', label: 'Funil' }, { id: 'crm', label: 'CRM' }]}
        subNavActive={nav.vista || 'pessoas'}
        onSubNav={(id) => { setFiltroVista('all'); setPage(0); setLeadsHash({ vista: id, modulo }); }}
      />
    );
  } else if (Header) {
    header = (
      <Header
        level={1}
        breadcrumb={[{ label: 'Marketing' }, { label: 'Outbound' }]}
        title="Outbound"
        subInfo={`${total.toLocaleString('pt-PT')} pessoas · ${pctQual || 0}% qualificadas · ${marcaLabel}`}
      />
    );
  } else if (nav.pessoa) {
    header = (
      <LeadsPageHeader
        compact
        breadcrumb={[{ label: `Marketing · Leads · ${modulo === 'inbound' ? 'Inbound' : 'Outbound'}`, onClick: () => setLeadsHash({ lista: '', pessoa: '', modulo }) }, { label: campanhaAberta?.titulo || 'Lista', onClick: () => setLeadsHash({ pessoa: '', modulo }) }, { label: leadsNome(detalhe?.nome || pessoa?.nome) }]}
        title={leadsNome(detalhe?.nome || pessoa?.nome)}
        sub={[detalhe?.empresa || pessoa?.empresa, anuncioPessoa?.ad_name ? `Anúncio ${anuncioPessoa.ad_name}` : '', detalhe?.tema_label || leadsTemaLabel(temasCatalogo, pessoa?.tema || detalhe?.tema) !== 'Sem tema' ? (detalhe?.tema_label || leadsTemaLabel(temasCatalogo, pessoa?.tema || detalhe?.tema)) : '', detalhe?.produto || pessoa?.produto, LEADS_FUNIL_LABEL[detalhe?.estado_funil || pessoa?.estado_funil] || 'Lead', (detalhe?.score == null || detalhe?.score === '') && (pessoa?.score == null || pessoa?.score === '') ? (detalhe?.qualificacao_estado?.label || 'Ainda sem Digi') : `Score ${detalhe?.score ?? pessoa?.score}`, `${detalhe?.n_submissoes ?? pessoa?.n_submissoes ?? 1} submissões`].filter(Boolean).join(' · ')}
        extra={linhasLista.length > 1 && (
          <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
            <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>{idxPessoa >= 0 ? `${idxPessoa + 1} de ${linhasLista.length}` : ''}</span>
            <button type="button" className="btn" disabled={idxPessoa <= 0} onClick={() => idxPessoa > 0 && abrirPessoa(linhasLista[idxPessoa - 1])}>Anterior</button>
            <button type="button" className="btn" disabled={idxPessoa < 0 || idxPessoa >= linhasLista.length - 1} onClick={() => idxPessoa >= 0 && idxPessoa < linhasLista.length - 1 && abrirPessoa(linhasLista[idxPessoa + 1])}>Seguinte</button>
          </div>
        )}
        tabs={<div style={{ display: 'flex' }}>{[['resumo', 'Resumo'], ['origens', `Origens (${Math.max((detalhe?.entradas || []).length, (pessoa?.entradas || []).length) || 0})`], ['conversa', `Conversa (${detalhe?.n_msgs || pessoa?.n_msgs || 0})`], ['notas', `Notas (${(detalhe?.notas || []).length})`]].map(([id, label]) => tabBtn(id, label))}</div>}
      />
    );
  } else if (nav.lista) {
    const n = {
      geradas: linhasLista.length,
      qualificadas: linhasLista.filter(l => l.estado_funil === 'qualificada').length,
      oportunidades: linhasLista.filter(l => l.estado_funil === 'oportunidade').length,
      vendas: linhasLista.filter(l => l.estado_funil === 'venda').length,
    };
    header = (
      <LeadsPageHeader
        breadcrumb={[{ label: `Marketing · Leads · ${modulo === 'inbound' ? 'Inbound' : 'Outbound'}`, onClick: () => setLeadsHash({ lista: '', pessoa: '', modulo }) }, { label: campanhaAberta?.tipo === 'site' ? 'Sites' : campanhaAberta?.tipo === 'canal' ? 'Canais' : campanhaAberta?.tipo === 'tema' ? 'Temas' : 'Campanhas' }, { label: campanhaAberta?.titulo || 'Lista' }]}
        title={campanhaAberta?.titulo || 'Lista'}
        sub={campanhaAberta?.comercial === false
          ? `${linhasLista.length.toLocaleString('pt-PT')} pessoas · fora do funil comercial${campanhaAberta?.descricao ? ` · ${campanhaAberta.descricao}` : ''}`
          : `${linhasLista.length.toLocaleString('pt-PT')} pessoas · ${n.qualificadas} qualificadas · ${n.oportunidades} oportunidades · ${n.vendas} vendas${campanhaAberta?.valor_propostas ? ` · ${leadsEur(campanhaAberta.valor_propostas)} em propostas` : ''}`}
        extra={typeof BrandMark === 'function' ? <BrandMark brand={leadsBrand(campanhaAberta?.marca_nome || campanhaAberta?.marca)} empty="" /> : null}
      />
    );
  } else {
    header = (
      <LeadsPageHeader
        breadcrumb={[{ label: 'Marketing' }, { label: 'Leads' }, { label: modulo === 'inbound' ? 'Inbound' : 'Outbound' }]}
        title={modulo === 'inbound' ? 'Inbound' : 'Outbound'}
        sub={`${total.toLocaleString('pt-PT')} pessoas · ${pctQual || 0}% qualificadas · ${marcaLabel}`}
        tabs={<div style={{ display: 'flex', overflowX: 'auto' }}>{brands.map(b => (
          <button key={b.slug} type="button" onClick={() => brandApi.setBrand(b.slug)} style={{ background: 'none', border: 'none', borderBottom: `2px solid ${marca === b.slug ? 'var(--ai-500)' : 'transparent'}`, color: marca === b.slug ? 'var(--text)' : 'var(--text-muted)', fontSize: 13, fontWeight: marca === b.slug ? 600 : 500, fontFamily: 'var(--font-display)', padding: '10px 18px 12px', cursor: 'pointer', whiteSpace: 'nowrap' }}>{b.name}</button>
        ))}</div>}
      />
    );
  }

  const drop = (label, value, onChange, options) => typeof AudFilterDropdown === 'function'
    ? <AudFilterDropdown label={label} value={value} onChange={onChange} options={options} />
    : null;

  const paginaConversa = !!(nav.pessoa && (nav.tab || 'resumo') === 'conversa');

  return (
    <LeadsShell>
      {!paginaConversa && header}
      <div className="scrollbar" style={{ flex: 1, minHeight: 0, overflowY: 'auto', overflowX: 'clip', padding: paginaConversa ? 0 : '28px 40px 48px', background: 'var(--bg)', display: 'flex', flexDirection: 'column', gap: paginaConversa ? 0 : 18 }}>
        {paginaConversa && header}
        <div style={paginaConversa ? { padding: '24px 40px 120px', display: 'flex', flexDirection: 'column', gap: 18 } : { display: 'contents' }}>
        {erro && <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 16, color: '#9f1239', fontSize: 13 }}>{erro} <button type="button" className="btn" style={{ marginLeft: 8 }} onClick={load}>Tentar de novo</button></div>}
        {loading && !nav.pessoa && typeof AudCalcProgress === 'function' && <AudCalcProgress message="A carregar as leads…" />}

        {!nav.lista && !nav.pessoa && data && (
          <>
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
              {drop('Período', periodo, mudarPeriodo, LEADS_PERIODOS.map(p => ({ value: p.id, label: p.label })))}
              {marca === 'todas' && drop('Marca', filtroMarcaCard, setFiltroMarcaCard, [{ value: 'all', label: 'Todas' }, ...[...new Set([...(data.campanhas || []).map(c => c.marca_nome || c.marca), ...(data.sites || []).map(c => c.marca_nome)].filter(Boolean))].map(name => ({ value: name, label: name }))])}
              {drop('Canal', filtroCanal, setFiltroCanal, [{ value: 'all', label: 'Todos' }, ...(data.catalogo || []).filter(c => c.modulo === modulo).map(c => ({ value: c.id, label: c.label }))])}
              {drop('Funil', filtroFunil, setFiltroFunil, [{ value: 'all', label: 'Todos' }, { value: 'leads', label: 'Com leads' }, { value: 'por_qualificar', label: 'Por qualificar' }, { value: 'qualificadas', label: 'Qualificadas' }, { value: 'oportunidades', label: 'Oportunidades' }, { value: 'vendas', label: 'Vendas' }, { value: 'sem_leads', label: 'Sem leads' }])}
              {modulo === 'inbound' && temasCatalogo.length > 0 && drop('Tema', filtroTema, setFiltroTema, [{ value: 'all', label: 'Todos' }, ...temasCatalogo.map(t => ({ value: t.id, label: t.label }))])}
              {modulo === 'inbound' && drop('Internas', internas, setInternas, [{ value: 'excluir', label: `Ocultar${data.internas_total ? ` (${data.internas_total})` : ''}` }, { value: 'incluir', label: 'Mostrar' }, { value: 'so', label: 'Só internas' }])}
              {(filtroCanal !== 'all' || filtroFunil !== 'all' || filtroMarcaCard !== 'all' || filtroTema !== 'all') && <button type="button" onClick={() => { setFiltroCanal('all'); setFiltroFunil('all'); setFiltroMarcaCard('all'); setFiltroTema('all'); }} style={{ background: 'none', border: 'none', color: 'var(--text-muted)', fontSize: 11, cursor: 'pointer' }}>limpar</button>}
              <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{campsFiltradas.length + sitesVisiveis.length + canaisVisiveis.length + temasVisiveis.length} listas</span>
            </div>
            <LeadsKpis funil={funil} active={filtroFunil} onPick={setFiltroFunil} />
            {modulo === 'inbound' && (funil.nao_comerciais > 0 || funil.valor_propostas > 0) && (
              <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: -8 }}>
                {data.cobertura && <span>{data.cobertura.pessoas_form.toLocaleString('pt-PT')} pessoas de formulário ({data.cobertura.submissoes_validas.toLocaleString('pt-PT')} submissões guardadas). {data.cobertura.repetidas.toLocaleString('pt-PT')} submissões repetidas agrupadas. {data.cobertura.testes.toLocaleString('pt-PT')} testes ocultos. </span>}
                {funil.valor_propostas > 0 && <span>{leadsEur(funil.valor_propostas)} em pedidos de proposta no período. </span>}
                {funil.nao_comerciais > 0 && <span>{funil.nao_comerciais} pessoas fora do funil comercial (recrutamento, newsletter). </span>}
                {funil.gestor_com_ganhos > 0 && <span>{funil.gestor_com_ganhos} pessoas com vendas no Gestor ({funil.gestor_ganhas} ganhas, {funil.gestor_abertas} abertas, {funil.gestor_perdidas} perdidas). O funil conta só as ganhas com valor acima de 1 €, ou as abertas, depois da primeira submissão. </span>}
                {funil.com_conversa_digi > 0 && <span>{funil.com_conversa_digi} leads de formulário também falaram com a Digi no WhatsApp. </span>}
                {data.internas_total > 0 && internas === 'excluir' && <span>{data.internas_total} internas ocultas.</span>}
              </div>
            )}
            {temasVisiveis.length > 0 && (
              <div>
                <div style={{ fontSize: 12, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 8 }}>Temas</div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 12 }}>{temasVisiveis.map(c => <LeadsCard key={c.id} c={c} catalogo={data.catalogo} temasCatalogo={temasCatalogo} onOpen={abrirLista} />)}</div>
              </div>
            )}
            {sitesVisiveis.length > 0 && (filtroCanal === 'all' || filtroCanal === 'site') && (
              <div>
                <div style={{ fontSize: 12, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 8 }}>Sites</div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 12 }}>{sitesVisiveis.map(c => <LeadsCard key={c.id} c={c} catalogo={data.catalogo} temasCatalogo={temasCatalogo} onOpen={abrirLista} />)}</div>
              </div>
            )}
            {canaisVisiveis.length > 0 && (
              <div>
                <div style={{ fontSize: 12, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 8 }}>Canais</div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 12 }}>{canaisVisiveis.map(c => <LeadsCard key={c.id} c={c} catalogo={data.catalogo} temasCatalogo={temasCatalogo} onOpen={abrirLista} />)}</div>
              </div>
            )}
            {(modulo === 'outbound' || gruposMarca.length > 0) && <div style={{ fontSize: 12, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-muted)' }}>{modulo === 'inbound' ? 'Campanhas Google Search' : 'Campanhas'}</div>}
            {gruposMarca.map(([marcaNome, camps]) => (
              <div key={marcaNome}>
                <div style={{ fontSize: 12, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 8 }}>{marcaNome}</div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 12 }}>{camps.map(c => <LeadsCard key={c.id} c={c} catalogo={data.catalogo} onOpen={abrirLista} />)}</div>
              </div>
            ))}
            {modulo === 'outbound' && gruposMarca.length === 0 && <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 28, fontSize: 13, color: 'var(--text-muted)' }}>Nenhuma campanha neste período.</div>}
          </>
        )}

        {nav.lista && !nav.pessoa && modulo === 'outbound' && nav.vista === 'funil' && (() => {
          const contagem = {
            qualificadas: abertoRows.filter(l => l.estado_funil === 'qualificada').length,
            oportunidades: abertoRows.filter(l => l.estado_funil === 'oportunidade').length,
            vendas: abertoRows.filter(l => l.estado_funil === 'venda').length,
          };
          const escolher = (id) => { setFiltroVista(id); setPage(0); };
          const etapa = filtroVista === 'all' ? '' : filtroVista;
          const grupos = etapa ? abertoRows.filter(l => etapa === 'leads' ? (l.estado_funil || 'lead') === 'lead' : l.estado_funil === etapa) : [];
          return (
            <>
              <LeadsKpis funil={{ geradas: abertoRows.length, qualificadas: contagem.qualificadas, oportunidades: contagem.oportunidades, vendas: contagem.vendas }} active={filtroVista} onPick={escolher} />
              <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Oportunidade e venda são negócios do Gestor abertos depois desta entrada. Escolhe uma etapa para ver as pessoas.</div>
              {etapa && grupos.length > 0 && <LeadsFunilLista rows={grupos} onOpen={abrirPessoa} />}
              {etapa && grupos.length === 0 && <div style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 10, padding: 28, color: 'var(--text-muted)', fontSize: 12 }}>Nenhuma pessoa nesta etapa.</div>}
            </>
          );
        })()}
        {nav.lista && !nav.pessoa && modulo === 'outbound' && nav.vista === 'crm' && (() => {
          const escolher = (id) => { setFiltroVista(id); setPage(0); };
          const grupos = abertoRows.filter(l => {
            if (filtroVista === 'all') return true;
            if (filtroVista === 'na_bd') return l.crm_nivel === 'forte' || l.crm_nivel === 'confirmado';
            if (filtroVista === 'possivel') return l.crm_nivel === 'possivel';
            if (filtroVista === 'ambiguo') return l.crm_nivel === 'ambiguo';
            if (filtroVista === 'sem_match') return !l.crm_nivel || l.crm_nivel === 'sem_match';
            if (filtroVista === 'abertas') return (l.gestor?.abertas || 0) > 0;
            if (filtroVista === 'ganhas') return (l.gestor?.ganhas || 0) > 0;
            return true;
          });
          const vistaRows = leadsOrdenar(grupos, sort);
          return (
            <>
              <LeadsGrupoCards active={filtroVista} onPick={escolher} items={[
                { id: 'na_bd', label: 'Na BD', value: abertoRows.filter(l => l.crm_nivel === 'forte' || l.crm_nivel === 'confirmado').length, accent: '#15803d' },
                { id: 'possivel', label: 'Possíveis', value: abertoRows.filter(l => l.crm_nivel === 'possivel').length, accent: '#b45309' },
                { id: 'ambiguo', label: 'Ambíguos', value: abertoRows.filter(l => l.crm_nivel === 'ambiguo').length, accent: '#b45309' },
                { id: 'sem_match', label: 'Não está na BD', value: abertoRows.filter(l => !l.crm_nivel || l.crm_nivel === 'sem_match').length, accent: '#64748b' },
                { id: 'abertas', label: 'Abertas no Gestor', value: abertoRows.filter(l => (l.gestor?.abertas || 0) > 0).length, accent: '#d97706' },
                { id: 'ganhas', label: 'Ganhas no Gestor', value: abertoRows.filter(l => (l.gestor?.ganhas || 0) > 0).length, accent: '#15803d' },
              ]} />
              <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Leitura do Gestor. Abertas e ganhas incluem o histórico anterior a esta campanha.</div>
              <LeadsCrmTabela rows={vistaRows} onOpen={abrirPessoa} sort={sort} onSort={(key) => setSort(s => ({ key, dir: s.key === key && s.dir === 'desc' ? 'asc' : 'desc' }))} />
            </>
          );
        })()}
        {nav.lista && !nav.pessoa && (modulo !== 'outbound' || !nav.vista || nav.vista === 'pessoas') && (
          <>
            {modulo !== 'outbound' && <LeadsKpis funil={{ geradas: linhasLista.length, qualificadas: linhasLista.filter(l => l.estado_funil === 'qualificada').length, oportunidades: linhasLista.filter(l => l.estado_funil === 'oportunidade').length, vendas: linhasLista.filter(l => l.estado_funil === 'venda').length }} active={filtroEstado === 'lead' ? 'leads' : filtroEstado} onPick={(id) => { setPage(0); setFiltroEstado(id === 'all' ? 'all' : id === 'leads' ? 'lead' : id); }} />}
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
              <input value={qLista} onChange={e => { setQLista(e.target.value); setPage(0); }} placeholder="Pesquisar pessoa" style={{ border: '1px solid var(--border)', borderRadius: 6, padding: '6px 8px', fontSize: 12, background: '#fff' }} />
              {drop('Estado', filtroEstado, v => { setFiltroEstado(v); setPage(0); }, [{ value: 'all', label: 'Todos' }, { value: 'lead', label: 'Lead' }, { value: 'qualificada', label: 'Qualificada' }, { value: 'oportunidade', label: 'Oportunidade' }, { value: 'venda', label: 'Venda' }])}
              {drop('Score', filtroScore, setFiltroScore, [{ value: 'all', label: 'Todos' }, { value: 'alto', label: '70 ou mais' }, { value: 'medio', label: '50–69' }, { value: 'baixo', label: 'Menos de 50' }, { value: 'sem', label: 'Sem score' }])}
              {drop('CRM', filtroCrm, setFiltroCrm, [{ value: 'all', label: 'Todos' }, { value: 'na_bd', label: 'Na BD' }, { value: 'possivel', label: 'Possível' }, { value: 'ambiguo', label: 'Ambíguo' }, { value: 'sem_match', label: 'Não está na BD' }])}
              {drop('Iniciado por', filtroIniciado, v => { setFiltroIniciado(v); setPage(0); }, [{ value: 'all', label: 'Todos' }, { value: 'Lead', label: 'Lead' }, { value: 'Digidelta', label: 'Digidelta' }])}
              {modulo === 'inbound' && campanhaAberta?.tipo !== 'tema' && temasLista.length > 0 && drop('Tema', filtroTema, v => { setFiltroTema(v); setPage(0); }, [{ value: 'all', label: 'Todos' }, ...temasLista.map(t => ({ value: t, label: leadsTemaLabel(temasCatalogo, t) }))])}
              {(campanhaAberta?.tipo === 'site' || campanhaAberta?.tipo === 'tema') && formsLista.length > 1 && drop('Formulário', filtroForm, v => { setFiltroForm(v); setPage(0); }, [{ value: 'all', label: 'Todos' }, ...formsLista.map(f => ({ value: f, label: f }))])}
              {campanhaAberta?.tipo !== 'site' && campanhaAberta?.tipo !== 'tema' && drop('Canal', filtroCanal, setFiltroCanal, [{ value: 'all', label: 'Todos' }, ...[...new Set(abertoRows.map(l => l.canal).filter(Boolean))].map(id => ({ value: id, label: leadsCanalLabel(data?.catalogo, id) }))])}
              {modulo === 'inbound' && drop('Internas', internas, setInternas, [{ value: 'excluir', label: 'Ocultar' }, { value: 'incluir', label: 'Mostrar' }, { value: 'so', label: 'Só internas' }])}
              {modulo === 'inbound' && abertoRows.some(l => l.conversa_digi) && drop('WA Digi', filtroWa, v => { setFiltroWa(v); setPage(0); }, [{ value: 'all', label: 'Todas' }, { value: 'com', label: 'Com conversa' }, { value: 'sem', label: 'Sem conversa' }])}
              {drop('Período', periodo, mudarPeriodo, LEADS_PERIODOS.map(p => ({ value: p.id, label: p.label })))}
              <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{linhasLista.length} pessoas{abertoRows.some(l => l.conversa_digi) ? ` · ${linhasLista.filter(l => l.conversa_digi).length} com conversa Digi` : ''}</span>
            </div>
            <LeadsPessoas rows={pageRows} catalogo={data?.catalogo} temasCatalogo={temasCatalogo} mostrarTema={modulo === 'inbound'} onOpen={abrirPessoa} sort={sort} onSort={(key) => setSort(s => ({ key, dir: s.key === key && s.dir === 'desc' ? 'asc' : 'desc' }))} />
            {linhasLista.length > 50 && (
              <div style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12 }}>
                <button type="button" className="btn" disabled={page === 0} onClick={() => setPage(p => Math.max(0, p - 1))}>Anterior</button>
                <span>{page * 50 + 1}–{Math.min(linhasLista.length, page * 50 + 50)} de {linhasLista.length}</span>
                <button type="button" className="btn" disabled={(page + 1) * 50 >= linhasLista.length} onClick={() => setPage(p => p + 1)}>Seguinte</button>
              </div>
            )}
          </>
        )}

        {nav.pessoa && <LeadsFicha pessoa={pessoa} detalhe={detalhe} tab={nav.tab || 'resumo'} onTab={(id) => setLeadsHash({ tab: id, modulo })} erro={detalheErro} onRetry={() => setDetalheTick(t => t + 1)} onActualizar={async () => {
          const d = await fetch('/api/marketing/crm/leads/pessoa/' + encodeURIComponent(nav.pessoa) + '?' + leadsQs()).then(r => r.json());
          if (d.error) throw new Error(d.error);
          setDetalhe(d);
        }} catalogo={data?.catalogo} temasCatalogo={temasCatalogo} camposLabels={camposLabels} />}
        </div>
      </div>
    </LeadsShell>
  );
}

window.MktLeadsControlScreen = MktLeadsControlScreen;
