// ========== SECURITY CENTER ==========
// Multi-source security event viewer + host registry UI.
//
// Shows live events from any source (API audit, Caddy access log, fail2ban,
// shared_bans) on any registered host (this DashCaddy, future remote agents).
//
// Live-tail uses SSE (/api/v1/security/events/stream).
(function() {
  injectModal('security-modal', `<div id="security-modal" class="weather-modal">
    <div class="weather-modal-content" style="min-width: 980px; max-width: 1280px;">
      <h3>🛡️ Security Center</h3>
      <p class="modal-subtitle">
        Live events from API, Caddy, fail2ban & shared_bans. Live-tail via SSE.
      </p>

      <div class="sec-tabs" style="display:flex;gap:8px;margin-bottom:14px;border-bottom:1px solid var(--border);">
        <button class="sec-tab active" data-tab="overview">Overview</button>
        <button class="sec-tab" data-tab="events">Events</button>
        <button class="sec-tab" data-tab="hosts">Hosts</button>
      </div>

      <!-- OVERVIEW TAB -->
      <div class="sec-panel" data-panel="overview">
        <div class="sec-stats" id="sec-stats" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:18px;">
          <div class="sec-stat" data-key="total">— events</div>
          <div class="sec-stat" data-key="warn">— warnings</div>
          <div class="sec-stat" data-key="error">— errors</div>
          <div class="sec-stat" data-key="denied">— denied</div>
          <div class="sec-stat" data-key="hosts">— hosts</div>
        </div>
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
          <div>
            <h4 style="margin:8px 0 6px;">Top Actors (24h)</h4>
            <div id="sec-top-actors" class="scroll-container" style="max-height:240px;">—</div>
          </div>
          <div>
            <h4 style="margin:8px 0 6px;">Top Targets (24h)</h4>
            <div id="sec-top-targets" class="scroll-container" style="max-height:240px;">—</div>
          </div>
        </div>
      </div>

      <!-- EVENTS TAB -->
      <div class="sec-panel" data-panel="events" style="display:none;">
        <div style="display:flex;gap:8px;margin-bottom:12px;align-items:center;flex-wrap:wrap;">
          <select id="sec-filter-source" class="sec-filter">
            <option value="">All sources</option>
            <option value="api">API</option>
            <option value="caddy">Caddy</option>
            <option value="fail2ban">fail2ban</option>
            <option value="shared-bans">shared_bans</option>
            <option value="agent">Agent</option>
          </select>
          <select id="sec-filter-severity" class="sec-filter">
            <option value="">All severities</option>
            <option value="critical">critical</option>
            <option value="error">error</option>
            <option value="warn">warn</option>
            <option value="notice">notice</option>
            <option value="info">info</option>
          </select>
          <select id="sec-filter-host" class="sec-filter">
            <option value="">All hosts</option>
          </select>
          <input id="sec-filter-actor" class="sec-filter" placeholder="actor (IP or user)" style="padding:6px 10px;">
          <button id="sec-refresh-btn" class="btn-sm">🔄 Refresh</button>
          <label style="margin-left:auto;display:flex;align-items:center;gap:6px;">
            <input type="checkbox" id="sec-live-tail" checked>
            <span>Live tail</span>
          </label>
        </div>
        <div id="sec-events-container" class="scroll-container" style="max-height:480px;">Loading…</div>
      </div>

      <!-- HOSTS TAB -->
      <div class="sec-panel" data-panel="hosts" style="display:none;">
        <div style="display:flex;gap:8px;margin-bottom:12px;">
          <button id="sec-host-register-btn" class="btn-sm">➕ Register Host</button>
          <button id="sec-hosts-refresh" class="btn-sm">🔄 Refresh</button>
        </div>
        <div id="sec-hosts-container" class="scroll-container" style="max-height:480px;">Loading…</div>
      </div>

      <div class="weather-modal-buttons modal-footer-bar">
        <button id="sec-cancel">Close</button>
      </div>
    </div>
  </div>`);

  // ============= STATE =============
  const modal = document.getElementById('security-modal');
  const openBtn = document.getElementById('security-center-btn');
  const cancelBtn = document.getElementById('sec-cancel');
  const tabs = modal.querySelectorAll('.sec-tab');
  const panels = modal.querySelectorAll('.sec-panel');

  let allEvents = []; // newest first
  let allHosts = [];
  let sseSource = null;

  // ============= TAB SWITCHING =============
  tabs.forEach(tab => {
    tab.addEventListener('click', () => {
      tabs.forEach(t => t.classList.toggle('active', t === tab));
      panels.forEach(p => p.style.display = p.dataset.panel === tab.dataset.tab ? '' : 'none');
      if (tab.dataset.tab === 'overview') refreshOverview();
      if (tab.dataset.tab === 'events') refreshEvents();
      if (tab.dataset.tab === 'hosts') refreshHosts();
    });
  });

  // ============= OPEN/CLOSE =============
  if (openBtn) {
    openBtn.addEventListener('click', () => {
      modal.classList.add('show');
      refreshOverview();
      startLiveTail();
    });
  }
  cancelBtn.addEventListener('click', closeModal);
  modal.addEventListener('click', e => { if (e.target === modal) closeModal(); });
  function closeModal() {
    modal.classList.remove('show');
    stopLiveTail();
  }

  // ============= LIVE TAIL (SSE) =============
  function startLiveTail() {
    stopLiveTail();
    if (!document.getElementById('sec-live-tail').checked) return;
    if (typeof EventSource === 'undefined') return; // browser doesn't support
    try {
      sseSource = new EventSource('/api/v1/security/events/stream');
      sseSource.addEventListener('init', (e) => {
        try {
          const data = JSON.parse(e.data);
          allEvents = data.events || [];
          renderEvents();
        } catch {}
      });
      sseSource.addEventListener('security', (e) => {
        try {
          const ev = JSON.parse(e.data);
          allEvents.unshift(ev);
          if (allEvents.length > 500) allEvents.length = 500;
          // Auto-refresh whichever panel is showing
          const active = modal.querySelector('.sec-tab.active')?.dataset?.tab;
          if (active === 'events') renderEvents();
          else if (active === 'overview') refreshOverview();
        } catch {}
      });
      sseSource.onerror = () => { /* browser auto-reconnects */ };
    } catch (e) {
      console.warn('[security] SSE failed:', e.message);
    }
  }
  function stopLiveTail() {
    if (sseSource) { try { sseSource.close(); } catch {} sseSource = null; }
  }
  document.getElementById('sec-live-tail').addEventListener('change', () => {
    if (modal.classList.contains('show')) startLiveTail();
  });

  // ============= OVERVIEW =============
  async function refreshOverview() {
    try {
      const since = new Date(Date.now() - 24*60*60*1000).toISOString();
      const [statsRes, hostsRes, eventsRes] = await Promise.all([
        fetch(`/api/v1/security/events/stats?since=${encodeURIComponent(since)}`),
        fetch('/api/v1/security/hosts'),
        fetch(`/api/v1/security/events?limit=1&since=${encodeURIComponent(since)}`),
      ]);
      const stats = (await statsRes.json()).data || {};
      const hosts = (await hostsRes.json()).data?.hosts || [];
      const eventsCount = (await eventsRes.json()).data?.total || 0;

      document.querySelector('#sec-stats [data-key="total"]').textContent = `${eventsCount} events (24h)`;
      document.querySelector('#sec-stats [data-key="warn"]').textContent = `${stats.by_severity?.warn || 0} warnings`;
      document.querySelector('#sec-stats [data-key="error"]').textContent = `${stats.by_severity?.error || 0} errors`;
      document.querySelector('#sec-stats [data-key="denied"]').textContent = `${stats.by_outcome?.denied || 0} denied`;
      document.querySelector('#sec-stats [data-key="hosts"]').textContent = `${hosts.length} hosts`;

      renderTopList('sec-top-actors', stats.top_actors || []);
      renderTopList('sec-top-targets', stats.top_targets || []);
    } catch (e) {
      console.warn('[security] refreshOverview failed:', e.message);
    }
  }
  function renderTopList(id, items) {
    const el = document.getElementById(id);
    if (!items.length) { el.innerHTML = '<div class="panel-empty">No data</div>'; return; }
    el.innerHTML = '<table style="width:100%;font-size:0.85rem;">' +
      items.map(it => `<tr><td style="padding:3px 0;word-break:break-all;">${escapeHtml(String(it.key))}</td><td style="text-align:right;color:var(--muted);">${it.count}</td></tr>`).join('') +
      '</table>';
  }

  // ============= EVENTS =============
  const filterSource = document.getElementById('sec-filter-source');
  const filterSeverity = document.getElementById('sec-filter-severity');
  const filterHost = document.getElementById('sec-filter-host');
  const filterActor = document.getElementById('sec-filter-actor');
  const refreshBtn = document.getElementById('sec-refresh-btn');

  [filterSource, filterSeverity, filterHost].forEach(el => el.addEventListener('change', refreshEvents));
  filterActor.addEventListener('input', debounce(refreshEvents, 250));
  refreshBtn.addEventListener('click', refreshEvents);

  async function refreshEvents() {
    try {
      const params = new URLSearchParams();
      params.set('limit', '200');
      if (filterSource.value)  params.set('source_type', filterSource.value);
      if (filterSeverity.value) params.set('severity', filterSeverity.value);
      if (filterHost.value)    params.set('source_host', filterHost.value);
      if (filterActor.value)   params.set('actor_prefix', filterActor.value);

      const res = await fetch(`/api/v1/security/events?${params}`);
      const data = (await res.json()).data;
      allEvents = data.events || [];
      renderEvents();

      // Refresh host dropdown if we don't have it yet
      if (!filterHost.options.length || filterHost.options.length === 1) {
        await refreshHostFilter();
      }
    } catch (e) {
      document.getElementById('sec-events-container').innerHTML = '<div class="panel-empty">Load failed: '+escapeHtml(e.message)+'</div>';
    }
  }

  function renderEvents() {
    const el = document.getElementById('sec-events-container');
    if (!allEvents.length) { el.innerHTML = '<div class="panel-empty">No events</div>'; return; }
    el.innerHTML = allEvents.slice(0, 200).map(renderEventRow).join('');
  }

  function renderEventRow(ev) {
    const sev = ev.severity || 'info';
    const sevColor = {
      critical: '#c0392b', error: '#e74c3c', warn: '#f39c12',
      notice: '#3498db', info: '#7f8c8d',
    }[sev] || '#7f8c8d';
    const time = ev.ts ? new Date(ev.ts).toLocaleTimeString() : '';
    const source = ev.source_type || '';
    const actor = ev.actor || '—';
    const target = ev.target || '';
    const action = ev.action || '';
    const outcome = ev.outcome || '';
    return `<div class="sec-event-row" style="display:grid;grid-template-columns:84px 80px 1fr 1fr 100px 90px;gap:8px;padding:5px 8px;border-bottom:1px solid var(--border);font-size:0.82rem;align-items:center;">
      <span style="color:${sevColor};font-weight:600;">${escapeHtml(sev)}</span>
      <span style="color:var(--muted);font-size:0.75rem;">${escapeHtml(source)}</span>
      <span title="${escapeHtml(actor)}" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${escapeHtml(actor)}</span>
      <span title="${escapeHtml(target)}" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${escapeHtml(action)} ${escapeHtml(target)}</span>
      <span style="color:var(--muted);font-size:0.75rem;">${escapeHtml(outcome)}</span>
      <span style="color:var(--muted);font-size:0.75rem;text-align:right;">${escapeHtml(time)}</span>
    </div>`;
  }

  async function refreshHostFilter() {
    try {
      const res = await fetch('/api/v1/security/hosts');
      const hosts = (await res.json()).data?.hosts || [];
      const current = filterHost.value;
      filterHost.innerHTML = '<option value="">All hosts</option>' +
        hosts.map(h => `<option value="${escapeHtml(h.id)}">${escapeHtml(h.label || h.id)}</option>`).join('');
      if (current) filterHost.value = current;
    } catch {}
  }

  // ============= HOSTS =============
  document.getElementById('sec-host-register-btn').addEventListener('click', registerHostPrompt);
  document.getElementById('sec-hosts-refresh').addEventListener('click', refreshHosts);

  async function refreshHosts() {
    try {
      const res = await fetch('/api/v1/security/hosts');
      const hosts = (await res.json()).data?.hosts || [];
      allHosts = hosts;
      const el = document.getElementById('sec-hosts-container');
      if (!hosts.length) { el.innerHTML = '<div class="panel-empty">No hosts registered. Click ➕ Register Host to add one.</div>'; return; }
      el.innerHTML = hosts.map(h => {
        const status = !h.enabled ? '🔴 disabled'
                     : !h.last_seen_at ? '⚪ registered'
                     : (Date.now() - Date.parse(h.last_seen_at) > 30*60*1000) ? '🟡 stale'
                     : '🟢 online';
        return `<div style="padding:10px 12px;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center;">
          <div>
            <strong>${escapeHtml(h.label || h.id)}</strong>
            <span style="color:var(--muted);margin-left:8px;font-size:0.8rem;">${escapeHtml(h.type)}</span>
            <div style="color:var(--muted);font-size:0.78rem;margin-top:2px;">
              id: ${escapeHtml(h.id)} ·
              registered ${new Date(h.registered_at).toLocaleDateString()} ·
              last seen ${h.last_seen_at ? new Date(h.last_seen_at).toLocaleString() : 'never'}
            </div>
          </div>
          <div>
            <span style="font-size:0.85rem;margin-right:12px;">${status}</span>
            ${h.id === 'self' ? '' : `<button class="btn-sm sec-host-del" data-id="${escapeHtml(h.id)}" style="color:var(--bad-fg);">Remove</button>`}
          </div>
        </div>`;
      }).join('');

      el.querySelectorAll('.sec-host-del').forEach(btn => {
        btn.addEventListener('click', async () => {
          if (!confirm(`Remove host ${btn.dataset.id}? Events already received will remain in the store.`)) return;
          await fetch(`/api/v1/security/hosts/${encodeURIComponent(btn.dataset.id)}`, { method: 'DELETE' });
          refreshHosts();
        });
      });
    } catch (e) {
      document.getElementById('sec-hosts-container').innerHTML = '<div class="panel-empty">Load failed: '+escapeHtml(e.message)+'</div>';
    }
  }

  async function registerHostPrompt() {
    const id = prompt('Host id (lowercase, no spaces):');
    if (!id) return;
    const label = prompt('Display label:', id) || id;
    const type  = prompt('Type ("dashcaddy", "service", or "agent"):', 'agent') || 'agent';
    try {
      const res = await fetch('/api/v1/security/hosts', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id, label, type }),
      });
      const data = await res.json();
      if (!res.ok) { alert('Failed: ' + (data?.error?.message || res.statusText)); return; }
      // Show the api_key ONCE in a dialog
      alert(`✅ Host registered!\n\nid: ${data.data.host.id}\nlabel: ${data.data.host.label}\ntype: ${data.data.host.type}\n\n🔑 API KEY (save this NOW — won't be shown again):\n\n${data.data.api_key}\n\nSend this key as: Authorization: Bearer <api_key>\nTo endpoint: POST /api/v1/security/events/ingest or /events/batch`);
      refreshHosts();
    } catch (e) {
      alert('Failed: ' + e.message);
    }
  }

  // ============= HELPERS =============
  function escapeHtml(s) {
    return String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
  }
  function debounce(fn, ms) {
    let t; return function() { clearTimeout(t); t = setTimeout(() => fn.apply(this, arguments), ms); };
  }
})();