/* screen_marketing_activacao_setup.jsx
   Activação — consola de setup-para-publicar (padrão Briefings).
   Carregado DEPOIS de screen_marketing_activacao.jsx e redefine window.MktActivacaoScreen.
*/

const ACT_CHANNELS = [
  { id: 'meta_ads',          label: 'Meta Ads',          short: 'META' },
  { id: 'linkedin_ads',      label: 'LinkedIn Ads',      short: 'LIN' },
  { id: 'google_ads_search', label: 'Google Search',     short: 'GGL' },
  { id: 'google_ads_display',label: 'Google Display',    short: 'DISP' },
  { id: 'email',             label: 'Email',             short: 'EML' },
  { id: 'whatsapp',          label: 'WhatsApp',          short: 'WA' },
  { id: 'website',           label: 'Website',           short: 'WEB' },
  { id: 'muppi_led',         label: 'Painéis LED',       short: 'LED' },
];

const ACT_ESTADO = {
  previsto:    { label: 'PREVISTO',    color: '#6b7fa3', bg: 'rgba(107,127,163,0.12)' },
  a_produzir:  { label: 'A PRODUZIR',  color: '#F59E0B', bg: 'rgba(245,158,11,0.12)' },
  setup:       { label: 'SETUP',       color: '#3859D0', bg: 'rgba(56,89,208,0.12)' },
  agendado:    { label: 'AGENDADO',    color: '#3859D0', bg: 'rgba(56,89,208,0.12)' },
  publicado:   { label: 'PUBLICADO',   color: '#10B981', bg: 'rgba(16,185,129,0.12)' },
  falhou:      { label: 'FALHOU',      color: '#EF4444', bg: 'rgba(239,68,68,0.12)' },
};

const ACT_SEND = new Set(['email', 'whatsapp']);
const ACT_BRAND_ORDER = ['mimaki', 'biond', 'decal', 'alldecor', 'sensek', 'netscreen', 'digidelta'];
const ACT_BRAND_NAMES = { mimaki: 'Mimaki', biond: 'BIOND', decal: 'Decal', alldecor: 'AllDecor', sensek: 'Sensek', netscreen: 'NetScreen', digidelta: 'Digidelta' };
const ACT_BRAND_COLORS = { mimaki: '#0066CC', biond: '#E8A000', decal: '#00A86B', alldecor: '#7C3AED', sensek: '#DC2626', netscreen: '#0EA5E9', digidelta: '#3859D0' };

const actThSt = {
  textAlign: 'left', padding: '8px 12px',
  fontSize: 10, fontFamily: 'var(--font-display)', fontWeight: 600,
  letterSpacing: '0.10em', textTransform: 'uppercase',
  color: 'var(--text-muted)', whiteSpace: 'nowrap',
};

function actGetUser() {
  const params = new URLSearchParams(window.location.search);
  if (params.get('dev') === 'costa') {
    return { email: 'fabio.costa@digidelta.pt', nome_apresentar: 'Fábio Costa' };
  }
  return window.currentUser || { email: 'fabio.costa@digidelta.pt', nome_apresentar: 'Fábio Costa' };
}

function actParseHash() {
  const h = window.location.hash.replace(/^#/, '');
  const params = new URLSearchParams(h);
  return { camp: params.get('camp') || null };
}

function actSetCamp(campId) {
  const params = new URLSearchParams(window.location.hash.replace(/^#/, ''));
  params.set('screen', 'marketing');
  if (campId) params.set('camp', campId);
  else params.delete('camp');
  window.location.hash = params.toString();
}

function actFmtDate(iso) {
  if (!iso) return '—';
  const d = new Date(iso);
  if (isNaN(d)) return String(iso).slice(0, 10);
  return d.toLocaleDateString('pt-PT', { day: '2-digit', month: 'short', year: 'numeric' });
}

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

function actToLocalInput(iso) {
  if (!iso) return '';
  const d = new Date(iso);
  if (isNaN(d)) return '';
  const pad = (n) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

function actEstadoBadge(estado, canal) {
  if (!estado) return <span style={{ color: 'var(--text-dim)', fontSize: 12 }}>—</span>;
  const cfg = ACT_ESTADO[estado] || ACT_ESTADO.previsto;
  let label = cfg.label;
  if (estado === 'publicado' && ACT_SEND.has(canal)) label = 'ENVIADO';
  return (
    <span style={{
      fontSize: 10, fontFamily: 'var(--font-mono)', fontWeight: 600,
      padding: '2px 7px', borderRadius: 4, display: 'inline-block',
      color: cfg.color, background: cfg.bg, letterSpacing: '0.04em', whiteSpace: 'nowrap',
    }}>{label}</span>
  );
}

const ActDropdown = ({ label, value, options, onChange }) => {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onClick = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onClick);
    return () => document.removeEventListener('mousedown', onClick);
  }, [open]);
  const current = options.find(o => o.value === value) || options[0];
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button onClick={() => setOpen(v => !v)} style={{
        background: 'var(--bg-elev, #ffffff)', color: 'var(--text, #112954)',
        border: '1px solid var(--border, #dde3ef)', borderRadius: 6,
        padding: '6px 10px', fontSize: 11.5,
        display: 'inline-flex', alignItems: 'center', gap: 8,
        cursor: 'pointer', fontFamily: 'inherit',
      }}>
        <span style={{ color: 'var(--text-dim, #475569)', fontSize: 10, textTransform: 'uppercase', letterSpacing: '.06em', fontFamily: 'var(--font-mono, monospace)' }}>{label}</span>
        <span style={{ fontWeight: 500 }}>{current?.label || '—'}</span>
        <span style={{ color: 'var(--text-muted, #64748b)', fontSize: 9 }}>▾</span>
      </button>
      {open && (
        <div className="animate-in" style={{
          position: 'absolute', top: 'calc(100% + 4px)', left: 0, zIndex: 50,
          background: 'var(--bg-elev, #ffffff)', border: '1px solid var(--border, #dde3ef)', borderRadius: 6,
          boxShadow: '0 8px 24px rgba(17,41,84,0.12)', minWidth: 180, padding: 4, maxHeight: 280, overflowY: 'auto',
        }}>
          {options.map(o => (
            <button key={o.value} onClick={() => { onChange(o.value); setOpen(false); }} style={{
              display: 'block', width: '100%', textAlign: 'left',
              background: o.value === value ? 'color-mix(in oklch, var(--ai-500, #3859D0) 12%, transparent)' : 'transparent',
              color: o.value === value ? 'var(--ai-500, #3859D0)' : 'var(--text, #112954)',
              border: 'none', padding: '7px 10px', borderRadius: 4,
              fontSize: 12, fontWeight: o.value === value ? 600 : 500,
              cursor: 'pointer', fontFamily: 'inherit',
            }}>{o.label}</button>
          ))}
        </div>
      )}
    </div>
  );
};

const ActSortHeader = ({ label, sortKey, sortBy, onSort, style: extra }) => {
  const active = sortBy.key === sortKey;
  return (
    <th style={{ ...actThSt, cursor: sortKey ? 'pointer' : 'default', userSelect: 'none', ...extra }}
      onClick={() => sortKey && onSort(sortKey)}>
      <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
        {label}
        {active && sortKey && window.Icon &&
          <window.Icon name={sortBy.dir === 'asc' ? 'arrowUp' : 'arrowDown'} size={9} style={{ color: 'var(--ai-500)' }} />}
      </span>
    </th>
  );
};

async function actFetch(url, opts) {
  const res = await fetch(url, { headers: { 'Content-Type': 'application/json' }, ...opts });
  if (!res.ok) {
    let b = {};
    try { b = await res.json(); } catch {}
    throw new Error(b.error || `HTTP ${res.status}`);
  }
  return res.json();
}

const ActBanner = ({ kpis, campanhas, userName }) => {
  const first = (userName || '').split(' ')[0] || 'Olá';
  const pl = (n, s, p) => n === 1 ? s : p;
  let heading = `${first}, pipeline de activação.`;
  let body = 'As campanhas com setup e planeamento aparecem aqui. Produção preenche o conteúdo quando estiver pronta.';
  if (kpis.falhas > 0) {
    heading = `${first}, ${kpis.falhas} ${pl(kpis.falhas, 'canal falhou', 'canais falharam')} na publicação.`;
    body = 'Revê as campanhas com falha antes de voltar a activar.';
  } else if (kpis.agendadas > 0) {
    heading = `${first}, ${kpis.agendadas} ${pl(kpis.agendadas, 'campanha está agendada', 'campanhas estão agendadas')}.`;
    body = 'Quando a data e hora do planeamento chegarem, o sistema publica ou envia.';
  } else if (kpis.setup > 0) {
    heading = `${first}, ${kpis.setup} ${pl(kpis.setup, 'campanha tem setup pronto', 'campanhas têm setup pronto')}.`;
    body = 'Abre a campanha, confirma Meta Ads, email e datas, e activa quando as peças existirem.';
  } else if (kpis.a_produzir > 0) {
    heading = `${first}, ${kpis.a_produzir} ${pl(kpis.a_produzir, 'campanha espera produção', 'campanhas esperam produção')}.`;
    body = 'O setup e as datas já estão. O conteúdo chega de Produção — até lá o botão Activar fica desligado.';
  } else if (kpis.total === 0) {
    heading = `${first}, ainda não há campanhas para activar.`;
    body = 'Aprova o setup numa campanha para ela aparecer nesta tabela.';
  }
  return (
    <div style={{ flexShrink: 0, padding: '10px 0 0' }}>
      <div style={{ fontSize: 22, fontWeight: 700, color: 'var(--text)', fontFamily: 'var(--font-display)', marginBottom: 6, letterSpacing: '-0.02em' }}>{heading}</div>
      <div style={{ fontSize: 13, color: 'var(--text-muted)', lineHeight: 1.75 }}>{body}</div>
    </div>
  );
};

const ActLista = ({ campanhas, isAll, onOpen, filterEstado }) => {
  const [sortBy, setSortBy] = React.useState({ key: 'updated_at', dir: 'desc' });
  const onSort = (key) => setSortBy(s => ({ key, dir: s.key === key && s.dir === 'asc' ? 'desc' : 'asc' }));

  const rows = React.useMemo(() => {
    const arr = Array.isArray(campanhas) ? campanhas : [];
    const filtered = filterEstado === 'all'
      ? arr
      : arr.filter(c => Object.values(c.canais || {}).some(x => x.estado === filterEstado));
    return filtered.slice().sort((a, b) => {
      const av = a[sortBy.key] ?? '';
      const bv = b[sortBy.key] ?? '';
      if (av < bv) return sortBy.dir === 'asc' ? -1 : 1;
      if (av > bv) return sortBy.dir === 'asc' ? 1 : -1;
      return 0;
    });
  }, [campanhas, sortBy, filterEstado]);

  if (campanhas === null) {
    return (
      <div>
        {[1, 2, 3, 4].map(i => (
          <div key={i} style={{ height: 44, borderRadius: 6, background: 'var(--bg-sunken, #eef1f6)', marginBottom: 6, opacity: 1 - i * 0.2 }} />
        ))}
      </div>
    );
  }
  if (!rows.length) {
    return (
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 8, color: 'var(--text-muted)', marginTop: 18 }}>
        <div style={{ fontSize: 14 }}>Sem campanhas para os filtros actuais.</div>
      </div>
    );
  }

  return (
    <div style={{ paddingBottom: 48 }}>
      <div style={{ overflowX: 'auto', width: '100%' }}>
        <table style={{ width: isAll ? 1680 : 1540, tableLayout: 'fixed', borderCollapse: 'collapse', fontSize: 12.5, fontFamily: 'var(--font-sans)' }}>
          <colgroup>
            <col style={{ width: 280 }} />
            {isAll && <col style={{ width: 140 }} />}
            {ACT_CHANNELS.map(ch => <col key={ch.id} style={{ width: 118 }} />)}
            <col style={{ width: 120 }} />
          </colgroup>
          <thead style={{ position: 'sticky', top: 0, zIndex: 2, background: 'var(--bg-elev)' }}>
            <tr style={{ borderBottom: '1px solid var(--border)' }}>
              <ActSortHeader label="Campanha" sortKey="titulo" sortBy={sortBy} onSort={onSort} />
              {isAll && <ActSortHeader label="Marca" sortKey="marca_slug" sortBy={sortBy} onSort={onSort} />}
              {ACT_CHANNELS.map(ch => (
                <th key={ch.id} style={{ ...actThSt, textAlign: 'center' }}>{ch.short}</th>
              ))}
              <ActSortHeader label="Actualizado" sortKey="updated_at" sortBy={sortBy} onSort={onSort} />
            </tr>
          </thead>
          <tbody>
            {rows.map((c, i) => {
              const bc = c.brand_color || ACT_BRAND_COLORS[c.marca_slug] || '#3859D0';
              return (
                <tr key={c.id} onClick={() => onOpen(c.id)}
                  style={{
                    cursor: 'pointer', borderBottom: '1px solid var(--border)',
                    transition: 'background 150ms ease',
                    animation: 'slide-up 0.2s ease-out both',
                    animationDelay: `${Math.min(i, 9) * 25}ms`,
                  }}
                  onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-hover, #f1f5f9)'}
                  onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
                >
                  <td style={{ padding: '10px 12px', overflow: 'hidden' }}>
                    <div style={{ fontWeight: 500, color: 'var(--text)', fontSize: 13, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                      {c.titulo || 'Sem título'}
                    </div>
                  </td>
                  {isAll && (
                    <td style={{ padding: '10px 12px', overflow: 'hidden' }}>
                      <span style={{ fontSize: 11, fontFamily: 'var(--font-display)', fontWeight: 700, letterSpacing: '0.06em', color: bc }}>
                        {(c.brand_name || c.marca_slug || '').toUpperCase()}
                      </span>
                    </td>
                  )}
                  {ACT_CHANNELS.map(ch => {
                    const cell = c.canais?.[ch.id];
                    return (
                      <td key={ch.id} style={{ padding: '10px 8px', textAlign: 'center' }}>
                        {actEstadoBadge(cell?.estado, ch.id)}
                      </td>
                    );
                  })}
                  <td style={{ padding: '10px 12px', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-muted)' }}>
                    {actFmtDate(c.updated_at)}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
};

const ActEmailTeste = ({ campId, pecaId, userEmail, disabled }) => {
  const [open, setOpen] = React.useState(false);
  const [pessoas, setPessoas] = React.useState([]);
  const [empresa, setEmpresa] = React.useState('all');
  const [depto, setDepto] = React.useState('all');
  const [q, setQ] = React.useState('');
  const [sel, setSel] = React.useState(() => new Set(userEmail ? [String(userEmail).toLowerCase()] : []));
  const [busy, setBusy] = React.useState(false);
  const [msg, setMsg] = React.useState(null);
  const box = React.useRef(null);

  React.useEffect(() => {
    if (!open) return;
    actFetch('/api/marketing/activacao/destinatarios-teste')
      .then(d => setPessoas(d.pessoas || []))
      .catch(e => setMsg(e.message));
  }, [open]);

  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (box.current && !box.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);

  const empresas = React.useMemo(() => [...new Set(pessoas.map(p => p.empresa))].sort(), [pessoas]);
  const deptos = React.useMemo(() => {
    const src = empresa === 'all' ? pessoas : pessoas.filter(p => p.empresa === empresa);
    return [...new Set(src.map(p => p.departamento))].sort();
  }, [pessoas, empresa]);

  const filtered = pessoas.filter(p => {
    if (empresa !== 'all' && p.empresa !== empresa) return false;
    if (depto !== 'all' && p.departamento !== depto) return false;
    if (q) {
      const s = (p.nome + ' ' + p.email).toLowerCase();
      if (!s.includes(q.toLowerCase())) return false;
    }
    return true;
  });

  const toggle = (email) => {
    setSel(prev => {
      const next = new Set(prev);
      if (next.has(email)) next.delete(email);
      else if (next.size >= 10) return prev;
      else next.add(email);
      return next;
    });
  };

  const enviar = async () => {
    if (!sel.size) return;
    setBusy(true); setMsg(null);
    try {
      const r = await actFetch('/api/marketing/activacao/email/teste', {
        method: 'POST',
        body: JSON.stringify({ campanha_id: campId, peca_id: pecaId, emails: [...sel] }),
      });
      setMsg(`Enviado para ${r.sent} destinatário${r.sent === 1 ? '' : 's'}.`);
    } catch (e) { setMsg(e.message); }
    finally { setBusy(false); }
  };

  const selStyle = { fontSize: 12, padding: '5px 8px', border: '1px solid var(--border)', borderRadius: 6, background: 'var(--bg)', color: 'var(--text)', fontFamily: 'inherit', width: '100%' };

  return (
    <div ref={box} style={{ position: 'relative' }}>
      <button
        className="btn"
        style={{ height: 30, padding: '0 12px', fontSize: 12, opacity: disabled ? 0.45 : 1 }}
        disabled={disabled}
        onClick={() => setOpen(v => !v)}
      >
        Enviar teste
      </button>
      {open && (
        <div style={{
          position: 'absolute', right: 0, top: 'calc(100% + 6px)', zIndex: 40,
          width: 360, background: '#fff', border: '1px solid var(--border)',
          borderRadius: 8, boxShadow: '0 12px 32px rgba(17,41,84,0.14)', padding: 12,
        }}>
          <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 8 }}>
            Teste interno · máx. 10
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6, marginBottom: 6 }}>
            <select value={empresa} onChange={e => { setEmpresa(e.target.value); setDepto('all'); }} style={selStyle}>
              <option value="all">Todas as empresas</option>
              {empresas.map(x => <option key={x} value={x}>{x}</option>)}
            </select>
            <select value={depto} onChange={e => setDepto(e.target.value)} style={selStyle}>
              <option value="all">Todos os departamentos</option>
              {deptos.map(x => <option key={x} value={x}>{x}</option>)}
            </select>
          </div>
          <input
            value={q} onChange={e => setQ(e.target.value)} placeholder="Procurar nome ou email…"
            style={{ ...selStyle, marginBottom: 8 }}
          />
          <div style={{ maxHeight: 220, overflowY: 'auto', border: '1px solid var(--border)', borderRadius: 6 }}>
            {filtered.length === 0 && (
              <div style={{ padding: 10, fontSize: 12, color: 'var(--text-muted)' }}>Sem resultados.</div>
            )}
            {filtered.map(p => {
              const on = sel.has(p.email);
              return (
                <label key={p.email} style={{
                  display: 'flex', gap: 8, alignItems: 'flex-start', padding: '7px 8px',
                  borderBottom: '1px solid var(--border)', cursor: 'pointer',
                  background: on ? 'rgba(56,89,208,0.06)' : 'transparent',
                }}>
                  <input type="checkbox" checked={on} onChange={() => toggle(p.email)} style={{ marginTop: 2 }} />
                  <span style={{ minWidth: 0 }}>
                    <span style={{ display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text)' }}>{p.nome}</span>
                    <span style={{ display: 'block', fontSize: 10, color: 'var(--text-muted)' }}>{p.email} · {p.empresa} · {p.departamento}</span>
                  </span>
                </label>
              );
            })}
          </div>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 10, gap: 8 }}>
            <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>{sel.size}/10 seleccionados</span>
            <button
              className="btn btn-ai"
              style={{ height: 28, padding: '0 12px', fontSize: 12, opacity: sel.size && !busy ? 1 : 0.45 }}
              disabled={!sel.size || busy}
              onClick={enviar}
            >
              {busy ? 'A enviar…' : `Enviar teste (${sel.size})`}
            </button>
          </div>
          {msg && <div style={{ marginTop: 8, fontSize: 12, color: /Enviado/.test(msg) ? '#166534' : '#b91c1c' }}>{msg}</div>}
        </div>
      )}
    </div>
  );
};

const ActCanalCard = ({ canal, onActivar, busy, campId, user }) => {
  const meta = ACT_CHANNELS.find(c => c.id === canal.canal) || { label: canal.canal, id: canal.canal };
  const s = canal.setup || {};
  const pecas = canal.pecas || [];
  const isEmail = canal.canal === 'email';
  const isAds = ['meta_ads', 'linkedin_ads', 'google_ads_search', 'google_ads_display'].includes(canal.canal);
  const pecaAgendada = pecas.find(p => p.scheduled_for)?.scheduled_for;
  const [whenLocal, setWhenLocal] = React.useState(() => actToLocalInput(pecaAgendada || canal.suggested_at));
  React.useEffect(() => {
    setWhenLocal(actToLocalInput(pecaAgendada || canal.suggested_at));
  }, [pecaAgendada, canal.suggested_at]);
  const whenDate = whenLocal ? new Date(whenLocal) : null;
  const whenPast = !!(whenDate && !isNaN(whenDate.getTime()) && whenDate.getTime() <= Date.now());

  const kv = (k, v) => (
    <div style={{ display: 'contents' }}>
      <div style={{ color: 'var(--text-muted)', fontSize: 12 }}>{k}</div>
      <div style={{ color: 'var(--text)', fontSize: 12 }}>{v || '—'}</div>
    </div>
  );

  return (
    <div style={{ background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 8, padding: 20, marginBottom: 16 }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, marginBottom: 14 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 15, fontWeight: 700 }}>{meta.label}</div>
          {actEstadoBadge(canal.estado, canal.canal)}
        </div>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
          {isEmail && (
            <ActEmailTeste
              campId={campId}
              pecaId={pecas[0]?.id}
              userEmail={user?.email}
              disabled={!pecas.length || !!busy}
            />
          )}
          <button
            className="btn"
            style={{ height: 30, padding: '0 12px', fontSize: 12, opacity: canal.can_activar ? 1 : 0.45 }}
            disabled={!canal.can_activar || busy}
            onClick={() => onActivar(canal.canal, { send_now: true })}
            title="Publica ou envia daqui a segundos"
          >
            {busy === canal.canal ? 'A activar…' : 'Enviar agora'}
          </button>
          <button
            className="btn btn-ai"
            style={{ height: 30, padding: '0 14px', fontSize: 12, opacity: canal.can_activar && whenLocal && !whenPast ? 1 : 0.45 }}
            disabled={!canal.can_activar || !whenLocal || whenPast || busy}
            onClick={() => onActivar(canal.canal, { scheduled_for: whenDate ? whenDate.toISOString() : null })}
            title={whenPast ? 'A hora já passou — altera ou usa Enviar agora' : 'Armar para esta data e hora (Lisboa)'}
          >
            {busy === canal.canal ? 'A activar…' : 'Activar'}
          </button>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20 }}>
        <div>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.10em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 10 }}>Setup</div>
          <div style={{ display: 'grid', gridTemplateColumns: '140px 1fr', gap: '6px 12px' }}>
            {kv('Janela planeamento', canal.planeamento?.start_date ? `${actFmtDate(canal.planeamento.start_date)}${canal.planeamento.end_date ? ' → ' + actFmtDate(canal.planeamento.end_date) : ''}` : null)}
            <div style={{ color: 'var(--text-muted)', fontSize: 12 }}>Data e hora</div>
            <div>
              <input
                type="datetime-local"
                value={whenLocal}
                onChange={e => setWhenLocal(e.target.value)}
                disabled={!canal.can_activar || !!busy}
                style={{
                  fontSize: 12, fontFamily: 'inherit', color: 'var(--text)',
                  border: `1px solid ${whenPast ? '#EF4444' : 'var(--border)'}`,
                  borderRadius: 6, padding: '5px 8px', background: 'var(--bg)',
                }}
              />
              <div style={{ fontSize: 10, color: whenPast ? '#EF4444' : 'var(--text-muted)', marginTop: 4 }}>
                {whenPast ? 'Já passou — altera a hora ou Enviar agora.' : 'Europe/Lisbon · usado só neste canal'}
              </div>
            </div>
            {isAds && kv('Conta ads', s.conta_ads)}
            {isAds && kv('Budget', s.budget_sugerido?.percentagem_total != null ? `${s.budget_sugerido.percentagem_total}% · ${s.budget_sugerido.racional || ''}` : s.budget_sugerido?.racional)}
            {isAds && kv('Bid', s.bid_strategy)}
            {isAds && kv('Objectivo', s.objectivo_campanha)}
            {isEmail && kv('Remetente / lista', s.lista_brevo || s.conta_publicacao)}
            {isEmail && kv('Horário', s.horario_publicacao)}
            {!isAds && !isEmail && kv('Destino', s.conta_publicacao || s.website_destino)}
            {!isAds && !isEmail && kv('Formato', s.formato_publicacao)}
            {s.horario_publicacao && !isEmail && kv('Horário', s.horario_publicacao)}
          </div>
          {(canal.segmentacao || []).length > 0 && (
            <div style={{ marginTop: 14 }}>
              <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.10em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 8 }}>Segmentação</div>
              {canal.segmentacao.map((sg, i) => (
                <div key={i} style={{ fontSize: 12, color: 'var(--text)', marginBottom: 4 }}>
                  <b>{sg.nome || 'Audiência'}</b>
                  {sg.country ? ` · ${sg.country}` : ''}
                  {sg.audiencia?.audience_size ? ` · ${sg.audiencia.audience_size}` : ''}
                </div>
              ))}
            </div>
          )}
          {(canal.listas || []).length > 0 && (
            <div style={{ marginTop: 10, fontSize: 12, color: 'var(--text-muted)' }}>
              Lista: {canal.listas.map(l => `${l.tipo}${l.contagem != null ? ` (${l.contagem})` : ''}`).join(' · ')}
            </div>
          )}
        </div>

        <div>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.10em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 10 }}>Conteúdo</div>
          {pecas.length === 0 ? (
            <div style={{ fontSize: 13, color: 'var(--text-muted)', padding: '16px 0' }}>À espera de Produção. O setup e a data já estão definidos.</div>
          ) : pecas.map(p => (
            <div key={p.id} style={{ display: 'flex', gap: 12, marginBottom: 12, paddingBottom: 12, borderBottom: '1px solid var(--border)' }}>
              <div style={{ width: 72, height: 72, borderRadius: 6, background: 'var(--bg)', overflow: 'hidden', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                {p.thumb
                  ? <img src={p.thumb} alt="" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} />
                  : <span style={{ fontSize: 10, color: 'var(--text-dim)' }}>sem preview</span>}
              </div>
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginBottom: 4 }}>
                  <span style={{ fontSize: 12, fontWeight: 600 }}>{p.content_type || p.canal_filho || 'peça'}</span>
                  {actEstadoBadge(
                    p.status === 'published' ? 'publicado'
                      : p.status === 'scheduled' ? 'agendado'
                      : p.status === 'failed_publish' ? 'falhou'
                      : p.status === 'approved' || p.status === 'ready_review' || p.status === 'pending_activation' ? 'setup'
                      : 'a_produzir',
                    canal.canal
                  )}
                </div>
                {p.subject && <div style={{ fontSize: 12 }}><b>Assunto:</b> {p.subject}</div>}
                {p.headline && <div style={{ fontSize: 12 }}><b>Headline:</b> {p.headline}</div>}
                {p.cta && <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>CTA: {p.cta}</div>}
                {p.scheduled_for && <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', marginTop: 4 }}>Agendado {actFmtDateTime(p.scheduled_for)}</div>}
                {isEmail && p.html && (
                  <details style={{ marginTop: 6 }}>
                    <summary style={{ fontSize: 11, cursor: 'pointer', color: '#3859D0' }}>Ver HTML do email</summary>
                    <iframe title="email" srcDoc={p.html} style={{ width: '100%', height: 220, border: '1px solid var(--border)', borderRadius: 6, marginTop: 6, background: '#fff' }} />
                  </details>
                )}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

const ActDetalhe = ({ campId, user, onBack }) => {
  const [data, setData] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [busy, setBusy] = React.useState(null);

  const reload = React.useCallback(async () => {
    try {
      setError(null);
      const d = await actFetch(`/api/marketing/activacao/setup/${campId}`);
      setData(d);
    } catch (e) { setError(e.message); }
    finally { setLoading(false); }
  }, [campId]);
  React.useEffect(() => { setLoading(true); reload(); }, [reload]);

  const activar = async (canal, opts = {}) => {
    setBusy(canal || 'all');
    try {
      await actFetch('/api/marketing/activacao/activar', {
        method: 'POST',
        body: JSON.stringify({
          campanha_id: campId,
          canal_pai: canal || undefined,
          actor_email: user.email,
          actor_name: user.nome_apresentar,
          send_now: !!opts.send_now,
          scheduled_for: opts.send_now ? undefined : (opts.scheduled_for || undefined),
        }),
      });
      await reload();
    } catch (e) { alert(e.message); }
    finally { setBusy(null); }
  };

  const camp = data?.campanha;
  const bc = camp?.brand_color || ACT_BRAND_COLORS[camp?.marca_slug] || '#3859D0';

  return (
    <div data-theme="light" style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', '--bg': '#f8fafc', '--bg-elev': '#ffffff', '--bg-hover': '#f1f5f9', '--bg-sunken': '#e8edf5', '--border': '#dde3ef', '--text': '#112954', '--text-muted': '#4a5e7a', '--text-dim': '#6b7fa3', '--ai-500': '#3859D0' }}>
      <div style={{ background: 'var(--bg-elev)', borderBottom: '1px solid var(--border)', padding: '20px 40px 16px', flexShrink: 0 }}>
        <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: '0.07em', color: 'var(--text-muted)', textTransform: 'uppercase', marginBottom: 6, fontFamily: 'var(--font-mono)' }}>
          MARKETING · ACTIVACAO
        </div>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16 }}>
          <div style={{ minWidth: 0 }}>
            <h1 style={{ margin: 0, fontSize: 21, fontWeight: 700, color: 'var(--text)', fontFamily: 'var(--font-display)', letterSpacing: '-0.01em', lineHeight: 1.2 }}>
              {camp?.titulo || (loading ? 'A carregar…' : 'Campanha')}
            </h1>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 8, flexWrap: 'wrap' }}>
              {camp?.status && (
                <span style={{ fontSize: 10, fontWeight: 700, padding: '2px 8px', borderRadius: 4, background: 'rgba(56,89,208,0.12)', color: '#3859D0', fontFamily: 'var(--font-mono)', letterSpacing: '0.04em' }}>
                  {String(camp.status).replace(/_/g, ' ').toUpperCase()}
                </span>
              )}
              {camp?.brand_name && (
                <span style={{ fontSize: 10, fontWeight: 700, padding: '2px 8px', borderRadius: 4, background: bc + '15', color: bc, fontFamily: 'var(--font-mono)', border: `1px solid ${bc}25`, letterSpacing: '0.04em' }}>
                  {camp.brand_name.toUpperCase()}
                </span>
              )}
            </div>
          </div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexShrink: 0, marginTop: 2 }}>
            <button className="btn" style={{ height: 30, padding: '0 12px', fontSize: 12 }} onClick={onBack}>← Voltar</button>
          </div>
        </div>
      </div>
      <div className="scrollbar" style={{ flex: 1, minHeight: 0, overflowY: 'auto', padding: '28px 40px 48px', background: 'var(--bg, #f8fafc)' }}>
        {loading && <div style={{ color: 'var(--text-muted)', fontSize: 13 }}>A carregar setup…</div>}
        {error && <div style={{ color: '#dc2626', fontSize: 13 }}>{error}</div>}
        {!loading && !error && data && (data.canais || []).length === 0 && (
          <div style={{ color: 'var(--text-muted)', fontSize: 14 }}>Esta campanha ainda não tem canais no briefing nem setup.</div>
        )}
        {!loading && !error && data && (data.canais || []).map(ch => (
          <ActCanalCard key={ch.canal} canal={ch} onActivar={activar} busy={busy} campId={campId} user={user} />
        ))}
      </div>
    </div>
  );
};

const ActHome = ({ user, onOpen }) => {
  const { brand, setBrand, isAll } = window.useMktBrand ? window.useMktBrand() : { brand: 'todas', setBrand: () => {}, isAll: true };
  const [allBrands, setAllBrands] = React.useState([]);
  const [data, setData] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [filterEstado, setFilterEstado] = React.useState('all');
  const [filterCanal, setFilterCanal] = React.useState('all');

  React.useEffect(() => {
    fetch('/api/marketing/brands').then(r => r.ok ? r.json() : []).then(d => {
      const src = Array.isArray(d) ? d : (d?.brands || []);
      const list = src.filter(b => b.slug !== 'todas').map(b => ({
        ...b, name: ACT_BRAND_NAMES[b.slug] || b.name,
      }));
      list.sort((a, b) => {
        const ia = ACT_BRAND_ORDER.indexOf(a.slug), ib = ACT_BRAND_ORDER.indexOf(b.slug);
        return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib);
      });
      setAllBrands(list);
    }).catch(() => {});
  }, []);

  const reload = React.useCallback(async () => {
    try {
      setError(null);
      const d = await actFetch(`/api/marketing/activacao/matriz${brand && brand !== 'todas' ? `?brand=${encodeURIComponent(brand)}` : ''}`);
      setData(d);
    } catch (e) { setError(e.message); }
    finally { setLoading(false); }
  }, [brand]);
  React.useEffect(() => { setLoading(true); reload(); }, [reload]);

  const campanhas = React.useMemo(() => {
    if (!data) return loading ? null : [];
    let arr = data.campanhas || [];
    if (filterCanal !== 'all') arr = arr.filter(c => c.canais?.[filterCanal]?.in_briefing);
    return arr;
  }, [data, filterCanal, loading]);

  const kpis = data?.kpis || { total: 0, a_produzir: 0, setup: 0, agendadas: 0, publicadas: 0, falhas: 0 };
  const kpiCards = [
    { label: 'Campanhas', value: kpis.total, filter: 'all', accent: '#3859D0', fill: 1 },
    { label: 'A produzir', value: kpis.a_produzir, filter: 'a_produzir', accent: '#F59E0B', fill: kpis.total ? kpis.a_produzir / kpis.total : 0 },
    { label: 'Setup', value: kpis.setup, filter: 'setup', accent: '#3859D0', fill: kpis.total ? kpis.setup / kpis.total : 0 },
    { label: 'Agendadas', value: kpis.agendadas, filter: 'agendado', accent: '#0f766e', fill: kpis.total ? kpis.agendadas / kpis.total : 0 },
    { label: 'Publicadas', value: kpis.publicadas, filter: 'publicado', accent: '#10B981', fill: kpis.total ? kpis.publicadas / kpis.total : 0 },
    { label: 'Falhas', value: kpis.falhas, filter: 'falhou', accent: '#EF4444', fill: kpis.total ? kpis.falhas / kpis.total : 0 },
  ];

  const hasActive = filterEstado !== 'all' || filterCanal !== 'all';
  const filteredCount = (campanhas || []).filter(c => filterEstado === 'all' || Object.values(c.canais || {}).some(x => x.estado === filterEstado)).length;

  return (
    <div data-theme="light" style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', '--bg': '#f8fafc', '--bg-elev': '#ffffff', '--bg-hover': '#f1f5f9', '--bg-sunken': '#e8edf5', '--border': '#dde3ef', '--text': '#112954', '--text-muted': '#4a5e7a', '--text-dim': '#6b7fa3', '--ai-500': '#3859D0' }}>
      <div style={{ background: 'var(--bg-elev)', borderBottom: '1px solid var(--border)', padding: '20px 40px 0', flexShrink: 0 }}>
        <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: '0.07em', color: 'var(--text-muted)', textTransform: 'uppercase', marginBottom: 6, fontFamily: 'var(--font-mono)' }}>
          MARKETING · ACTIVACAO
        </div>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16 }}>
          <div>
            <h1 style={{ margin: 0, fontSize: 21, fontWeight: 700, color: 'var(--text)', fontFamily: 'var(--font-display)', letterSpacing: '-0.01em', lineHeight: 1.2 }}>Activação</h1>
            <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 6 }}>
              {kpis.total} campanha{kpis.total !== 1 ? 's' : ''}{isAll ? ' · todas as marcas' : ''}
            </div>
          </div>
        </div>
        <div style={{ height: 1, background: 'var(--border)', margin: '16px -40px 0' }} />
        <div style={{ display: 'flex', gap: 0, overflowX: 'auto' }}>
          {[{ slug: 'todas', name: 'Todas' }, ...allBrands].map(b => {
            const active = b.slug === 'todas' ? isAll : brand === b.slug;
            return (
              <button key={b.slug} onClick={() => setBrand && setBrand(b.slug === 'todas' ? 'todas' : b.slug)}
                style={{
                  background: 'none', border: 'none', outline: 'none',
                  borderBottom: `2px solid ${active ? 'var(--ai-500)' : 'transparent'}`,
                  color: active ? 'var(--text)' : 'var(--text-muted)',
                  fontSize: 13, fontWeight: active ? 600 : 500,
                  fontFamily: 'var(--font-display)', letterSpacing: '.01em',
                  padding: '10px 18px 12px', cursor: 'pointer', whiteSpace: 'nowrap',
                }}>
                {b.name}
              </button>
            );
          })}
        </div>
      </div>

      <div className="scrollbar" style={{ flex: 1, minHeight: 0, overflowY: 'auto', overflowX: 'clip', padding: '28px 40px 0', background: 'var(--bg, #f8fafc)', display: 'flex', flexDirection: 'column', gap: 18 }}>
        {!loading && !error && data && <ActBanner kpis={kpis} campanhas={data.campanhas} userName={user.nome_apresentar} />}

        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 8 }}>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
            <ActDropdown label="Estado" value={filterEstado} onChange={setFilterEstado} options={[
              { value: 'all', label: 'Todos' },
              { value: 'a_produzir', label: 'A produzir' },
              { value: 'setup', label: 'Setup' },
              { value: 'agendado', label: 'Agendado' },
              { value: 'publicado', label: 'Publicado' },
              { value: 'falhou', label: 'Falhou' },
            ]} />
            <ActDropdown label="Canal" value={filterCanal} onChange={setFilterCanal} options={[
              { value: 'all', label: 'Todos' },
              ...ACT_CHANNELS.map(c => ({ value: c.id, label: c.label })),
            ]} />
            {hasActive && (
              <button onClick={() => { setFilterEstado('all'); setFilterCanal('all'); }} style={{
                background: 'none', border: 'none', color: 'var(--text-muted)', fontSize: 11,
                cursor: 'pointer', padding: '4px 6px', fontFamily: 'var(--font-mono)',
              }}>✕ limpar</button>
            )}
            <span style={{ fontSize: 12, color: 'var(--text-muted)', paddingLeft: 4 }}>
              {filteredCount} resultado{filteredCount !== 1 ? 's' : ''}
            </span>
          </div>
        </div>

        <div style={{ display: 'flex', gap: 12 }}>
          {kpiCards.map((k, i) => {
            const isActive = k.filter !== 'all' && filterEstado === k.filter;
            return (
              <div key={k.label} onClick={() => setFilterEstado(isActive ? 'all' : k.filter)}
                style={{
                  flex: '1 1 0', background: 'var(--bg-elev, #ffffff)',
                  border: `1px solid ${isActive ? k.accent : 'var(--border, #dde3ef)'}`,
                  borderRadius: 8, padding: '12px 16px 0',
                  display: 'flex', flexDirection: 'column', gap: 4, overflow: 'hidden',
                  cursor: 'pointer',
                  animation: 'slide-up 0.25s ease-out both',
                  animationDelay: `${i * 60}ms`,
                }}>
                <div style={{ fontSize: 9.5, fontWeight: 600, letterSpacing: '0.10em', textTransform: 'uppercase', color: isActive ? k.accent : 'var(--text-muted)', fontFamily: 'var(--font-mono)', whiteSpace: 'nowrap' }}>{k.label}</div>
                <div style={{ fontSize: 22, fontWeight: 700, fontFamily: 'var(--font-display)', color: k.accent, lineHeight: 1, paddingBottom: 10 }}>{k.value}</div>
                <div style={{ height: 3, background: 'var(--bg-sunken, #eef1f6)', overflow: 'hidden' }}>
                  <div style={{ height: '100%', width: `${(k.fill || 0) * 100}%`, background: k.accent }} />
                </div>
              </div>
            );
          })}
        </div>

        {error && <div style={{ color: '#dc2626', fontSize: 13 }}>{error}</div>}
        <ActLista campanhas={campanhas} isAll={isAll} onOpen={onOpen} filterEstado={filterEstado} />
      </div>
    </div>
  );
};

const MktActivacaoScreen = () => {
  const [hash, setHash] = React.useState(actParseHash());
  React.useEffect(() => {
    const onHash = () => setHash(actParseHash());
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  const user = React.useMemo(() => actGetUser(), []);

  return (
    <div className="scrollbar" style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
      <style>{`
        @keyframes slide-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
      `}</style>
      {hash.camp
        ? <ActDetalhe campId={hash.camp} user={user} onBack={() => actSetCamp(null)} />
        : <ActHome user={user} onOpen={id => actSetCamp(id)} />
      }
    </div>
  );
};

window.MktActivacaoScreen = MktActivacaoScreen;
