const API = '/api';

async function api(path, options = {}) {
  const res = await fetch(`${API}${path}`, {
    headers: { 'Content-Type': 'application/json', ...(options.headers || {}) },
    ...options,
  });
  if (!res.ok) throw new Error(`${res.status} ${path}`);
  return res.json();
}

function fmtDate(iso) {
  if (!iso) return '—';
  try {
    return new Date(iso).toLocaleString('pt-PT', { dateStyle: 'short', timeStyle: 'short' });
  } catch {
    return iso;
  }
}

function esc(s) {
  return String(s ?? '')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

let state = {
  view: 'dashboard',
  ticketFilter: 'all',
  sourceFilter: 'all',
  eventSourceFilter: 'all',
  selectedTicketId: null,
  tickets: [],
  summary: null,
  scorecardTenant: null,
  scorecardDomain: null,
};

const views = {
  dashboard: document.getElementById('view-dashboard'),
  overview: document.getElementById('view-overview'),
  tickets: document.getElementById('view-tickets'),
  events: document.getElementById('view-events'),
  tenants: document.getElementById('view-tenants'),
  infra: document.getElementById('view-infra'),
};

function setView(name) {
  state.view = name;
  const titles = {
    dashboard: 'Dashboard',
    overview: 'Audit Overview',
    tickets: 'Tickets',
    events: 'Eventos webhook',
    tenants: 'Tenants',
    infra: 'Infraestrutura',
  };
  document.getElementById('page-title').textContent = titles[name] || 'Ligbox Ops';
  document.querySelectorAll('.nav button').forEach((b) => {
    b.classList.toggle('active', b.dataset.view === name);
  });
  Object.entries(views).forEach(([k, el]) => el?.classList.toggle('active', k === name));
  refresh();
}

async function loadHealth() {
  const el = document.getElementById('global-health');
  try {
    const h = await api('/health');
    el.className = 'status-pill ok';
    el.innerHTML = '<span class="dot"></span> API online';
    return h;
  } catch {
    el.className = 'status-pill err';
    el.innerHTML = '<span class="dot"></span> API offline';
    return null;
  }
}

async function renderDashboard() {
  const box = document.getElementById('dashboard-content');
  box.innerHTML = '<p class="loading">A carregar…</p>';
  try {
    const [summary, funnel, audit, vm112, wazuh] = await Promise.all([
      api('/v1/desk/summary'),
      api('/v1/onboard/funnel').catch(() => ({ stages: {}, active_sessions: [], sessions_total: 0 })),
      api('/v1/audit/overview').catch(() => ({ tenants: [] })),
      api('/v1/infra/vm112/status').catch(() => ({ error: 'indisponível' })),
      api('/v1/infra/wazuh/status').catch(() => ({ error: 'indisponível' })),
    ]);
    state.summary = summary;
    const vmOk = vm112.vm112?.status === 'ok';
    const wazuhOk = wazuh.http_status === 401 || wazuh.http_status === 200;
    const sessions = funnel.active_sessions || [];
    const sessionRows = sessions.slice(0, 8).map((s) => `
      <div class="funnel-session ${s.stale ? 'stale' : ''}">
        <div>
          <strong>${esc(s.domain || '—')}</strong>
          <div class="ticket-meta"><code>${esc((s.session_id || '').slice(0, 12))}</code> · ${esc(FUNNEL_LABELS[s.current_stage] || s.current_stage)}</div>
        </div>
        <div>${s.stale ? '<span class="badge review">inactivo</span>' : ''}${s.ticket_id ? `<span class="badge open">#${s.ticket_id}</span>` : ''}</div>
      </div>`).join('');
    const auditCards = (audit.tenants || []).map((t) => `
      <div class="health-card health-${esc(t.status)}">
        <div class="health-card-head">
          <strong>${esc(t.name)}</strong>
          ${healthBadge(t.status)}
        </div>
        <div class="health-score">${t.score?.pass ?? 0}/${t.score?.total ?? 8} checks OK</div>
        <div class="ticket-meta">${t.domains_count || 0} domínio(s) · ${fmtDate(t.last_audit_at)}</div>
      </div>`).join('');
    box.innerHTML = `
      <div class="stats">
        <div class="stat"><label>Abertos</label><strong>${summary.tickets_open}</strong></div>
        <div class="stat"><label>Fechados</label><strong>${summary.tickets_closed}</strong></div>
        <div class="stat"><label>Sessões funil</label><strong>${funnel.sessions_total || 0}</strong></div>
        <div class="stat"><label>Eventos</label><strong>${summary.webhook_events}</strong></div>
      </div>
      ${auditCards ? `<div class="health-grid" style="margin-bottom:1rem">${auditCards}</div>` : ''}
      <div class="grid-2">
        <div class="card">
          <h3>Funil onboarding <span class="ticket-meta">48h</span></h3>
          ${funnelBarHtml(funnel.stages || {}, funnel.sessions_total || 0)}
          ${sessionRows ? `<h4 style="margin:1rem 0 0.5rem;font-size:0.85rem">Sessões activas</h4><div class="funnel-sessions">${sessionRows}</div>` : '<p class="loading" style="margin-top:1rem">Sem sessões recentes</p>'}
        </div>
        <div class="card">
          <h3>Tickets recentes</h3>
          <div class="ticket-list">
            ${(summary.recent_tickets || []).map(ticketRowHtml).join('') || '<p class="loading">Sem tickets</p>'}
          </div>
        </div>
      </div>
      <div class="card" style="margin-top:1rem">
        <h3>Infra</h3>
        <div class="grid-2" style="gap:0.75rem">
          <div class="infra-card">
            <div><strong>VM112 Portal</strong><p class="ticket-meta">${vm112.vm112?.service || vm112.error || '—'}</p></div>
            <span class="badge ${vmOk ? 'ok' : 'review'}">${vmOk ? 'online' : 'check'}</span>
          </div>
          <div class="infra-card">
            <div><strong>VM104 Wazuh</strong><p class="ticket-meta">API ${wazuh.http_status ?? '—'}</p></div>
            <span class="badge ${wazuhOk ? 'ok' : 'review'}">${wazuhOk ? 'online' : 'check'}</span>
          </div>
        </div>
      </div>`;
    box.querySelectorAll('.ticket-row').forEach((btn) => {
      btn.addEventListener('click', () => {
        state.selectedTicketId = Number(btn.dataset.id);
        setView('tickets');
      });
    });
  } catch (e) {
    box.innerHTML = `<p class="loading">Erro: ${esc(e.message)}</p>`;
  }
}

function sourceBadge(src) {
  if (src === 'wazuh') return '<span class="badge wazuh">wazuh</span>';
  if (src === 'vm112-onboard') return '<span class="badge onboard">onboard</span>';
  return src ? `<span class="badge">${esc(src)}</span>` : '';
}

function severityBadge(level) {
  if (level == null) return '';
  const n = Number(level);
  let cls = 'sev-low';
  if (n >= 12) cls = 'sev-critical';
  else if (n >= 10) cls = 'sev-high';
  else if (n >= 7) cls = 'sev-med';
  return `<span class="badge ${cls}">L${n}</span>`;
}

const FUNNEL_LABELS = {
  started: 'Iniciado',
  domain_validated: 'Domínio OK',
  dns_applied: 'DNS aplicado',
  account_created: 'Conta criada',
  infra_synced: 'Infra sync',
  completed: 'Concluído',
  failed: 'Falhou',
};

function funnelBarHtml(stages, total) {
  const order = ['started', 'domain_validated', 'dns_applied', 'account_created', 'infra_synced', 'completed', 'failed'];
  const max = Math.max(total || 1, ...order.map((k) => stages[k] || 0));
  return order
    .filter((k) => k !== 'failed' || (stages.failed || 0) > 0)
    .map((key) => {
      const n = stages[key] || 0;
      const pct = max ? Math.round((n / max) * 100) : 0;
      return `
        <div class="funnel-row">
          <span class="funnel-label">${FUNNEL_LABELS[key] || key}</span>
          <div class="funnel-bar"><div class="funnel-fill" style="width:${pct}%"></div></div>
          <strong class="funnel-count">${n}</strong>
        </div>`;
    })
    .join('');
}

function timelineHtml(events) {
  if (!events?.length) return '';
  return `<ol class="timeline">${events
    .map(
      (e) => `
      <li class="timeline-item">
        <span class="timeline-dot"></span>
        <div>
          <strong>${esc(e.event_type)}</strong>
          ${e.stage ? `<span class="badge open">${esc(e.stage)}</span>` : ''}
          <div class="ticket-meta">${fmtDate(e.created_at)}</div>
        </div>
      </li>`
    )
    .join('')}</ol>`;
}

function healthBadge(status) {
  const map = { healthy: 'ok', degraded: 'review', critical: 'closed', unknown: 'open' };
  const cls = map[status] || 'open';
  return `<span class="badge ${cls} health-${esc(status)}">${esc(status || 'unknown')}</span>`;
}

function checkStatusBadge(status) {
  const cls = { pass: 'ok', warn: 'review', fail: 'closed', error: 'closed', skip: 'open' }[status] || 'open';
  return `<span class="badge ${cls}">${esc(status)}</span>`;
}

function ticketRowHtml(t) {
  const review = t.needs_review ? '<span class="badge review">revisão</span>' : '';
  const verified = t.account_verified ? '<span class="badge ok">verificado</span>' : '';
  const sub = t.event === 'wazuh.alert'
    ? esc(t.description || t.subject)
    : esc(t.domain || t.subject);
  const meta = t.event === 'wazuh.alert'
    ? `${esc(t.agent || t.domain || '')} · ${fmtDate(t.created_at)}`
    : `${esc(t.email || '')} · ${fmtDate(t.created_at)}`;
  return `
    <button type="button" class="ticket-row ${state.selectedTicketId === t.id ? 'selected' : ''}" data-id="${t.id}">
      <span class="badge ${t.status}">${esc(t.status)}</span>
      <div>
        <div class="ticket-subject">${sub}</div>
        <div class="ticket-meta">${meta}</div>
      </div>
      <div>${sourceBadge(t.source)}${severityBadge(t.severity)}${review}${verified}</div>
    </button>`;
}

async function renderOverview() {
  const el = document.getElementById('overview-content');
  const panel = document.getElementById('scorecard-panel');
  el.innerHTML = '<p class="loading">A carregar overview…</p>';
  try {
    const data = await api('/v1/audit/overview');
    const cards = (data.tenants || []).map((t) => {
      const issues = (t.top_issues || [])
        .slice(0, 3)
        .map((i) => `<li><code>${esc(i.domain)}</code> · ${esc(i.check_id)} — ${esc(i.message || i.status)}</li>`)
        .join('');
      const domains = [...new Set((t.top_issues || []).map((i) => i.domain).filter(Boolean))];
      const domainBtns = domains.map((d) =>
        `<button type="button" class="btn btn-ghost btn-sm" data-tenant="${t.tenant_id}" data-domain="${esc(d)}">${esc(d)}</button>`
      ).join(' ');
      return `
        <div class="card health-card health-${esc(t.status)}">
          <div class="health-card-head">
            <div>
              <h3 style="margin:0">${esc(t.name)}</h3>
              <p class="ticket-meta">${esc(t.ip)} · ${t.domains_count || 0} domínio(s)</p>
            </div>
            ${healthBadge(t.status)}
          </div>
          <div class="health-score">${t.score?.pass ?? 0}/${t.score?.total ?? 8} pass · ${t.score?.warn ?? 0} warn · ${t.score?.fail ?? 0} fail</div>
          <p class="ticket-meta">Último audit: ${fmtDate(t.last_audit_at)}</p>
          ${issues ? `<ul class="issue-list">${issues}</ul>` : '<p class="loading">Sem issues ou aguardar 1.º ciclo audit</p>'}
          <div class="actions" style="margin-top:0.75rem">${domainBtns || `<button type="button" class="btn btn-ghost btn-sm" data-run-audit="${t.tenant_id}">Correr audit cycle</button>`}</div>
        </div>`;
    }).join('');
    el.innerHTML = cards
      ? `<div class="health-grid">${cards}</div>`
      : '<p class="loading">Nenhum tenant auditado. Complete onboarding ou POST /audit/cycle.</p>';
    el.querySelectorAll('[data-domain]').forEach((btn) => {
      btn.addEventListener('click', () => loadScorecard(Number(btn.dataset.tenant), btn.dataset.domain));
    });
    el.querySelectorAll('[data-run-audit]').forEach((btn) => {
      btn.addEventListener('click', async () => {
        btn.disabled = true;
        try {
          await api('/v1/audit/cycle', { method: 'POST' });
          await renderOverview();
        } finally {
          btn.disabled = false;
        }
      });
    });
    if (state.scorecardTenant && state.scorecardDomain) {
      await loadScorecard(state.scorecardTenant, state.scorecardDomain, panel);
    } else {
      panel.style.display = 'none';
    }
  } catch (e) {
    el.innerHTML = `<p class="loading">Erro: ${esc(e.message)}</p>`;
    panel.style.display = 'none';
  }
}

async function loadScorecard(tenantId, domain, panelEl) {
  const panel = panelEl || document.getElementById('scorecard-panel');
  panel.style.display = 'block';
  state.scorecardTenant = tenantId;
  state.scorecardDomain = domain;
  panel.innerHTML = '<p class="loading">A carregar scorecard…</p>';
  try {
    const sc = await api(`/v1/audit/tenants/${tenantId}/scorecard?domain=${encodeURIComponent(domain)}`);
    const rows = (sc.checks || []).map((c) => `
      <tr>
        <td>${esc(c.label || c.check_id)}</td>
        <td>${checkStatusBadge(c.status)}</td>
        <td>${esc(c.message || '—')}</td>
        <td>${fmtDate(c.checked_at)}</td>
      </tr>`).join('');
    panel.innerHTML = `
      <div class="health-card-head">
        <h3 style="margin:0">Scorecard — ${esc(domain)}</h3>
        ${healthBadge(sc.overall_status)}
      </div>
      <p class="ticket-meta">Tenant #${tenantId} · ${fmtDate(sc.checked_at)}</p>
      <div class="table-wrap" style="margin-top:0.75rem">
        <table>
          <thead><tr><th>Check</th><th>Status</th><th>Mensagem</th><th>Verificado</th></tr></thead>
          <tbody>${rows || '<tr><td colspan="4">Sem checks</td></tr>'}</tbody>
        </table>
      </div>`;
  } catch (e) {
    panel.innerHTML = `<p class="loading">Erro scorecard: ${esc(e.message)}</p>`;
  }
}

async function renderTickets() {
  const listEl = document.getElementById('ticket-list');
  const detailEl = document.getElementById('ticket-detail');
  listEl.innerHTML = '<p class="loading">A carregar tickets…</p>';
  try {
    let q = '';
    const params = [];
    if (state.ticketFilter !== 'all') params.push(`status=${state.ticketFilter}`);
    if (state.sourceFilter !== 'all') params.push(`source=${state.sourceFilter}`);
    if (params.length) q = '?' + params.join('&');
    const data = await api(`/v1/desk/tickets${q}`);
    state.tickets = data.tickets || [];
    listEl.innerHTML = state.tickets.length
      ? state.tickets.map(ticketRowHtml).join('')
      : '<p class="loading">Nenhum ticket neste filtro</p>';
    listEl.querySelectorAll('.ticket-row').forEach((btn) => {
      btn.addEventListener('click', () => {
        state.selectedTicketId = Number(btn.dataset.id);
        renderTicketDetail();
        listEl.querySelectorAll('.ticket-row').forEach((r) => r.classList.remove('selected'));
        btn.classList.add('selected');
      });
    });
    if (state.selectedTicketId) await renderTicketDetail();
    else detailEl.innerHTML = '<div class="card detail-panel"><p class="empty">Seleccione um ticket</p></div>';
  } catch (e) {
    listEl.innerHTML = `<p class="loading">Erro: ${esc(e.message)}</p>`;
  }
}

async function renderTicketDetail() {
  const detailEl = document.getElementById('ticket-detail');
  if (!state.selectedTicketId) return;
  detailEl.innerHTML = '<div class="card detail-panel"><p class="loading">A carregar…</p></div>';
  try {
    const t = await api(`/v1/desk/tickets/${state.selectedTicketId}`);
    const timeline = t.timeline || t.related_events || [];
    detailEl.innerHTML = `
      <div class="card detail-panel">
        <div style="display:flex;justify-content:space-between;align-items:flex-start;gap:0.5rem;flex-wrap:wrap">
          <h3 style="margin:0">Ticket #${t.id}</h3>
          <span class="badge ${t.status}">${esc(t.status)}</span>
        </div>
        <dl class="kv">
          <dt>Origem</dt><dd>${sourceBadge(t.source)}</dd>
          <dt>Domínio/Agente</dt><dd>${esc(t.domain || t.agent || '—')}</dd>
          <dt>Email</dt><dd>${esc(t.email || '—')}</dd>
          <dt>Evento</dt><dd>${esc(t.event || '—')}</dd>
          ${t.ready_for_ops ? '<dt>Ops</dt><dd><span class="badge ok">ready for ops</span></dd>' : ''}
          ${t.severity != null ? `<dt>Severidade</dt><dd>${severityBadge(t.severity)}</dd>` : ''}
          ${t.rule_id ? `<dt>Regra</dt><dd>${esc(t.rule_id)}</dd>` : ''}
          ${t.description ? `<dt>Descrição</dt><dd>${esc(t.description)}</dd>` : ''}
          ${t.billing_state ? `<dt>Billing</dt><dd><span class="badge warn">${esc(t.billing_state)}</span></dd>` : ''}
          ${t.webmail_released != null ? `<dt>Webmail</dt><dd>${t.webmail_released ? 'Liberado' : 'Pendente'}</dd>` : ''}
          <dt>${t.source === 'wazuh' ? 'Alert ID' : 'Sessão onboarding'}</dt><dd><code>${esc(t.session_id || '—')}</code></dd>
          <dt>Verificado</dt><dd>${t.account_verified ? 'Sim' : 'Não'}</dd>
          <dt>Revisão</dt><dd>${t.needs_review ? 'Necessária' : 'Não'}</dd>
          <dt>Criado</dt><dd>${fmtDate(t.created_at)}</dd>
        </dl>
        <div class="actions">
          ${t.status === 'open'
            ? `<button type="button" class="btn btn-primary" data-action="close">Fechar ticket</button>`
            : `<button type="button" class="btn btn-ghost" data-action="open">Reabrir ticket</button>`}
        </div>
        ${timeline.length ? `<h3 style="margin-top:1.25rem">Timeline onboarding</h3>${timelineHtml(timeline)}` : ''}
        <h3 style="margin-top:1.25rem">Payload</h3>
        <pre class="raw">${esc(JSON.stringify(t.payload, null, 2))}</pre>
      </div>`;
    detailEl.querySelector('[data-action="close"]')?.addEventListener('click', () => updateTicketStatus('closed'));
    detailEl.querySelector('[data-action="open"]')?.addEventListener('click', () => updateTicketStatus('open'));
  } catch (e) {
    detailEl.innerHTML = `<div class="card"><p class="loading">Erro: ${esc(e.message)}</p></div>`;
  }
}

async function updateTicketStatus(status) {
  await api(`/v1/desk/tickets/${state.selectedTicketId}`, {
    method: 'PATCH',
    body: JSON.stringify({ status }),
  });
  await renderTickets();
}

async function renderEvents() {
  const el = document.getElementById('events-content');
  el.innerHTML = '<p class="loading">A carregar eventos…</p>';
  try {
    const srcQ = state.eventSourceFilter !== 'all' ? `?source=${state.eventSourceFilter}` : '';
    const data = await api(`/v1/webhooks/events${srcQ}`);
    const rows = (data.events || []).map((e) => {
      const p = e.payload || {};
      const dataObj = p.data || {};
      return `<tr>
        <td>${e.id}</td>
        <td>${sourceBadge(e.source)}</td>
        <td><span class="badge open">${esc(e.event_type)}</span> ${severityBadge(dataObj.level || e.severity)}</td>
        <td>${esc(p.domain || '—')}</td>
        <td><code>${esc((p.session_id || '').slice(0, 16))}</code></td>
        <td>${fmtDate(e.created_at)}</td>
      </tr>`;
    }).join('');
    el.innerHTML = `
      <div class="card table-wrap">
        <table>
          <thead><tr><th>ID</th><th>Origem</th><th>Evento</th><th>Agente/Domínio</th><th>Ref</th><th>Data</th></tr></thead>
          <tbody>${rows || '<tr><td colspan="6">Sem eventos</td></tr>'}</tbody>
        </table>
      </div>`;
  } catch (e) {
    el.innerHTML = `<p class="loading">Erro: ${esc(e.message)}</p>`;
  }
}

async function renderTenants() {
  const el = document.getElementById('tenants-content');
  el.innerHTML = '<p class="loading">A carregar…</p>';
  try {
    const data = await api('/v1/tenants');
    el.innerHTML = `
      <div class="card table-wrap">
        <table>
          <thead><tr><th>ID</th><th>Nome</th><th>IP</th><th>Papel</th><th>Desde</th></tr></thead>
          <tbody>${(data.tenants || []).map((t) => `
            <tr>
              <td>${t.id}</td>
              <td>${esc(t.name)}</td>
              <td><code>${esc(t.ip)}</code></td>
              <td>${esc(t.role)}</td>
              <td>${fmtDate(t.created_at)}</td>
            </tr>`).join('')}
          </tbody>
        </table>
      </div>`;
  } catch (e) {
    el.innerHTML = `<p class="loading">Erro: ${esc(e.message)}</p>`;
  }
}

async function renderInfra() {
  const el = document.getElementById('infra-content');
  el.innerHTML = '<p class="loading">A verificar…</p>';
  try {
    const [vm112, wazuh, integrations] = await Promise.all([
      api('/v1/infra/vm112/status'),
      api('/v1/infra/wazuh/status'),
      api('/v1/integrations'),
    ]);
    el.innerHTML = `
      <div class="card">
        <h3>VM112 — Portal Onboard</h3>
        <dl class="kv">
          <dt>HTTP</dt><dd>${vm112.http_status ?? '—'}</dd>
          <dt>Service</dt><dd>${esc(vm112.vm112?.service || vm112.error || '—')}</dd>
        </dl>
      </div>
      <div class="card">
        <h3>VM104 — Wazuh SOC</h3>
        <dl class="kv">
          <dt>API</dt><dd>${wazuh.http_status ?? '—'}</dd>
          <dt>Integração</dt><dd>webhook level ≥ 10 → VM122</dd>
        </dl>
      </div>
      <div class="card">
        <h3>Integrações activas</h3>
        <pre class="raw">${esc(JSON.stringify(integrations, null, 2))}</pre>
      </div>`;
  } catch (e) {
    el.innerHTML = `<p class="loading">Erro: ${esc(e.message)}</p>`;
  }
}

async function refresh() {
  await loadHealth();
  if (state.view === 'dashboard') await renderDashboard();
  if (state.view === 'overview') await renderOverview();
  if (state.view === 'tickets') await renderTickets();
  if (state.view === 'events') await renderEvents();
  if (state.view === 'tenants') await renderTenants();
  if (state.view === 'infra') await renderInfra();
}

document.querySelectorAll('.nav button').forEach((btn) => {
  btn.addEventListener('click', () => setView(btn.dataset.view));
});

document.querySelectorAll('.filter-btn[data-filter]').forEach((btn) => {
  btn.addEventListener('click', () => {
    state.ticketFilter = btn.dataset.filter;
    document.querySelectorAll('.filter-btn[data-filter]').forEach((b) => b.classList.toggle('active', b === btn));
    renderTickets();
  });
});

document.querySelectorAll('.filter-btn[data-source]').forEach((btn) => {
  btn.addEventListener('click', () => {
    const kind = btn.dataset.kind || 'ticket';
    if (kind === 'event') {
      state.eventSourceFilter = btn.dataset.source;
      document.querySelectorAll('.filter-btn[data-kind="event"]').forEach((b) => b.classList.toggle('active', b === btn));
      renderEvents();
    } else {
      state.sourceFilter = btn.dataset.source;
      document.querySelectorAll('.filter-btn[data-kind="ticket"]').forEach((b) => b.classList.toggle('active', b === btn));
      renderTickets();
    }
  });
});

document.getElementById('btn-refresh')?.addEventListener('click', refresh);

setView('dashboard');
setInterval(refresh, 30000);
