/* SISTEMA · Ligação Primavera ES (Dimension) — Monitor VPN strongSwan → SQL Server → PostgreSQL
   Contrato esperado de GET /api/primavera-es/monitor (endpoints ainda por criar):
   {
     vpn:  { connected, ip, gateway, uptime_secs | uptime, last_connected },
     sql:  { ok, tested_at, views_accessible },
     sync: { last_complete_at, next_at, total_rows },
     sync_state: [{ table_name, rows_total, last_sync_at, status }],
     sync_log:   [{ id, started_at, group_name, table_name, rows_synced, duration_ms, status, error_msg }]
   }
   POST /api/primavera-es/vpn/connect | vpn/disconnect | force-sync → { ok: true } ou { error }
   Credenciais SQL não aparecem neste ficheiro. */


const VIEW_TO_PG_ES = {
  'V_Clientes': 'clientes',
  'V_Fornecedores': 'fornecedores',
  'V_CabecDoc': 'documentos',
  'LinhasDoc': 'documentos_linhas',
  'V_CabecCompras': 'compras',
  'V_INV_LinhasCompras': 'compras_linhas',
  'Artigo': 'artigos',
  'V_IAM_Familias': 'familias',
  'Vendedores': 'vendedores',
  'V_INV_ValoresActuaisStock': 'stock_actual',
  'V_INV_LinhasDoc': 'stock_movimentos',
  'V_IAM_Moedas': 'moedas',
  'V_Codigos': 'condicoes_pagamento',
  'V_Documentos': 'documentos_status',
  'V_HistoricoPendentesLiq': 'liquidacoes',
  'V_Movimentos': 'tesouraria_movimentos',
};

const ES_DIRECT_TABLES = new Set(['LinhasDoc', 'Artigo', 'Vendedores']);

const ES_VPN_IP = '172.16.0.130';
const ES_VPN_GATEWAY = 'azuregateway-...vpn.azure.com';
const ES_SQL_HOST = '10.0.0.5:55477';
const ES_SQL_DB = 'PRIDIGIDDS';
const ES_SQL_USER = 'DigiAI';

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

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

function fmtNEs(n) {
  if (n == null || n === '') return '—';
  const v = Number(n);
  if (!Number.isFinite(v)) return '—';
  return v.toLocaleString('pt-PT');
}

function fmtUptimeEs(vpn) {
  if (!vpn) return '—';
  if (typeof vpn.uptime === 'string' && vpn.uptime.trim()) return vpn.uptime;
  const secs = Number(vpn.uptime_secs);
  if (!Number.isFinite(secs) || secs < 0) return '—';
  const h = Math.floor(secs / 3600);
  const m = Math.floor((secs % 3600) / 60);
  if (h > 0) return h + 'h ' + m + 'min';
  return m + ' min';
}

function esFonteTipo(name) {
  if (ES_DIRECT_TABLES.has(name)) return 'tabela';
  if (VIEW_TO_PG_ES[name] || String(name || '').startsWith('V_')) return 'view';
  return 'tabela';
}

function GroupBadgeEs({ 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 StatusPillEs({ status }) {
  if (!status) return <span style={{ color: 'var(--text-dim)' }}>—</span>;
  const ok = status === '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>
  );
}

function TipoPillEs({ tipo }) {
  const tabela = tipo === 'tabela';
  return (
    <span style={{
      fontSize: 10, padding: '1px 6px', borderRadius: 3, fontFamily: 'var(--font-mono)', letterSpacing: '0.04em',
      background: tabela ? '#e0e7ff' : 'var(--bg)', color: tabela ? '#3730a3' : 'var(--text-muted)',
      border: tabela ? 'none' : '1px solid var(--border)',
    }}>
      {tipo}
    </span>
  );
}

async function readJsonEs(r) {
  const text = await r.text();
  try { return JSON.parse(text); } catch { return null; }
}

const SistemaPrimaveraES = () => {
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [busy, setBusy] = React.useState(null);
  const [actionMsg, setActionMsg] = 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-es/monitor');
      const body = await readJsonEs(r);
      if (!r.ok || !body || typeof body !== 'object' || (body.error && !body.vpn && !body.sql && !body.sync && !body.sync_state)) {
        setData(null);
        setError('Endpoint não disponível');
      } else {
        setData(body);
      }
    } catch (e) {
      setData(null);
      setError('Endpoint não disponível');
    } finally {
      setLoading(false);
    }
  }, []);

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

  const postAction = async (url, okText) => {
    setBusy(url);
    setActionMsg(null);
    try {
      const r = await fetch(url, { method: 'POST' });
      const body = await readJsonEs(r);
      if (!r.ok || !body || body.ok === false) {
        setActionMsg('Erro: ' + ((body && body.error) || 'Endpoint não disponível'));
      } else {
        setActionMsg(okText);
        load();
      }
    } catch (e) {
      setActionMsg('Erro: Endpoint não disponível');
    }
    setBusy(null);
    setTimeout(() => setActionMsg(null), 6000);
  };

  const vpn = data?.vpn || null;
  const sql = data?.sql || null;
  const sync = data?.sync || null;
  const connected = vpn ? vpn.connected === true || vpn.status === 'connected' : null;
  const syncState = Array.isArray(data?.sync_state) ? data.sync_state : [];
  const syncLog = Array.isArray(data?.sync_log) ? data.sync_log : [];
  const totalRows = sync?.total_rows != null
    ? sync.total_rows
    : (syncState.length ? syncState.reduce((s, row) => s + (Number(row.rows_total) || 0), 0) : null);

  const dot = connected == null ? 'var(--text-dim)' : connected ? '#22c55e' : '#ef4444';
  const vpnLabel = connected == null ? (loading ? '…' : '—') : connected ? 'CONNECTED' : 'DISCONNECTED';

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

      <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 ES</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' }}>
          {actionMsg && (
            <span style={{ fontSize: 12, color: actionMsg.startsWith('Erro') ? '#ef4444' : '#10b981' }}>{actionMsg}</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={() => postAction('/api/primavera-es/force-sync', 'Sync pedido.')} disabled={!!busy}>
            {busy === '/api/primavera-es/force-sync' ? 'A enviar…' : 'Forçar Sync'}
          </button>
        </div>
      </div>

      {error && (
        <div style={{ padding: '10px 14px', background: '#fee2e2', color: '#b91c1c', borderRadius: 6, marginBottom: 16, fontSize: 13 }}>
          Endpoint não disponível — o monitor mostra a ligação prevista. Os dados vivos aparecem quando /api/primavera-es/monitor existir.
        </div>
      )}

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12, marginBottom: 20 }}>

        <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: dot, display: 'inline-block' }} />
            <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', letterSpacing: '0.05em' }}>VPN · VPS STRONGSWAN</span>
          </div>
          <div style={{ fontSize: 24, fontWeight: 700, letterSpacing: '-0.5px', color: dot, marginBottom: 6 }}>{vpnLabel}</div>
          <div style={{ fontSize: 12, color: 'var(--text-muted)', lineHeight: 1.6 }}>
            IP VPN: <span style={{ fontFamily: 'var(--font-mono)' }}>{vpn?.ip || ES_VPN_IP}</span><br />
            Gateway: <span style={{ fontFamily: 'var(--font-mono)' }}>{vpn?.gateway || ES_VPN_GATEWAY}</span><br />
            Uptime da sessão: {fmtUptimeEs(vpn)}<br />
            Última ligação: {fmtDtEs(vpn?.last_connected)}
          </div>
          <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
            <button className="btn btn-sm btn-primary" onClick={() => postAction('/api/primavera-es/vpn/connect', 'Pedido para ligar a VPN enviado.')} disabled={!!busy || connected === true}>
              {busy === '/api/primavera-es/vpn/connect' ? 'A ligar…' : 'Ligar VPN'}
            </button>
            <button className="btn btn-sm" onClick={() => postAction('/api/primavera-es/vpn/disconnect', 'Pedido para desligar a VPN enviado.')} disabled={!!busy || connected === false}>
              {busy === '/api/primavera-es/vpn/disconnect' ? 'A desligar…' : 'Desligar VPN'}
            </button>
          </div>
          <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 10, fontFamily: 'var(--font-mono)', lineHeight: 1.5 }}>
            IKEv2 on-demand · azure-es<br />
            {ES_SQL_DB} → schema primavera_es
          </div>
        </div>

        <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 }}>SQL SERVER · {ES_SQL_DB}</div>
          <div style={{ fontSize: 12, color: 'var(--text-muted)', lineHeight: 1.7 }}>
            Host: <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text)' }}>{ES_SQL_HOST}</span><br />
            BD: <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text)' }}>{ES_SQL_DB}</span><br />
            User: <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text)' }}>{ES_SQL_USER}</span> <span style={{ color: 'var(--text-dim)' }}>(read-only)</span>
          </div>
          <div style={{ borderTop: '1px solid var(--border)', marginTop: 10, paddingTop: 10 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 3 }}>Último teste de ligação</div>
            {sql && typeof sql.ok === 'boolean' ? (
              <div style={{ fontSize: 13, fontWeight: 600, color: sql.ok ? '#16a34a' : '#dc2626' }}>
                {sql.ok ? 'OK' : 'FAIL'}
                <span style={{ fontWeight: 400, color: 'var(--text-dim)', marginLeft: 8 }}>{fmtDtEs(sql.tested_at)}</span>
              </div>
            ) : (
              <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>{loading ? '…' : '—'}</div>
            )}
            <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 8 }}>
              Views/tabelas acessíveis: <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text-muted)' }}>{sql?.views_accessible != null ? fmtNEs(sql.views_accessible) : (loading ? '…' : '—')}</span>
            </div>
          </div>
        </div>

        <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 }}>SYNC · primavera_es</div>
          <div style={{ marginBottom: 10 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 3 }}>Último sync completo</div>
            <div style={{ fontSize: 13, fontWeight: 600 }}>{sync?.last_complete_at ? fmtDtEs(sync.last_complete_at) : (loading ? '…' : '—')}</div>
          </div>
          <div style={{ borderTop: '1px solid var(--border)', paddingTop: 10, marginBottom: 10 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 3 }}>Próximo sync agendado</div>
            <div style={{ fontSize: 13, fontWeight: 600 }}>{sync?.next_at ? fmtDtEs(sync.next_at) : (loading ? '…' : '—')}</div>
          </div>
          <div style={{ borderTop: '1px solid var(--border)', paddingTop: 10 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 3 }}>Registos totais sincronizados</div>
            <div style={{ fontSize: 13, fontWeight: 600, fontFamily: 'var(--font-mono)' }}>{fmtNEs(totalRows)}</div>
          </div>
        </div>
      </div>

      <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_es._sync_state · {data ? syncState.length : (loading ? '…' : '0')}</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], ['FONTE ES', 'left', 10], ['TIPO', 'left', 10], ['ROWS', 'right', 10], ['ÚLTIMA SYNC', 'left', 16], ['ESTADO', 'left', 10]].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>
                {syncState.length ? [...syncState].sort((a, b) => (b.last_sync_at || '') > (a.last_sync_at || '') ? 1 : -1).map((row, i) => {
                  const fonte = row.table_name;
                  const pgName = VIEW_TO_PG_ES[fonte] || row.pg_name || fonte;
                  return (
                    <tr key={fonte || i} 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)' }}>{fonte}</td>
                      <td style={{ padding: '5px 10px' }}><TipoPillEs tipo={esFonteTipo(fonte)} /></td>
                      <td style={{ padding: '5px 10px', textAlign: 'right', fontFamily: 'var(--font-mono)' }}>{fmtNEs(row.rows_total)}</td>
                      <td style={{ padding: '5px 16px', color: 'var(--text-muted)' }}>{fmtDtEs(row.last_sync_at)}</td>
                      <td style={{ padding: '5px 10px' }}><StatusPillEs status={row.status} /></td>
                    </tr>
                  );
                }) : (
                  <tr>
                    <td colSpan={6} style={{ padding: '24px 16px', color: 'var(--text-dim)', textAlign: 'center', fontSize: 12 }}>
                      {loading ? 'A carregar…' : 'Sem registos — a sync ES ainda não correu.'}
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        )}
      </div>

      <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_es._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>
              {syncLog.length ? syncLog.map((row, i) => (
                <tr key={row.id != null ? row.id : i} 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' }}>{fmtDtEs(row.started_at)}</td>
                  <td style={{ padding: '4px 10px', whiteSpace: 'nowrap' }}>{row.group_name ? <GroupBadgeEs 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)' }}>{fmtNEs(row.rows_synced)}</td>
                  <td style={{ padding: '4px 10px', fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', whiteSpace: 'nowrap' }}>{fmtDurEs(row.duration_ms)}</td>
                  <td style={{ padding: '4px 10px', whiteSpace: 'nowrap' }}><StatusPillEs 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.'}
                  </td>
                </tr>
              )}
            </tbody>
          </table>
        </div>
      </div>

    </div>
  );
};

window.SistemaPrimaveraES = SistemaPrimaveraES;
