/* Setup · Actividade — quem está no marketing e o que fez.
   Leitura em directo, com ruído de aberturas discreto e falhas à vista.
   Expõe window.MktActividadeScreen. */

const ACT_LABEL = {
  inicio: 'Início',
  objectivos: 'Objectivos',
  marcas: 'Marcas e Estratégia',
  'plano-comunicacao': 'Plano de Comunicação',
  briefings: 'Briefings',
  campanhas: 'Campanhas',
  conteudos: 'Produção de Conteúdos',
  publicacao: 'Activação',
  'open-houses': 'Open Houses',
  audiencias: 'Audiências',
  'leads-outbound': 'Outbound',
  'leads-inbound': 'Inbound',
  leads: 'Leads',
  sdr: 'SDR AI',
  'sdr-humano': 'SDR Suporte',
  prospeccao: 'Prospeção',
  resultados: 'Resultados',
  'analise-campanhas': 'Análise de campanhas',
  budget: 'Budget',
  clipping: 'Clipping',
  seo: 'SEO',
  ligacoes: 'Ligações',
  actividade: 'Actividade',
  digi: 'Digi',
  estrategia: 'Estratégia',
  marketing: 'Marketing',
};

const ACT_SINAL = [
  { id: '', key: 'tudo', label: 'Tudo' },
  { id: 'accoes', key: 'accoes', label: 'Acções' },
  { id: 'falhas', key: 'falhas', label: 'Falhas' },
  { id: 'aberturas', key: 'aberturas', label: 'Aberturas' },
];

function actLabel(modulo) {
  const key = String(modulo || '');
  return ACT_LABEL[key] || (key ? key : 'Marketing');
}

function actQs(extra) {
  const p = new URLSearchParams(extra || {});
  return p.toString();
}

function actN(n) {
  return new Intl.NumberFormat('pt-PT').format(Number(n) || 0);
}

async function actividadeFetch(url, signal) {
  const res = await fetch(url, { credentials: 'same-origin', signal });
  const body = await res.json().catch(() => ({}));
  if (res.status === 401) throw Object.assign(new Error('Sessão em falta.'), { status: 401 });
  if (res.status === 403) throw Object.assign(new Error(body.error || 'Sem acesso à actividade.'), { status: 403 });
  if (!res.ok) throw new Error(body.error || 'Não foi possível ler a actividade.');
  return body;
}

function actHa(iso) {
  const t = new Date(iso).getTime();
  if (!t) return '';
  const s = Math.max(0, Math.round((Date.now() - t) / 1000));
  if (s < 60) return 'agora';
  const m = Math.round(s / 60);
  if (m < 60) return `há ${m} min`;
  const h = Math.round(m / 60);
  if (h < 24) return `há ${h} h`;
  return `há ${Math.round(h / 24)} d`;
}

function actHora(iso) {
  const d = new Date(iso);
  if (Number.isNaN(d.getTime())) return '—';
  const hoje = new Date();
  const time = d.toLocaleTimeString('pt-PT', { hour: '2-digit', minute: '2-digit' });
  if (d.toDateString() === hoje.toDateString()) return time;
  const dia = d.toLocaleDateString('pt-PT', { day: '2-digit', month: '2-digit' });
  return `${dia} ${time}`;
}

function actAbsoluto(iso) {
  const d = new Date(iso);
  if (Number.isNaN(d.getTime())) return '—';
  return d.toLocaleString('pt-PT', {
    day: '2-digit', month: 'short', year: 'numeric',
    hour: '2-digit', minute: '2-digit', second: '2-digit',
  });
}

function actFalhou(ev) {
  return ev?.accao === 'falhou' || Number(ev?.estado) >= 400;
}

function actAgrupar(eventos) {
  const out = [];
  for (const ev of eventos) {
    const prev = out[out.length - 1];
    const igual = prev
      && prev.email === ev.email
      && prev.resumo === ev.resumo
      && prev.modulo === ev.modulo
      && prev.accao === ev.accao
      && (prev.caminho || '') === (ev.caminho || '')
      && (prev.estado ?? null) === (ev.estado ?? null);
    if (igual) prev.vezes += 1;
    else out.push({ ...ev, vezes: 1 });
  }
  return out;
}

const ActSelect = ({ value, onChange, children, ariaLabel }) => (
  <select
    aria-label={ariaLabel}
    value={value}
    onChange={e => onChange(e.target.value)}
    style={{
      height: 34, padding: '0 10px', borderRadius: 8,
      border: '1px solid var(--border)', background: 'var(--bg)',
      color: 'var(--text)', fontSize: 13, fontFamily: 'var(--font-display)',
    }}
  >{children}</select>
);

const ActSeg = ({ value, onChange, options, ariaLabel }) => (
  <div role="group" aria-label={ariaLabel} style={{
    display: 'inline-flex', border: '1px solid var(--border)', borderRadius: 8,
    overflow: 'hidden', background: 'var(--bg)',
  }}>
    {options.map((o, i) => {
      const on = value === o.id;
      const falhas = o.id === 'falhas' && Number(o.count) > 0;
      return (
        <button
          key={o.id || 'tudo'}
          type="button"
          aria-pressed={on}
          onClick={() => onChange(o.id)}
          style={{
            height: 34, padding: '0 12px', border: 0, cursor: 'pointer',
            borderRight: i < options.length - 1 ? '1px solid var(--border)' : 0,
            background: on ? (o.id === 'falhas' ? 'rgba(185,28,28,.10)' : 'var(--bg-elev)') : 'transparent',
            color: on ? (o.id === 'falhas' ? '#B91C1C' : 'var(--text)') : (falhas ? '#B91C1C' : 'var(--text-muted)'),
            fontWeight: on || falhas ? 650 : 500,
            fontSize: 12, fontFamily: 'var(--font-display)', whiteSpace: 'nowrap',
          }}
        >{o.label}{o.count != null ? ` ${actN(o.count)}` : ''}</button>
      );
    })}
  </div>
);

const ActStat = ({ label, value, hint, active, tone, onClick }) => {
  const falha = tone === 'falha';
  const Tag = onClick ? 'button' : 'div';
  return (
    <Tag
      type={onClick ? 'button' : undefined}
      onClick={onClick}
      aria-pressed={onClick ? !!active : undefined}
      style={{
        textAlign: 'left', font: 'inherit', color: 'inherit',
        padding: '12px 14px', borderRadius: 10,
        border: `1px solid ${active ? (falha ? 'rgba(185,28,28,.45)' : '#3859D0') : 'var(--border)'}`,
        background: active ? (falha ? 'rgba(185,28,28,.08)' : 'rgba(56,89,208,.08)') : 'var(--bg-elev)',
        cursor: onClick ? 'pointer' : 'default',
      }}
    >
      <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.06em', color: 'var(--text-dim)' }}>{label}</div>
      <div style={{ marginTop: 4, fontSize: 22, fontWeight: 650, fontFamily: 'var(--font-display)', letterSpacing: '-0.03em', color: falha && Number(value) > 0 ? '#B91C1C' : 'var(--text)' }}>{actN(value)}</div>
      {hint ? <div style={{ marginTop: 2, fontSize: 11, color: 'var(--text-muted)' }}>{hint}</div> : null}
    </Tag>
  );
};

const MktActividadeScreen = () => {
  const [dias, setDias] = React.useState('7');
  const [email, setEmail] = React.useState('');
  const [modulo, setModulo] = React.useState('');
  const [sinal, setSinal] = React.useState('');
  const [limite, setLimite] = React.useState(80);
  const [q, setQ] = React.useState('');
  const [qDeb, setQDeb] = React.useState('');
  const [data, setData] = React.useState(null);
  const [online, setOnline] = React.useState([]);
  const [erro, setErro] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [actualizado, setActualizado] = React.useState(null);
  const [desactualizado, setDesactualizado] = React.useState(false);
  const [aberto, setAberto] = React.useState(null);
  const gen = React.useRef(0);
  const ctrlRef = React.useRef(null);
  const listaRef = React.useRef(null);

  React.useEffect(() => {
    const t = setTimeout(() => setQDeb(q.trim()), 300);
    return () => clearTimeout(t);
  }, [q]);

  const qRef = React.useRef(qDeb);
  if (qRef.current !== qDeb) {
    qRef.current = qDeb;
    if (limite !== 80) setLimite(80);
  }

  const query = React.useMemo(() => {
    const params = { dias, limite: String(limite) };
    if (email) params.email = email;
    if (modulo) params.modulo = modulo;
    if (qDeb) params.q = qDeb;
    if (sinal) params.sinal = sinal;
    return actQs(params);
  }, [dias, email, modulo, qDeb, sinal, limite]);

  const load = React.useCallback((silent) => {
    const my = ++gen.current;
    ctrlRef.current?.abort();
    const ctrl = new AbortController();
    ctrlRef.current = ctrl;
    if (!silent) setLoading(true);
    actividadeFetch('/api/marketing/actividade?' + query, ctrl.signal)
      .then(d => {
        if (my !== gen.current) return;
        setData(d);
        setOnline(d.online || []);
        setErro(null);
        setActualizado(new Date());
        setDesactualizado(false);
      })
      .catch(e => {
        if (e.name === 'AbortError' || my !== gen.current) return;
        if (silent) setDesactualizado(true);
        else setErro(e);
      })
      .finally(() => {
        if (my === gen.current && !silent) setLoading(false);
      });
  }, [query]);

  React.useEffect(() => { load(false); }, [load]);

  React.useEffect(() => {
    if (erro?.status === 401 || erro?.status === 403) return undefined;
    const id = setInterval(() => load(true), 30000);
    return () => clearInterval(id);
  }, [load, erro]);

  React.useEffect(() => () => {
    gen.current += 1;
    ctrlRef.current?.abort();
  }, []);

  const recortar = (fn) => (valor) => {
    setLimite(80);
    setAberto(null);
    fn(valor);
  };

  const sessoes = data?.sessoes || [];
  const pessoasMap = new Map();
  for (const p of data?.pessoas || []) pessoasMap.set(p.email, p.nome || p.email);
  for (const s of sessoes) if (s.email && !pessoasMap.has(s.email)) pessoasMap.set(s.email, s.nome || s.email);
  const pessoas = [...pessoasMap.entries()].map(([mail, nome]) => ({ email: mail, nome })).sort((a, b) => String(a.nome).localeCompare(String(b.nome), 'pt'));
  const contagens = data?.contagens || { tudo: 0, accoes: 0, falhas: 0, aberturas: 0 };
  const modulos = (data?.modulos || []).filter(m => m && m.modulo);
  if (modulo && !modulos.some(m => m.modulo === modulo)) modulos.push({ modulo, n: 0 });
  const eventos = data?.eventos || [];
  const grupos = actAgrupar(eventos);
  const total = data?.total || 0;
  const pessoasAgora = new Set(sessoes.map(s => s.email)).size;
  const pessoaNome = pessoasMap.get(email) || email;
  const bloqueado = erro?.status === 403 || erro?.status === 401;

  const verPessoa = (mail) => {
    recortar(setEmail)(mail);
    listaRef.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  };

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg)', color: 'var(--text)' }}>
      <div style={{ background: 'var(--bg-elev)', borderBottom: '1px solid var(--border)', padding: '20px 40px 16px', flexShrink: 0 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 16, alignItems: 'flex-end', flexWrap: 'wrap' }}>
          <div>
            <div style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', letterSpacing: '0.08em' }}>
              MARKETING · SETUP
            </div>
            <h1 style={{ margin: '6px 0 0', fontSize: 26, fontWeight: 650, fontFamily: 'var(--font-display)', letterSpacing: '-0.02em' }}>
              Actividade
            </h1>
            <p style={{ margin: '6px 0 0', fontSize: 13, color: 'var(--text-muted)', maxWidth: 640 }}>
              Quem está no marketing agora e o que fez. Aberturas de ecrã ficam discretas. Falhas ficam marcadas.
            </p>
          </div>
          <div role="status" style={{ fontSize: 12, color: desactualizado ? '#B45309' : 'var(--text-muted)', textAlign: 'right' }}>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
              <span style={{ width: 8, height: 8, borderRadius: 99, background: desactualizado ? '#B45309' : '#166534' }} />
              {desactualizado ? 'Actualização falhou' : 'Em directo'}
            </span>
            {actualizado ? <div>visto {actHora(actualizado)}</div> : null}
          </div>
        </div>
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '20px 40px 32px' }}>
        {bloqueado ? (
          <div style={{ padding: 18, borderRadius: 10, border: '1px solid var(--border)', background: 'var(--bg-elev)', maxWidth: 520 }}>
            <div style={{ fontWeight: 650, marginBottom: 6 }}>Sem acesso</div>
            <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>{erro.message}</div>
          </div>
        ) : (
          <>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))', gap: 10, marginBottom: 18 }}>
              <ActStat label="NO MÓDULO AGORA" value={online.length} hint={`${actN(pessoasAgora)} com sessão aberta`} />
              <ActStat label="SESSÕES" value={sessoes.length} hint="host de marketing" />
              <ActStat
                label="ACÇÕES"
                value={contagens.accoes}
                hint="sem aberturas de ecrã"
                active={sinal === 'accoes'}
                onClick={() => recortar(setSinal)(sinal === 'accoes' ? '' : 'accoes')}
              />
              <ActStat
                label="FALHAS"
                value={contagens.falhas}
                hint="pedidos que não correram"
                tone="falha"
                active={sinal === 'falhas'}
                onClick={() => recortar(setSinal)(sinal === 'falhas' ? '' : 'falhas')}
              />
            </div>

            <div style={{ marginBottom: 22 }}>
              <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.06em', color: 'var(--text-dim)', marginBottom: 8 }}>
                QUEM ESTÁ AGORA
              </div>
              {sessoes.length === 0 ? (
                <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Não há sessões abertas neste host.</div>
              ) : (
                <div style={{ border: '1px solid var(--border)', borderRadius: 10, overflow: 'auto', background: 'var(--bg-elev)', maxHeight: 280 }}>
                  <div style={{
                    display: 'grid', minWidth: 720,
                    gridTemplateColumns: 'minmax(180px, 1.4fr) 170px 120px minmax(140px, 1fr) 130px',
                    gap: 12, padding: '8px 14px', position: 'sticky', top: 0, zIndex: 1,
                    fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.05em', color: 'var(--text-dim)',
                    borderBottom: '1px solid var(--border)', background: 'var(--bg-elev)',
                  }}>
                    <span>PESSOA</span><span>ÚLTIMA ACTIVIDADE</span><span>EXPIRA</span><span>MÓDULO</span><span>ESTADO</span>
                  </div>
                  {sessoes.map(s => (
                    <button key={s.id} type="button" onClick={() => verPessoa(email === s.email ? '' : s.email)}
                      style={{
                        display: 'grid', width: '100%', minWidth: 720, textAlign: 'left',
                        gridTemplateColumns: 'minmax(180px, 1.4fr) 170px 120px minmax(140px, 1fr) 130px',
                        gap: 12, alignItems: 'center', padding: '10px 14px',
                        border: 'none', borderBottom: '1px solid var(--border)', cursor: 'pointer',
                        boxShadow: email === s.email ? 'inset 3px 0 0 #3859D0' : 'none',
                        background: email === s.email ? 'var(--bg-sunken, #eef1f6)' : 'transparent',
                        color: 'var(--text)', font: 'inherit',
                      }}>
                      <span style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
                        <span style={{ width: 8, height: 8, borderRadius: 99, background: s.no_marketing ? '#166534' : 'var(--border)', flexShrink: 0 }} />
                        <span style={{ minWidth: 0 }}>
                          <span style={{ display: 'block', fontSize: 13, fontWeight: 650, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{s.nome || s.email}</span>
                          <span style={{ display: 'block', fontSize: 11, color: 'var(--text-dim)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{s.email}</span>
                        </span>
                      </span>
                      <span title={actAbsoluto(s.ultima)} style={{ fontSize: 12, color: 'var(--text-muted)' }}>{actHora(s.ultima)} · {actHa(s.ultima)}</span>
                      <span title={actAbsoluto(s.expira)} style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text-muted)' }}>{actHora(s.expira)}</span>
                      <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{s.no_marketing && s.modulo ? actLabel(s.modulo) : '—'}</span>
                      <span style={{ fontSize: 11, fontWeight: 650, color: s.no_marketing ? '#166534' : 'var(--text-muted)' }}>{s.no_marketing ? 'No marketing' : 'Sessão activa'}</span>
                    </button>
                  ))}
                </div>
              )}
            </div>

            <div ref={listaRef} style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center', marginBottom: 10 }}>
              <input
                aria-label="Pesquisar actividade"
                value={q}
                onChange={e => setQ(e.target.value)}
                placeholder="Pesquisar acção, caminho ou pessoa"
                style={{
                  height: 34, minWidth: 220, flex: '1 1 220px', padding: '0 10px', borderRadius: 8,
                  border: '1px solid var(--border)', background: 'var(--bg)',
                  color: 'var(--text)', fontSize: 13,
                }}
              />
              <ActSelect ariaLabel="Pessoa" value={email} onChange={recortar(setEmail)}>
                <option value="">Todas as pessoas</option>
                {pessoas.map(p => (
                  <option key={p.email} value={p.email}>{p.nome || p.email}</option>
                ))}
              </ActSelect>
              <ActSeg
                ariaLabel="Período"
                value={dias}
                onChange={recortar(setDias)}
                options={[
                  { id: '1', label: 'Hoje' },
                  { id: '7', label: '7 dias' },
                  { id: '30', label: '30 dias' },
                ]}
              />
            </div>

            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center', marginBottom: 10 }}>
              <ActSeg
                ariaLabel="Tipo de actividade"
                value={sinal}
                onChange={recortar(setSinal)}
                options={ACT_SINAL.map(s => ({ ...s, count: contagens[s.key] }))}
              />
              {(email || modulo || sinal || qDeb) ? (
                <button type="button" onClick={() => { setEmail(''); setModulo(''); setSinal(''); setQ(''); setQDeb(''); setLimite(80); setAberto(null); }}
                  style={{ height: 34, padding: '0 10px', borderRadius: 8, border: '1px solid var(--border)', background: 'transparent', color: 'var(--text-muted)', fontSize: 12, cursor: 'pointer' }}>
                  Limpar filtros
                </button>
              ) : null}
            </div>

            {modulos.length > 0 ? (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 14 }} role="group" aria-label="Módulos com actividade">
                <button type="button" aria-pressed={!modulo} onClick={() => recortar(setModulo)('')}
                  style={{
                    height: 28, padding: '0 10px', borderRadius: 99, cursor: 'pointer',
                    border: '1px solid var(--border)', fontSize: 12, fontFamily: 'var(--font-display)',
                    background: !modulo ? '#3859D0' : 'var(--bg-elev)',
                    color: !modulo ? '#fff' : 'var(--text)',
                  }}>Todos</button>
                {modulos.map(m => {
                  const on = modulo === m.modulo;
                  return (
                    <button key={m.modulo} type="button" aria-pressed={on} onClick={() => recortar(setModulo)(on ? '' : m.modulo)}
                      style={{
                        height: 28, padding: '0 10px', borderRadius: 99, cursor: 'pointer',
                        border: '1px solid var(--border)', fontSize: 12, fontFamily: 'var(--font-display)',
                        background: on ? '#3859D0' : 'var(--bg-elev)',
                        color: on ? '#fff' : 'var(--text)',
                      }}>
                      {actLabel(m.modulo)} <span style={{ opacity: 0.75 }}>{actN(m.n)}</span>
                    </button>
                  );
                })}
              </div>
            ) : null}

            {email ? (
              <div style={{ fontSize: 13, marginBottom: 10, color: 'var(--text-muted)' }}>
                A ver a actividade de <strong style={{ color: 'var(--text)' }}>{pessoaNome}</strong>
              </div>
            ) : null}

            {desactualizado && data ? (
              <div role="status" style={{ fontSize: 13, color: '#B45309', marginBottom: 12 }}>
                A última actualização falhou. A mostrar os dados das {actHora(actualizado)}.
              </div>
            ) : null}

            {erro && !erro.status ? (
              <div role="alert" style={{ fontSize: 13, color: '#B91C1C', marginBottom: 12 }}>{erro.message}</div>
            ) : loading && !data ? (
              <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>A carregar…</div>
            ) : grupos.length === 0 ? (
              <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>
                {email || modulo || sinal || qDeb ? 'Nada neste recorte. Limpa um filtro ou alarga o período.' : 'Sem actividade neste período.'}
              </div>
            ) : (
              <div style={{ border: '1px solid var(--border)', borderRadius: 10, overflow: 'auto', background: 'var(--bg-elev)', opacity: loading ? 0.72 : 1 }}>
                {grupos.map(ev => {
                  const falhou = actFalhou(ev);
                  const abriu = ev.accao === 'abriu';
                  const open = aberto === ev.id;
                  return (
                    <div key={ev.id} style={{ borderBottom: '1px solid var(--border)', background: falhou ? 'rgba(185,28,28,.06)' : 'transparent', boxShadow: falhou ? 'inset 3px 0 0 #B91C1C' : 'none' }}>
                      <button
                        type="button"
                        aria-expanded={open}
                        onClick={() => setAberto(open ? null : ev.id)}
                        style={{
                          display: 'grid', width: '100%', minWidth: 640, textAlign: 'left', font: 'inherit', color: 'inherit', cursor: 'pointer',
                          gridTemplateColumns: '88px minmax(140px, 200px) minmax(180px, 1fr) auto',
                          gap: 12, alignItems: 'center', padding: '12px 14px',
                          border: 0, background: 'transparent',
                        }}
                      >
                        <span title={actAbsoluto(ev.created_at)} style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text-muted)' }}>{actHora(ev.created_at)}</span>
                        <span style={{ minWidth: 0 }}>
                          <span style={{ display: 'block', fontSize: 13, fontWeight: 650, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{ev.nome || ev.email}</span>
                        </span>
                        <span style={{ minWidth: 0 }}>
                          <span style={{ display: 'block', fontSize: 13, color: abriu ? 'var(--text-dim)' : 'var(--text)', fontWeight: abriu ? 450 : 550 }}>
                            {ev.resumo}
                            {ev.vezes > 1 ? <span style={{ marginLeft: 8, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-muted)' }}>×{ev.vezes}</span> : null}
                            {falhou ? <span style={{ marginLeft: 8, fontSize: 10, fontWeight: 700, fontFamily: 'var(--font-mono)', letterSpacing: '0.04em', color: '#B91C1C' }}>FALHOU</span> : null}
                          </span>
                          {ev.caminho ? (
                            <span style={{ display: 'block', marginTop: 2, fontFamily: 'var(--font-mono)', fontSize: 11, color: falhou ? '#B91C1C' : 'var(--text-dim)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                              {ev.metodo ? `${ev.metodo} ` : ''}{ev.caminho}{Number(ev.estado) >= 400 ? ` · ${ev.estado}` : ''}
                            </span>
                          ) : null}
                        </span>
                        <span style={{ fontSize: 12, color: 'var(--text-muted)', textAlign: 'right' }}>{actLabel(ev.modulo)}</span>
                      </button>
                      {open ? (
                        <div style={{ padding: '0 14px 12px 114px', fontSize: 12, color: 'var(--text-muted)' }}>
                          <div>{actAbsoluto(ev.created_at)}{ev.vezes > 1 ? ` · ${ev.vezes} eventos iguais seguidos` : ''}</div>
                          {ev.caminho ? (
                            <div style={{ marginTop: 4, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-dim)', wordBreak: 'break-all' }}>
                              {ev.metodo ? `${ev.metodo} ` : ''}{ev.caminho}{ev.estado ? ` · ${ev.estado}` : ''}
                            </div>
                          ) : null}
                          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 8 }}>
                            <button type="button" onClick={() => verPessoa(ev.email)}
                              style={{ height: 28, padding: '0 10px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--bg)', color: 'var(--text)', fontSize: 12, cursor: 'pointer' }}>
                              Ver só {ev.nome || ev.email}
                            </button>
                            {ev.modulo ? (
                              <button type="button" onClick={() => recortar(setModulo)(ev.modulo)}
                                style={{ height: 28, padding: '0 10px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--bg)', color: 'var(--text)', fontSize: 12, cursor: 'pointer' }}>
                                Ver só {actLabel(ev.modulo)}
                              </button>
                            ) : null}
                          </div>
                        </div>
                      ) : null}
                    </div>
                  );
                })}
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, justifyContent: 'space-between', alignItems: 'center', padding: '10px 14px', fontSize: 12, color: 'var(--text-muted)' }}>
                  <span>{actN(eventos.length)} de {actN(total)} eventos{grupos.length < eventos.length ? ` · ${actN(grupos.length)} linhas` : ''}</span>
                  {eventos.length < total && limite < 500 ? (
                    <button type="button" onClick={() => setLimite(n => Math.min(500, n + 80))} disabled={loading}
                      style={{ height: 30, padding: '0 12px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--bg)', color: 'var(--text)', fontSize: 12, cursor: loading ? 'default' : 'pointer' }}>
                      {loading ? 'A carregar…' : 'Mostrar mais'}
                    </button>
                  ) : null}
                  {limite >= 500 && total > eventos.length ? (
                    <span>As 500 mais recentes. Aperta o período ou a pesquisa para o resto.</span>
                  ) : null}
                </div>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
};

window.MktActividadeScreen = MktActividadeScreen;
