/* Ligações — consola de Apps, APIs e contas.
   Expõe window.MktLigacoesScreen. */

const LIG_STATUS = {
  ligado:       { label: 'Ligado',        color: '#166534', bg: 'rgba(22,163,74,.12)' },
  atencao:      { label: 'Atenção',       color: '#92400E', bg: 'rgba(245,158,11,.16)' },
  app_guardada: { label: 'App guardada',  color: '#92400E', bg: 'rgba(245,158,11,.16)' },
  por_ligar:    { label: 'Por ligar',     color: '#9A3412', bg: 'rgba(185,28,28,.08)' },
  em_breve:     { label: 'Em breve',      color: '#64748B', bg: 'var(--bg-sunken)' },
  erro:         { label: 'Erro',          color: '#B91C1C', bg: 'rgba(220,38,38,.10)' },
};

const BRIEFING_LABELS = {
  meta_ads: 'Meta Ads',
  linkedin_ads: 'LinkedIn Ads',
  google_ads_search: 'Google Search Ads',
  google_ads_display: 'Google Display',
  email: 'Email Marketing',
  whatsapp: 'WhatsApp',
  website: 'Website / Blog',
  muppi_led: 'Painéis LED',
};

const LIG_CAT_COLOR = {
  canais: '#3859D0',
  dados: '#0F766E',
  negocio: '#9A3412',
  infra: '#6D28D9',
};

async function mktLigFetch(url, opts) {
  const p = new URLSearchParams(window.location.search || '');
  const email = window.currentUser?.email || '';
  if (email && !p.get('email')) p.set('email', email);
  const full = url + (url.includes('?') ? '&' : '?') + p.toString();
  let res;
  try {
    res = await fetch(full, { credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, ...opts });
  } catch (e) {
    throw new Error(`Erro de rede: ${e.message}`);
  }
  const body = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(body.error || `HTTP ${res.status}`);
  return body;
}

function ligStatusMeta(status) {
  return LIG_STATUS[status] || LIG_STATUS.por_ligar;
}

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

function ligSourceLabel(source) {
  if (source === 'db') return 'Cofre';
  if (source === 'env') return '.env';
  return null;
}

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

function ligExtraChannels(provider) {
  const ids = provider?.briefing_channels || [];
  if (ids.length > 1) return ids;
  if (ids.length === 1) {
    const label = BRIEFING_LABELS[ids[0]] || ids[0];
    if (label.toLowerCase() !== String(provider.label || '').toLowerCase()) return ids;
  }
  return [];
}

function ligFailText(provider) {
  if (provider?.status !== 'atencao' && provider?.status !== 'erro') return null;
  const last = provider.usage?.last;
  if (last && last.ok === false && last.error) return last.error;
  return provider.last_check?.message || null;
}

const LigToast = ({ msg, type }) => {
  if (!msg) return null;
  const bg = type === 'error' ? '#B91C1C' : type === 'warn' ? '#B45309' : '#166534';
  return (
    <div style={{
      position: 'fixed', bottom: 24, right: 24, zIndex: 4000,
      padding: '12px 16px', borderRadius: 8, fontSize: 13, maxWidth: 360,
      background: bg, color: '#fff', boxShadow: '0 10px 30px rgba(17,41,84,.18)',
    }}>{msg}</div>
  );
};

const LigMonogram = ({ label, category }) => {
  const letter = String(label || '?').trim().charAt(0).toUpperCase();
  const color = LIG_CAT_COLOR[category] || '#3859D0';
  return (
    <div style={{
      width: 36, height: 36, borderRadius: 8, flexShrink: 0,
      display: 'grid', placeItems: 'center',
      background: `${color}14`, color, fontFamily: 'var(--font-display)',
      fontWeight: 700, fontSize: 15,
    }}>{letter}</div>
  );
};

const LigBadge = ({ status }) => {
  const st = ligStatusMeta(status);
  return (
    <span style={{
      fontSize: 10, fontWeight: 700, fontFamily: 'var(--font-mono)', letterSpacing: '0.04em',
      textTransform: 'uppercase', padding: '2px 7px', borderRadius: 4,
      background: st.bg, color: st.color,
    }}>{st.label}</span>
  );
};

const inpStyle = {
  fontSize: 13, fontFamily: 'inherit', color: 'var(--text)',
  border: '1px solid var(--border)', borderRadius: 8, padding: '8px 10px',
  background: 'var(--bg-sunken)', width: '100%',
};

const LIG_TABS = [
  { id: 'saude', label: 'Saúde' },
  { id: 'chamadas', label: 'Chamadas' },
  { id: 'config', label: 'Configuração' },
];

const LIG_PERIODS = [
  { id: 1, label: '24 h' },
  { id: 7, label: '7 dias' },
  { id: 30, label: '30 dias' },
];

function ligSsGet(key, fallback) {
  try {
    const v = sessionStorage.getItem(`ligacoes-filter-${key}`);
    return v == null || v === '' ? fallback : v;
  } catch { return fallback; }
}

function ligSsSet(key, value) {
  try { sessionStorage.setItem(`ligacoes-filter-${key}`, value); } catch { /* sessão indisponível */ }
}

function ligMatchesCard(provider, card) {
  if (card === 'ligadas') return provider.status === 'ligado';
  if (card === 'atencao') return provider.status === 'atencao' || provider.status === 'app_guardada';
  if (card === 'chamadas') return (provider.usage?.calls_7d || 0) > 0;
  if (card === 'falhas') return (provider.usage?.fails_7d || 0) > 0;
  return true;
}

function ligSortValue(provider, key) {
  if (key === 'when') {
    const iso = provider.usage?.last?.at || provider.last_check?.checked_at;
    const t = iso ? new Date(iso).getTime() : 0;
    return Number.isNaN(t) ? 0 : t;
  }
  if (key === 'latency') {
    const n = provider.usage?.last?.latency_ms ?? provider.last_check?.latency_ms;
    return n == null ? -1 : Number(n);
  }
  if (key === 'calls') return provider.usage?.calls_7d || 0;
  if (key === 'fails') return provider.usage?.fails_7d || 0;
  return 0;
}

const ligTh = {
  textAlign: 'left', fontSize: 10, fontWeight: 600, fontFamily: 'var(--font-mono)',
  letterSpacing: '0.05em', textTransform: 'uppercase', color: 'var(--text-dim)',
  padding: '10px 12px', borderBottom: '1px solid var(--border)', whiteSpace: 'nowrap',
  background: 'var(--bg-elev)', position: 'sticky', top: 0, zIndex: 1,
};

const LigSortTh = ({ label, sortKey, sort, onSort }) => {
  const active = sort.key === sortKey;
  return (
    <th style={ligTh}>
      <button
        type="button"
        onClick={() => onSort(sortKey)}
        style={{
          border: 0, background: 'transparent', padding: 0, cursor: 'pointer',
          font: 'inherit', letterSpacing: 'inherit', textTransform: 'inherit',
          color: active ? 'var(--text)' : 'var(--text-dim)', fontWeight: 600,
        }}
      >{label}{active ? (sort.dir === 'asc' ? ' ↑' : ' ↓') : ''}</button>
    </th>
  );
};

const LigSetupPage = ({ providerKey, marca, seed, canWrite, onBack, onChanged, onToast }) => {
  const [detail, setDetail] = React.useState(null);
  const [config, setConfig] = React.useState({});
  const [secrets, setSecrets] = React.useState({});
  const [busy, setBusy] = React.useState(null);
  const [confirmOff, setConfirmOff] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const [tab, setTab] = React.useState('saude');
  const [days, setDays] = React.useState(7);
  const [callsLoading, setCallsLoading] = React.useState(false);

  const load = React.useCallback(async (period, resetForm) => {
    const q = new URLSearchParams();
    if (marca) q.set('marca_slug', marca);
    q.set('days', String(period || 7));
    if (resetForm) setErr(null);
    const out = await mktLigFetch(`/api/marketing/ligacoes/${providerKey}?${q.toString()}`);
    setDetail(out);
    if (resetForm) {
      setConfig({ ...(out.provider?.config || {}) });
      setSecrets({});
    }
    return out;
  }, [providerKey, marca]);

  React.useEffect(() => {
    let stop = false;
    setCallsLoading(true);
    load(7, true).catch(e => { if (!stop) setErr(e.message); }).finally(() => { if (!stop) setCallsLoading(false); });
    return () => { stop = true; };
  }, [load]);

  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key !== 'Escape') return;
      if (e.target && (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA')) return;
      onBack();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onBack]);

  const changePeriod = async (next) => {
    setDays(next);
    setCallsLoading(true);
    try { await load(next, false); }
    catch (e) { setErr(e.message); }
    finally { setCallsLoading(false); }
  };

  const view = detail?.provider || seed;
  const fields = view?.fields || [];
  const writable = !!(detail ? detail.can_write : canWrite);
  const phase = view?.phase;
  const checked = view?.last_check;
  const src = ligSourceLabel(view?.source);
  const calls = detail?.calls;

  const guardar = async () => {
    setBusy('save'); setErr(null);
    try {
      await mktLigFetch(`/api/marketing/ligacoes/${providerKey}`, {
        method: 'PUT',
        body: JSON.stringify({ marca_slug: marca || null, config, secrets }),
      });
      onToast('Ligação guardada no cofre.');
      await load(days, true);
      if (onChanged) await onChanged();
    } catch (e) { setErr(e.message); }
    finally { setBusy(null); }
  };

  const testar = async () => {
    setBusy('test'); setErr(null);
    try {
      const out = await mktLigFetch(`/api/marketing/ligacoes/${providerKey}/test`, {
        method: 'POST',
        body: JSON.stringify({ marca_slug: marca || null }),
      });
      onToast(out.message || (out.ok ? 'Ligação ok.' : 'O teste falhou.'), out.ok ? 'ok' : 'warn');
      await load(days, true);
      if (onChanged) await onChanged();
    } catch (e) { setErr(e.message); onToast(e.message, 'error'); }
    finally { setBusy(null); }
  };

  const desligar = async () => {
    if (!confirmOff) { setConfirmOff(true); return; }
    setBusy('off'); setErr(null);
    try {
      const q = marca ? `?marca_slug=${encodeURIComponent(marca)}` : '';
      await mktLigFetch(`/api/marketing/ligacoes/${providerKey}${q}`, { method: 'DELETE' });
      onToast('Ligação desactivada. O .env deixa de ser usado enquanto estiver desligada.');
      setConfirmOff(false);
      await load(days, true);
      if (onChanged) await onChanged();
    } catch (e) { setErr(e.message); }
    finally { setBusy(null); }
  };

  const autorizar = async () => {
    setBusy('oauth'); setErr(null);
    try {
      const q = new URLSearchParams({
        marca_slug: marca || '',
        vanity: (config.vanity || view?.vanity || '').trim(),
        organization_urn: (config.organization_id || '').trim(),
        return_to: 'ligacoes',
      });
      const out = await mktLigFetch(`/api/marketing/ligacoes/${providerKey}/oauth/start?${q.toString()}`);
      window.location.href = out.url;
    } catch (e) { setErr(e.message); setBusy(null); }
  };

  const copiar = async (text) => {
    try {
      await navigator.clipboard.writeText(text);
      onToast('Redirect URL copiado.');
    } catch { onToast('Não foi possível copiar.', 'warn'); }
  };

  const tabBtn = (id, label) => {
    const active = tab === id;
    return (
      <button
        key={id}
        type="button"
        onClick={() => setTab(id)}
        style={{
          border: 0, background: 'transparent', cursor: 'pointer',
          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)', padding: '10px 16px 12px',
        }}
      >{label}</button>
    );
  };

  return (
    <div data-theme="light" 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: '16px 40px 0', flexShrink: 0 }}>
        <div style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', letterSpacing: '0.08em' }}>
          MARKETING · LIGAÇÕES
        </div>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16, marginTop: 8 }}>
          <div style={{ minWidth: 0 }}>
            <button type="button" onClick={onBack} className="btn btn-sm" style={{ height: 28, padding: '0 10px', marginBottom: 8 }}>← Ligações</button>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
              <LigMonogram label={view?.label} category={view?.category} />
              <h1 className="font-display" style={{ margin: 0, fontSize: 21, fontWeight: 700, letterSpacing: '-0.01em' }}>{view?.label || 'Ligação'}</h1>
              <LigBadge status={view?.status} />
            </div>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 6, lineHeight: 1.45 }}>{view?.desc}</div>
          </div>
          {!phase && (
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
              <button type="button" className="btn btn-ai" disabled={!writable || !!busy || !fields.length} onClick={guardar} style={{ height: 32, padding: '0 14px', fontSize: 12, opacity: writable && !busy ? 1 : 0.5 }}>
                {busy === 'save' ? 'A guardar…' : 'Guardar'}
              </button>
              <button type="button" className="btn" disabled={!writable || !!busy} onClick={testar} style={{ height: 32, padding: '0 14px', fontSize: 12 }}>
                {busy === 'test' ? 'A testar…' : 'Testar'}
              </button>
              {view?.oauth && (
                <button type="button" className="btn" disabled={!writable || !!busy} onClick={autorizar} style={{ height: 32, padding: '0 14px', fontSize: 12 }}>
                  {busy === 'oauth' ? 'A abrir…' : 'Autorizar'}
                </button>
              )}
              <button type="button" className="btn" disabled={!writable || !!busy || view?.source === 'none'} onClick={desligar} style={{ height: 32, padding: '0 14px', fontSize: 12, color: confirmOff ? '#B91C1C' : undefined }}>
                {busy === 'off' ? 'A desligar…' : (confirmOff ? 'Confirmar desligar' : 'Desligar')}
              </button>
            </div>
          )}
        </div>
        <div style={{ display: 'flex', gap: 0, marginTop: 12 }}>
          {LIG_TABS.map(item => tabBtn(item.id, item.label))}
        </div>
      </div>

      <div className="scrollbar" style={{ flex: 1, overflowY: 'auto', padding: '22px 40px 48px' }}>
        {err && <div style={{ fontSize: 12, color: '#B91C1C', marginBottom: 12 }}>{err}</div>}

        {tab === 'saude' && (
          <div style={{ maxWidth: 720, display: 'grid', gap: 14 }}>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 10 }}>
              {[
                ['Origem', src || '—'],
                ['Âmbito', view?.scope === 'global' ? 'Global' : (marca || '—')],
                ['Latência', checked?.latency_ms != null ? `${checked.latency_ms} ms` : '—'],
                ['Último teste', ligFmtWhen(checked?.checked_at) || '—'],
              ].map(([label, value]) => (
                <div key={label} style={{ background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 10, padding: '12px 14px' }}>
                  <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', letterSpacing: '0.06em', textTransform: 'uppercase' }}>{label}</div>
                  <div style={{ fontSize: 14, fontWeight: 700, marginTop: 6 }}>{value}</div>
                </div>
              ))}
            </div>
            {checked?.message && (
              <div style={{ fontSize: 13, color: 'var(--text)', background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 10, padding: '12px 14px', lineHeight: 1.5 }}>{checked.message}</div>
            )}
            {view?.expires_at && (
              <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Expira {ligFmtWhen(view.expires_at)}</div>
            )}
            <div style={{ display: 'flex', gap: 16, fontSize: 12, color: 'var(--text-muted)' }}>
              <span>24 h <b style={{ color: 'var(--text)' }}>{ligFmtNum(calls?.calls_24h || 0)}</b> · {ligFmtNum(calls?.fails_24h || 0)} falhas</span>
              <span>7 dias <b style={{ color: 'var(--text)' }}>{ligFmtNum(calls?.calls_7d || view?.usage?.calls_7d || 0)}</b> · {ligFmtNum(calls?.fails_7d || view?.usage?.fails_7d || 0)} falhas</span>
            </div>
          </div>
        )}

        {tab === 'chamadas' && (
          <div>
            <div style={{ display: 'flex', gap: 6, marginBottom: 14 }}>
              {LIG_PERIODS.map(period => (
                <button
                  key={period.id}
                  type="button"
                  onClick={() => changePeriod(period.id)}
                  className="btn btn-sm"
                  style={{
                    height: 28, padding: '0 12px', fontSize: 12,
                    fontWeight: days === period.id ? 700 : 500,
                    borderColor: days === period.id ? 'var(--ai-500)' : undefined,
                    background: days === period.id ? 'rgba(56,89,208,0.08)' : undefined,
                  }}
                >{period.label}</button>
              ))}
            </div>
            {callsLoading && <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>A carregar chamadas…</div>}
            {!callsLoading && !(calls?.recent || []).length && (
              <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Sem chamadas neste período.</div>
            )}
            {!callsLoading && (calls?.recent || []).length > 0 && (
              <div style={{ background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 10, overflow: 'auto' }}>
                <table style={{ width: '100%', borderCollapse: 'collapse', minWidth: 640 }}>
                  <thead>
                    <tr>
                      {['Hora', 'Operação', 'HTTP', 'Latência', 'Resultado'].map(label => (
                        <th key={label} style={ligTh}>{label}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {calls.recent.map((row, i) => (
                      <tr key={`${row.created_at}-${i}`}>
                        <td style={{ padding: '8px 12px', borderBottom: '1px solid var(--border)', fontFamily: 'var(--font-mono)', fontSize: 12 }}>{ligFmtWhen(row.created_at)}</td>
                        <td style={{ padding: '8px 12px', borderBottom: '1px solid var(--border)', fontSize: 12 }}>
                          <div>{row.operation || 'chamada'}</div>
                          {row.ok === false && row.error && <div style={{ color: '#B91C1C', fontSize: 11, marginTop: 2 }}>{row.error}</div>}
                        </td>
                        <td style={{ padding: '8px 12px', borderBottom: '1px solid var(--border)', fontFamily: 'var(--font-mono)', fontSize: 12 }}>{row.http_status || '—'}</td>
                        <td style={{ padding: '8px 12px', borderBottom: '1px solid var(--border)', fontFamily: 'var(--font-mono)', fontSize: 12 }}>{row.latency_ms != null ? `${row.latency_ms} ms` : '—'}</td>
                        <td style={{ padding: '8px 12px', borderBottom: '1px solid var(--border)', fontSize: 12, color: row.ok === false ? '#B91C1C' : '#166534', fontWeight: 600 }}>{row.ok === false ? 'Falhou' : 'Ok'}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        )}

        {tab === 'config' && (
          <div style={{ maxWidth: 640, display: 'grid', gap: 16 }}>
            {phase && (
              <div style={{ fontSize: 13, color: 'var(--text-muted)', lineHeight: 1.5 }}>
                Esta integração está planeada para <b>{phase}</b>. Ainda não há campos para preencher.
              </div>
            )}
            {!phase && fields.length === 0 && (
              <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Esta integração ainda não tem campos de credencial.</div>
            )}
            {!phase && fields.length > 0 && (
              <div style={{ display: 'grid', gap: 10 }}>
                {fields.map(field => {
                  const isSecret = !!field.secret;
                  const value = isSecret ? (secrets[field.key] || '') : (config[field.key] || '');
                  const hint = isSecret ? (view?.hints?.[field.key] || '') : '';
                  const common = {
                    value,
                    disabled: !writable || !!busy,
                    placeholder: hint ? `Guardado (${hint}) — cola para substituir` : (field.placeholder || ''),
                    autoComplete: 'off',
                    onChange: e => {
                      const v = e.target.value;
                      if (isSecret) setSecrets(s => ({ ...s, [field.key]: v }));
                      else setConfig(c => ({ ...c, [field.key]: v }));
                    },
                    style: field.type === 'textarea' ? { ...inpStyle, minHeight: 96, resize: 'vertical', fontFamily: 'var(--font-mono)', fontSize: 11 } : inpStyle,
                  };
                  return (
                    <label key={field.key} style={{ display: 'grid', gap: 4 }}>
                      <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>{field.label}{field.required ? ' *' : ''}</span>
                      {field.type === 'textarea' ? <textarea {...common} /> : <input type={isSecret ? 'password' : 'text'} {...common} />}
                    </label>
                  );
                })}
              </div>
            )}
            {view?.oauth && detail?.redirect_uri && (
              <div style={{ fontSize: 12, color: 'var(--text-muted)', lineHeight: 1.45 }}>
                Redirect URL na tab Auth da App
                <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginTop: 6 }}>
                  <code style={{ flex: 1, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text)', wordBreak: 'break-all' }}>{detail.redirect_uri}</code>
                  <button type="button" className="btn btn-sm" onClick={() => copiar(detail.redirect_uri)} style={{ height: 28 }}>Copiar</button>
                </div>
              </div>
            )}
            {!writable && !phase && (
              <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Só um administrador pode alterar ligações.</div>
            )}
            {Array.isArray(view?.howto) && view.howto.length > 0 && (
              <div>
                <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.06em', color: 'var(--text-dim)', textTransform: 'uppercase', marginBottom: 6 }}>Como obter</div>
                <ol style={{ margin: 0, paddingLeft: 18, display: 'grid', gap: 4, fontSize: 12, color: 'var(--text-muted)', lineHeight: 1.45 }}>
                  {view.howto.map(step => <li key={step}>{step}</li>)}
                </ol>
                {view.docs && (
                  <a href={view.docs} target="_blank" rel="noreferrer" style={{ display: 'inline-block', marginTop: 8, fontSize: 12, color: 'var(--ai-500)' }}>Documentação</a>
                )}
              </div>
            )}
            {Array.isArray(detail?.audit) && detail.audit.length > 0 && (
              <div>
                <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.06em', color: 'var(--text-dim)', textTransform: 'uppercase', marginBottom: 6 }}>Alterações</div>
                <div style={{ display: 'grid', gap: 6 }}>
                  {detail.audit.map((row, i) => (
                    <div key={`${row.created_at}-${i}`} style={{ display: 'flex', gap: 8, fontSize: 12, color: 'var(--text-muted)' }}>
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-dim)', flexShrink: 0 }}>{ligFmtWhen(row.created_at)}</span>
                      <span style={{ color: 'var(--text)' }}>{row.action}</span>
                      <span>{row.actor_email ? row.actor_email.split('@')[0] : 'sistema'}</span>
                      {row.ok === false && <span style={{ color: '#B91C1C' }}>falhou</span>}
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
};

const MktLigacoesScreen = () => {
  const hashMarca = (() => {
    try { return new URLSearchParams(window.location.hash.replace(/^#/, '')).get('marca') || ''; }
    catch { return ''; }
  })();
  const [marca, setMarca] = React.useState(hashMarca || 'biond');
  const [data, setData] = React.useState(null);
  const [cat, setCat] = React.useState('todas');
  const [q, setQ] = React.useState('');
  const [card, setCard] = React.useState(() => ligSsGet('card', 'all'));
  const [sort, setSort] = React.useState(() => ({
    key: ligSsGet('sort', ''),
    dir: ligSsGet('dir', 'desc') === 'asc' ? 'asc' : 'desc',
  }));
  const [err, setErr] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  window.useMktZoneLoading(loading && !data);
  const [openKey, setOpenKey] = React.useState(null);
  const [toast, setToast] = React.useState(null);
  const [testing, setTesting] = React.useState(false);

  const showToast = (msg, type = 'ok') => {
    setToast({ msg, type });
    setTimeout(() => setToast(null), 3200);
  };

  const load = React.useCallback(async (slug) => {
    setLoading(true); setErr(null);
    try {
      const out = await mktLigFetch(`/api/marketing/ligacoes?marca_slug=${encodeURIComponent(slug || marca)}`);
      setData(out);
      if (out.selected?.marca?.slug) setMarca(out.selected.marca.slug);
    } catch (e) { setErr(e.message); }
    finally { setLoading(false); }
  }, [marca]);

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

  React.useEffect(() => {
    const pending = window.mktLigacaoPending;
    if (pending) {
      window.mktLigacaoPending = null;
      setOpenKey(pending);
    }
    window.mktOpenLigacao = (key) => setOpenKey(key);
    return () => { delete window.mktOpenLigacao; };
  }, []);

  React.useEffect(() => {
    const params = new URLSearchParams(window.location.hash.replace(/^#/, ''));
    if (params.get('li') === 'ok') showToast('LinkedIn autorizado. Já podes publicar na Activação.');
    if (params.get('li') === 'erro') showToast(params.get('err') || 'OAuth LinkedIn falhou.', 'error');
  }, []);

  const providers = data?.providers || [];
  const categories = [{ id: 'todas', label: 'Todas' }, ...(data?.categories || [])];
  const summary = data?.summary || {};
  const query = q.trim().toLowerCase();
  const visible = providers.filter(p => {
    if (cat !== 'todas' && p.category !== cat) return false;
    if (!ligMatchesCard(p, card)) return false;
    if (!query) return true;
    return `${p.label} ${p.desc} ${p.key} ${(p.briefing_channels || []).join(' ')}`.toLowerCase().includes(query);
  });
  if (sort.key) {
    const dir = sort.dir === 'asc' ? 1 : -1;
    visible.sort((a, b) => (ligSortValue(a, sort.key) - ligSortValue(b, sort.key)) * dir);
  }
  const toggleCard = (id) => {
    const next = card === id ? 'all' : id;
    setCard(next);
    ligSsSet('card', next);
  };
  const onSort = (key) => {
    const next = sort.key === key
      ? { key, dir: sort.dir === 'asc' ? 'desc' : 'asc' }
      : { key, dir: 'desc' };
    setSort(next);
    ligSsSet('sort', next.key);
    ligSsSet('dir', next.dir);
  };
  const clearFilters = () => {
    setCard('all');
    setQ('');
    ligSsSet('card', 'all');
  };
  const baseCount = Math.max(providers.length, 1);
  const showMarcas = visible.some(p => p.scope === 'marca') || cat === 'todas' || cat === 'canais';
  const openSeed = providers.find(p => p.key === openKey) || null;

  const testAll = async () => {
    setTesting(true);
    try {
      const out = await mktLigFetch('/api/marketing/ligacoes/test-all', {
        method: 'POST',
        body: JSON.stringify({ marca_slug: marca }),
      });
      const failed = (out.results || []).filter(r => r.ok === false && r.status !== 'por_ligar' && r.status !== 'app_guardada').length;
      showToast(failed ? `${failed} teste(s) falharam.` : 'Testes concluídos.', failed ? 'warn' : 'ok');
      await load(marca);
    } catch (e) { showToast(e.message, 'error'); }
    finally { setTesting(false); }
  };

  const atencaoN = (summary.atencao || 0) + (summary.app_guardada || 0);
  const withCalls = providers.filter(p => (p.usage?.calls_7d || 0) > 0).length;
  const withFails = providers.filter(p => (p.usage?.fails_7d || 0) > 0).length;
  const tiles = [
    { id: 'ligadas', label: 'Ligadas', value: summary.ligadas || 0, fill: (summary.ligadas || 0) / baseCount, accent: '#166534' },
    { id: 'atencao', label: 'Atenção', value: atencaoN, fill: atencaoN / baseCount, accent: '#92400E' },
    { id: 'chamadas', label: 'Chamadas 7 dias', value: summary.calls_7d || 0, fill: withCalls / baseCount, accent: '#112954' },
    { id: 'falhas', label: 'Falhas 7 dias', value: summary.fails_7d || 0, fill: withFails / baseCount, accent: '#B91C1C' },
  ];

  if (openKey) {
    return (
      <>
        <LigSetupPage
          providerKey={openKey}
          marca={marca}
          seed={openSeed}
          canWrite={!!data?.can_write}
          onBack={() => setOpenKey(null)}
          onChanged={() => load(marca)}
          onToast={showToast}
        />
        <LigToast msg={toast?.msg} type={toast?.type} />
      </>
    );
  }

  return (
    <div data-theme="light" 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 0', flexShrink: 0 }}>
        <div style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', letterSpacing: '0.08em' }}>
          MARKETING · LIGAÇÕES
        </div>
        <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, marginTop: 6 }}>
          <div>
            <h1 className="font-display" style={{ margin: 0, fontSize: 21, fontWeight: 700, letterSpacing: '-0.01em' }}>
              Apps, APIs e contas
            </h1>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 4 }}>
              Estado, latência e chamadas dos últimos 7 dias.
            </div>
          </div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', paddingBottom: 2 }}>
            <input
              value={q}
              onChange={e => setQ(e.target.value)}
              placeholder="Pesquisar integração"
              style={{ ...inpStyle, width: 200, background: 'var(--bg-elev)', height: 32 }}
            />
            <button type="button" className="btn btn-sm" disabled={testing || !data?.can_write} onClick={testAll} style={{ height: 32, opacity: data?.can_write ? 1 : 0.5 }}>
              {testing ? 'A testar…' : 'Testar todas'}
            </button>
          </div>
        </div>
        <div style={{ height: 1, background: 'var(--border)', margin: '16px -40px 0' }} />
        <div style={{ display: 'flex', gap: 0, overflowX: 'auto' }}>
          {categories.map(c => {
            const active = cat === c.id;
            return (
              <button
                key={c.id}
                type="button"
                onClick={() => setCat(c.id)}
                style={{
                  border: 0, background: 'transparent', cursor: 'pointer',
                  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)', padding: '10px 18px 12px',
                }}
              >{c.label}</button>
            );
          })}
        </div>
      </div>

      <div className="scrollbar" style={{ flex: 1, overflowY: 'auto', padding: '22px 40px 48px' }}>
        {showMarcas && (data?.marcas || []).length > 0 && (
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 16 }}>
            {data.marcas.map(m => (
              <button
                key={m.slug}
                type="button"
                className="btn"
                onClick={() => { setMarca(m.slug); load(m.slug); }}
                style={{
                  height: 28, padding: '0 12px', fontSize: 12,
                  borderColor: marca === m.slug ? (m.color || '#3859D0') : undefined,
                  background: marca === m.slug ? 'rgba(56,89,208,0.08)' : undefined,
                  fontWeight: marca === m.slug ? 700 : 500,
                }}
              >{m.name || m.slug}</button>
            ))}
          </div>
        )}

        {data && (
          <div style={{ display: 'flex', gap: 12, marginBottom: 10 }}>
            {tiles.map(tile => {
              const active = card === tile.id;
              return (
                <button
                  key={tile.id}
                  type="button"
                  onClick={() => toggleCard(tile.id)}
                  style={{
                    flex: '1 1 0', textAlign: 'left', cursor: 'pointer', font: 'inherit', color: 'inherit',
                    background: 'var(--bg-elev)', border: `1px solid ${active ? tile.accent : 'var(--border)'}`,
                    borderRadius: 8, padding: '12px 16px 0', display: 'flex', flexDirection: 'column', gap: 4, overflow: 'hidden',
                  }}
                >
                  <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: active ? tile.accent : 'var(--text-muted)', fontFamily: 'var(--font-mono)' }}>{tile.label}</div>
                  <div className="font-display" style={{ fontSize: 22, fontWeight: 700, color: tile.accent, lineHeight: 1, paddingBottom: 10 }}>{ligFmtNum(tile.value)}</div>
                  <div style={{ height: 3, background: 'var(--bg-sunken)', margin: '0 -16px' }}>
                    <div style={{ height: '100%', width: `${Math.min(100, (tile.fill || 0) * 100)}%`, background: tile.accent }} />
                  </div>
                </button>
              );
            })}
          </div>
        )}

        {(card !== 'all' || query) && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12, fontSize: 12, color: 'var(--text-muted)' }}>
            <span>{visible.length} resultado{visible.length === 1 ? '' : 's'}</span>
            <button type="button" onClick={clearFilters} style={{ border: 0, background: 'none', color: 'var(--text-muted)', cursor: 'pointer', fontFamily: 'var(--font-mono)', fontSize: 11, padding: '4px 6px' }}>✕ limpar</button>
          </div>
        )}

        {loading && <div style={{ fontSize: 13, color: 'var(--text-muted)', padding: '32px 0' }}>A carregar ligações…</div>}
        {err && <div style={{ fontSize: 13, color: '#B91C1C' }}>{err}</div>}

        {!loading && !err && visible.length === 0 && (
          <div style={{ padding: '48px 0', textAlign: 'center' }}>
            <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Nenhuma integração neste filtro.</div>
            <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 6 }}>Experimenta outra categoria ou limpa o filtro.</div>
          </div>
        )}

        {!loading && !err && visible.length > 0 && (
          <div style={{ background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 10, overflow: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', minWidth: 760 }}>
              <thead>
                <tr>
                  <th style={ligTh}>Integração</th>
                  <th style={ligTh}>Estado</th>
                  <LigSortTh label="Última chamada" sortKey="when" sort={sort} onSort={onSort} />
                  <LigSortTh label="Latência" sortKey="latency" sort={sort} onSort={onSort} />
                  <LigSortTh label="Chamadas 7d" sortKey="calls" sort={sort} onSort={onSort} />
                  <LigSortTh label="Falhas 7d" sortKey="fails" sort={sort} onSort={onSort} />
                  <th style={ligTh}>Origem</th>
                </tr>
              </thead>
              <tbody>
                {visible.map(p => {
                  const last = p.usage?.last;
                  const when = ligFmtWhen(last?.at) || ligFmtWhen(p.last_check?.checked_at);
                  const latency = last?.latency_ms ?? p.last_check?.latency_ms;
                  const fail = ligFailText(p);
                  const channels = ligExtraChannels(p);
                  const src = ligSourceLabel(p.source);
                  return (
                    <tr
                      key={p.key}
                      onClick={() => setOpenKey(p.key)}
                      style={{ cursor: 'pointer' }}
                      onMouseEnter={e => { e.currentTarget.style.background = 'var(--bg-sunken)'; }}
                      onMouseLeave={e => { e.currentTarget.style.background = ''; }}
                    >
                      <td style={{ padding: '10px 12px', borderBottom: '1px solid var(--border)', verticalAlign: 'top' }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                          <LigMonogram label={p.label} category={p.category} />
                          <div style={{ minWidth: 0 }}>
                            <div className="font-display" style={{ fontSize: 13, fontWeight: 700 }}>{p.label}</div>
                            {channels.length > 0 && (
                              <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', marginTop: 2 }}>
                                {channels.map(id => BRIEFING_LABELS[id] || id).join(' · ')}
                              </div>
                            )}
                          </div>
                        </div>
                      </td>
                      <td style={{ padding: '10px 12px', borderBottom: '1px solid var(--border)', verticalAlign: 'top' }}>
                        <LigBadge status={p.status} />
                      </td>
                      <td style={{ padding: '10px 12px', borderBottom: '1px solid var(--border)', verticalAlign: 'top', maxWidth: 280 }}>
                        <div style={{ fontSize: 12, fontFamily: 'var(--font-mono)', color: 'var(--text)' }}>{when || (p.phase ? p.phase : '—')}</div>
                        {fail && <div style={{ fontSize: 11, color: '#B91C1C', marginTop: 3, lineHeight: 1.35 }}>{fail}</div>}
                      </td>
                      <td style={{ padding: '10px 12px', borderBottom: '1px solid var(--border)', verticalAlign: 'top', fontFamily: 'var(--font-mono)', fontSize: 12 }}>
                        {latency != null ? `${latency} ms` : '—'}
                      </td>
                      <td style={{ padding: '10px 12px', borderBottom: '1px solid var(--border)', verticalAlign: 'top', fontFamily: 'var(--font-mono)', fontSize: 12 }}>
                        {ligFmtNum(p.usage?.calls_7d || 0)}
                      </td>
                      <td style={{ padding: '10px 12px', borderBottom: '1px solid var(--border)', verticalAlign: 'top', fontFamily: 'var(--font-mono)', fontSize: 12, color: p.usage?.fails_7d ? '#B91C1C' : 'inherit' }}>
                        {ligFmtNum(p.usage?.fails_7d || 0)}
                      </td>
                      <td style={{ padding: '10px 12px', borderBottom: '1px solid var(--border)', verticalAlign: 'top', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-dim)' }}>
                        {src || '—'}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}
      </div>

      <LigToast msg={toast?.msg} type={toast?.type} />
    </div>
  );
};

window.MktLigacoesScreen = MktLigacoesScreen;
