/* SISTEMA · Ligação Primavera — Monitor de integração SQL Server → PostgreSQL */


// _sync_state guarda o nome da view SQL Server como table_name — mapear para nome PG
const VIEW_TO_PG = {
  'INCT_VW_TabTESMOVIMENTOS': 'tesouraria_movimentos',
  'INCT_VW_TabCabecDocStatus': 'documentos_status',
  'INCT_VW_TabCabLiq': 'liquidacoes',
  'INCT_VW_TabCabecDoc': 'documentos',
  'INCT_VW_TabLinhasDoc': 'documentos_linhas',
  'INCT_VW_TabClientes': 'clientes',
  'INCT_VW_TabFornecedores': 'fornecedores',
  'INCT_VW_TabVendedores': 'vendedores',
  'INCT_VW_TabArtigo': 'artigos',
  'INCT_VW_TabFamilias': 'familias',
  'INCT_VW_TabSubFamilias': 'subfamilias',
  'INCT_VW_TabCondPag': 'condicoes_pagamento',
  'INCT_VW_TabCabecCompras': 'compras',
  'INCT_VW_TabLinhasCompras': 'compras_linhas',
  'INCT_VW_TabINV_Movimentos': 'stock_movimentos',
  'INCT_VW_TabMoedas': 'moedas',
  'INCT_VW_TabArtigoCliente': 'artigos_cliente',
  'INCT_VW_TabMoradasAlternativasClientes': 'clientes_moradas',
};

// Grupo por tabela PG
const PG_GROUP_MAP = {
  tesouraria_movimentos: 'realtime', documentos_status: 'realtime',
  liquidacoes: 'hourly', documentos: 'hourly', documentos_linhas: 'hourly',
};

function fmtDt(dt) {
  if (!dt) return '—';
  return new Date(dt).toLocaleString('pt-PT', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
}

function fmtDur(ms) {
  if (ms == null) return '—';
  return ms < 1000 ? ms + 'ms' : (ms / 1000).toFixed(1) + 's';
}

function fmtN(n) {
  if (n == null) return '—';
  return Number(n).toLocaleString('pt-PT');
}

function GroupBadge({ group }) {
  const s = {
    realtime: { background: '#ef4444', color: '#fff' },
    hourly:   { background: '#f59e0b', color: '#000' },
    daily:    { background: 'var(--text-dim)', color: '#fff' },
    snapshot: { background: '#6366f1', color: '#fff' },
    agent:    { background: '#0ea5e9', color: '#fff' },
  }[group] || { background: 'var(--text-dim)', color: '#fff' };
  return (
    <span style={{ ...s, fontSize: 10, padding: '1px 6px', borderRadius: 3, fontFamily: 'var(--font-mono)', letterSpacing: '0.04em', whiteSpace: 'nowrap' }}>
      {group}
    </span>
  );
}

function StatusPill({ status }) {
  const ok = status === 'ok';
  return (
    <span style={{ fontSize: 10, padding: '1px 6px', borderRadius: 3, fontFamily: 'var(--font-mono)', background: ok ? '#d1fae5' : '#fee2e2', color: ok ? '#065f46' : '#b91c1c' }}>
      {status}
    </span>
  );
}

const SistemaPrimavera = () => {
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [forcing, setForcing] = React.useState(false);
  const [forceMsg, setForceMsg] = React.useState(null);
  const [syncTableOpen, setSyncTableOpen] = React.useState(false);

  const load = React.useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const r = await fetch('/api/primavera/monitor');
      if (!r.ok) throw new Error(await r.text());
      setData(await r.json());
    } catch (e) {
      setError(e.message);
    } finally {
      setLoading(false);
    }
  }, []);

  React.useEffect(() => { load(); }, []);
  React.useEffect(() => {
    const t = setInterval(load, 60000);
    return () => clearInterval(t);
  }, [load]);

  const forceSnapshot = async () => {
    setForcing(true);
    setForceMsg(null);
    try {
      const r = await fetch('/api/primavera/force-snapshot', { method: 'POST' });
      const j = await r.json();
      setForceMsg(j.ok ? 'Queued — o agente irá executar em breve.' : 'Erro: ' + j.error);
    } catch (e) {
      setForceMsg('Erro: ' + e.message);
    }
    setForcing(false);
    setTimeout(() => setForceMsg(null), 6000);
  };

  const agent = data?.agent;
  const isOnline = agent?.alive;

  return (
    <div style={{ height: '100%', overflow: 'auto', padding: '24px 28px', background: 'var(--bg)' }}>

      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 20 }}>
        <div>
          <div style={{ fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', letterSpacing: '0.08em' }}>SISTEMA · LIGAÇÃO PRIMAVERA</div>
          <h2 className="font-display" style={{ margin: '4px 0 0', fontSize: 20 }}>Monitor de Integração</h2>
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', gap: 8, alignItems: 'center' }}>
          {forceMsg && (
            <span style={{ fontSize: 12, color: forceMsg.startsWith('Erro') ? '#ef4444' : '#10b981' }}>{forceMsg}</span>
          )}
          <button className="btn btn-sm" onClick={load} disabled={loading} style={{ opacity: loading ? 0.5 : 1 }}>
            {loading ? 'A carregar…' : 'Actualizar'}
          </button>
          <button className="btn btn-sm btn-primary" onClick={forceSnapshot} disabled={forcing}>
            {forcing ? 'A enviar…' : 'Forçar Snapshot'}
          </button>
        </div>
      </div>

      {error && (
        <div style={{ padding: '10px 14px', background: '#fee2e2', color: '#b91c1c', borderRadius: 6, marginBottom: 16, fontSize: 13 }}>
          Erro ao carregar monitor: {error}
        </div>
      )}

      {/* Top row: 3 cards */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12, marginBottom: 20 }}>

        {/* Agent Status */}
        <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, padding: '14px 16px' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
            <span style={{ width: 8, height: 8, borderRadius: '50%', flexShrink: 0, background: !data ? 'var(--text-dim)' : isOnline ? '#22c55e' : '#ef4444', display: 'inline-block' }} />
            <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', letterSpacing: '0.05em' }}>AGENT · MACBOOK MARKETING</span>
          </div>
          <div style={{ fontSize: 24, fontWeight: 700, letterSpacing: '-0.5px', color: !data ? 'var(--text-dim)' : isOnline ? '#22c55e' : '#ef4444', marginBottom: 6 }}>
            {!data ? '…' : isOnline ? 'ONLINE' : 'OFFLINE'}
          </div>
          {agent?.last_seen ? (
            <div style={{ fontSize: 12, color: 'var(--text-muted)', lineHeight: 1.5 }}>
              Último heartbeat: {fmtDt(agent.last_seen)}<br />
              <span style={{ color: agent.last_seen_mins < 10 ? '#22c55e' : agent.last_seen_mins < 15 ? '#f59e0b' : '#ef4444' }}>
                {agent.last_seen_mins} min atrás
              </span>
            </div>
          ) : (
            <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>{loading ? '…' : 'Sem heartbeat registado'}</div>
          )}
          <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 8, fontFamily: 'var(--font-mono)', lineHeight: 1.5 }}>
            100.74.212.97 · Tailscale<br />
            PRIDIG2006 → schema primavera (PG)
          </div>
        </div>

        {/* Snapshots */}
        <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, padding: '14px 16px' }}>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', letterSpacing: '0.05em', marginBottom: 10 }}>SNAPSHOTS · cron 03:00 diário</div>

          <div style={{ marginBottom: 10 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 3 }}>VP Nightly (vp_snapshots)</div>
            {data?.vp_snapshot ? (
              <>
                <div style={{ fontSize: 13, fontWeight: 600 }}>{fmtDt(data.vp_snapshot.created_at)}</div>
                <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>
                  file_date: {data.vp_snapshot.file_date || '—'} · por: {data.vp_snapshot.imported_by || '—'}
                </div>
              </>
            ) : (
              <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>{loading ? '…' : 'Sem dados'}</div>
            )}
          </div>

          <div style={{ borderTop: '1px solid var(--border)', paddingTop: 10 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 3 }}>Top 10 Clientes 2026</div>
            {data?.top10_snapshot_at ? (
              <div style={{ fontSize: 13, fontWeight: 600 }}>{fmtDt(data.top10_snapshot_at)}</div>
            ) : (
              <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>{loading ? '…' : 'Sem dados'}</div>
            )}
          </div>
        </div>

        {/* Trigger Queue */}
        <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, padding: '14px 16px' }}>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', letterSpacing: '0.05em', marginBottom: 10 }}>TRIGGER QUEUE · últimos 5</div>
          {data?.trigger_queue?.length ? data.trigger_queue.map(tq => (
            <div key={tq.id} style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12, marginBottom: 6, flexWrap: 'wrap' }}>
              <span style={{
                fontSize: 10, padding: '1px 5px', borderRadius: 3, fontFamily: 'var(--font-mono)', whiteSpace: 'nowrap',
                background: tq.status === 'done' ? '#d1fae5' : tq.status === 'running' ? '#fef3c7' : tq.status === 'cancelled' ? '#f3f4f6' : '#e0e7ff',
                color: tq.status === 'done' ? '#065f46' : tq.status === 'running' ? '#92400e' : '#374151',
              }}>{tq.status}</span>
              <span style={{ color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', fontSize: 11 }}>{tq.command}</span>
              <span style={{ marginLeft: 'auto', color: 'var(--text-dim)', fontSize: 11, whiteSpace: 'nowrap' }}>{fmtDt(tq.created_at)}</span>
            </div>
          )) : (
            <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>{loading ? '…' : 'Sem triggers registados'}</div>
          )}
        </div>
      </div>

      {/* Sync State Table */}
      <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, marginBottom: 20 }}>
        <div onClick={() => setSyncTableOpen(o => !o)} style={{ padding: '12px 16px', display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer', userSelect: 'none' }}>
          <span style={{ fontSize: 13, fontWeight: 600 }}>Tabelas Sincronizadas</span>
          <span style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>primavera._sync_state · {data?.sync_state?.length ?? '…'} / 1 tabela activa</span>
          <span style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--text-dim)' }}>{syncTableOpen ? '▲' : '▼'}</span>
        </div>
        {syncTableOpen && (
          <div style={{ borderTop: '1px solid var(--border)', overflowX: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--bg)' }}>
                  {[['TABELA PG', 'left', 16], ['VIEW SQL SERVER', 'left', 10], ['GRUPO', 'left', 10], ['ROWS', 'right', 10], ['ÚLTIMA SYNC', 'left', 16]].map(([h, align, px]) => (
                    <th key={h} style={{ padding: `6px ${px}px`, textAlign: align, fontWeight: 500, color: 'var(--text-dim)', fontSize: 11, fontFamily: 'var(--font-mono)' }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {data?.sync_state?.length ? [...data.sync_state].sort((a, b) => (b.last_sync_at || '') > (a.last_sync_at || '') ? 1 : -1).map((row, i) => {
                  const pgName = VIEW_TO_PG[row.table_name] || row.table_name;
                  const grp = PG_GROUP_MAP[pgName] || 'daily';
                  return (
                    <tr key={row.table_name} style={{ borderBottom: '1px solid var(--border)', background: i % 2 !== 0 ? 'var(--bg)' : 'transparent' }}>
                      <td style={{ padding: '5px 16px', fontFamily: 'var(--font-mono)', fontSize: 11 }}>{pgName}</td>
                      <td style={{ padding: '5px 10px', color: 'var(--text-dim)', fontSize: 11, fontFamily: 'var(--font-mono)' }}>{row.table_name}</td>
                      <td style={{ padding: '5px 10px' }}><GroupBadge group={grp} /></td>
                      <td style={{ padding: '5px 10px', textAlign: 'right', fontFamily: 'var(--font-mono)' }}>{fmtN(row.rows_total)}</td>
                      <td style={{ padding: '5px 16px', color: 'var(--text-muted)' }}>{fmtDt(row.last_sync_at)}</td>
                    </tr>
                  );
                }) : (
                  <tr>
                    <td colSpan={5} style={{ padding: '24px 16px', color: 'var(--text-dim)', textAlign: 'center', fontSize: 12 }}>
                      {loading ? 'A carregar…' : 'Sem registos — sync genérico ainda não executou (foco nos snapshots VP e Top10).'}
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* Sync Log */}
      <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, marginBottom: 24 }}>
        <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ fontSize: 13, fontWeight: 600 }}>Log de Sync Recente</span>
          <span style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>primavera._sync_log · últimos 40</span>
        </div>
        <div style={{ overflowX: 'auto', maxHeight: 360, overflowY: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
            <thead>
              <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--bg)' }}>
                {['INÍCIO', 'GRUPO', 'TABELA', 'ROWS', 'DUR.', 'ESTADO', 'ERRO'].map(h => (
                  <th key={h} style={{ padding: '6px 10px', textAlign: h === 'ROWS' ? 'right' : 'left', fontWeight: 500, color: 'var(--text-dim)', fontSize: 11, fontFamily: 'var(--font-mono)', whiteSpace: 'nowrap' }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {data?.sync_log?.length ? data.sync_log.map((row, i) => (
                <tr key={row.id} style={{ borderBottom: '1px solid var(--border)', background: row.status === 'error' ? 'rgba(239,68,68,0.05)' : i % 2 !== 0 ? 'var(--bg)' : 'transparent' }}>
                  <td style={{ padding: '4px 10px', fontFamily: 'var(--font-mono)', fontSize: 11, whiteSpace: 'nowrap' }}>{fmtDt(row.started_at)}</td>
                  <td style={{ padding: '4px 10px', whiteSpace: 'nowrap' }}><GroupBadge group={row.group_name} /></td>
                  <td style={{ padding: '4px 10px', fontFamily: 'var(--font-mono)', fontSize: 11 }}>{row.table_name}</td>
                  <td style={{ padding: '4px 10px', textAlign: 'right', fontFamily: 'var(--font-mono)' }}>{fmtN(row.rows_synced)}</td>
                  <td style={{ padding: '4px 10px', fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', whiteSpace: 'nowrap' }}>{fmtDur(row.duration_ms)}</td>
                  <td style={{ padding: '4px 10px', whiteSpace: 'nowrap' }}><StatusPill status={row.status} /></td>
                  <td style={{ padding: '4px 10px', color: '#ef4444', fontSize: 11, maxWidth: 240, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={row.error_msg || ''}>{row.error_msg || ''}</td>
                </tr>
              )) : (
                <tr>
                  <td colSpan={7} style={{ padding: '24px 10px', color: 'var(--text-dim)', textAlign: 'center', fontSize: 12 }}>
                    {loading ? 'A carregar…' : 'Sem logs de sync — sync genérico ainda não executou.'}
                  </td>
                </tr>
              )}
            </tbody>
          </table>
        </div>
      </div>

    </div>
  );
};

window.SistemaPrimavera = SistemaPrimavera;
