// ── Native Logs Viewer ────────────────────────────────────────────────
// Fetches logs via the Glass UI's gateway RPC and renders them natively.
// No iframe, no SPA proxy — direct gateway connection.

const LOGS_POLL_MS   = 3000;
const LOGS_LIMIT     = 500;
const LOGS_MAX_BYTES = 250000;

const LEVEL_COLORS = {
  TRACE: '#6b7280',
  DEBUG: '#8b5cf6',
  INFO:  '#60a5fa',
  WARN:  '#f59e0b',
  ERROR: '#ef4444',
  FATAL: '#dc2626',
};

const LEVEL_ORDER = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'];

let logsContainer = null;
let logsCursor    = null;
let logsTimer     = null;
let logsAutoFollow = true;
let logsLevelFilters = new Set(LEVEL_ORDER);
let logsFilterText = '';
let logsEntries = [];

function createLogsUI() {
  const overlay = document.querySelector('body > .page-overlay');
  const frame   = document.getElementById('page-overlay-frame');

  // Hide the iframe
  if (frame) frame.style.display = 'none';

  // Create or get native logs container
  let container = document.getElementById('native-logs-container');
  if (!container) {
    container = document.createElement('div');
    container.id = 'native-logs-container';
    container.innerHTML = `
      <div class="logs-toolbar">
        <div class="logs-filters">
          ${LEVEL_ORDER.map(l => `
            <label class="logs-level-toggle" data-level="${l}">
              <input type="checkbox" checked data-level="${l}">
              <span class="logs-level-badge" style="color:${LEVEL_COLORS[l]}">${l}</span>
            </label>
          `).join('')}
        </div>
        <div class="logs-search">
          <input type="text" id="logs-search-input" placeholder="Filter logs..." />
        </div>
        <div class="logs-actions">
          <label class="logs-auto-follow">
            <input type="checkbox" id="logs-auto-follow-cb" checked> Auto-follow
          </label>
          <button id="logs-export-btn" title="Export visible">Export</button>
        </div>
      </div>
      <div class="logs-scroll" id="logs-scroll">
        <div class="logs-entries" id="logs-entries"></div>
      </div>
    `;
    overlay.appendChild(container);

    // Wire up level filters
    container.querySelectorAll('.logs-level-toggle input').forEach(cb => {
      cb.addEventListener('change', () => {
        const level = cb.dataset.level;
        if (cb.checked) logsLevelFilters.add(level);
        else logsLevelFilters.delete(level);
        renderLogs();
      });
    });

    // Wire up search
    document.getElementById('logs-search-input').addEventListener('input', e => {
      logsFilterText = e.target.value.toLowerCase();
      renderLogs();
    });

    // Wire up auto-follow
    document.getElementById('logs-auto-follow-cb').addEventListener('change', e => {
      logsAutoFollow = e.target.checked;
      if (logsAutoFollow) scrollToBottom();
    });

    // Wire up export
    document.getElementById('logs-export-btn').addEventListener('click', () => {
      const visible = getVisibleEntries();
      const text = visible.map(e => e.raw).join('\n');
      const blob = new Blob([text], { type: 'text/plain' });
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = `symi-logs-${new Date().toISOString().slice(0,19)}.txt`;
      a.click();
    });
  }

  logsContainer = container;
  container.style.display = 'flex';
  return container;
}

function destroyLogsUI() {
  if (logsTimer) { clearInterval(logsTimer); logsTimer = null; }
  const container = document.getElementById('native-logs-container');
  if (container) container.style.display = 'none';
  const frame = document.getElementById('page-overlay-frame');
  if (frame) frame.style.display = '';
}

function parseLogLine(line) {
  try {
    const obj = JSON.parse(line);
    const level = obj._meta?.logLevelName || 'INFO';
    const time  = obj.time || obj._meta?.date || '';
    const msg   = obj['1'] || obj.msg || obj.message || '';
    const sub   = obj['0'] || '';
    return { level, time, msg, sub, raw: line, parsed: obj };
  } catch {
    // Plain text line
    return { level: 'INFO', time: '', msg: line, sub: '', raw: line, parsed: null };
  }
}

function getVisibleEntries() {
  return logsEntries.filter(e => {
    if (!logsLevelFilters.has(e.level)) return false;
    if (logsFilterText && !e.raw.toLowerCase().includes(logsFilterText)) return false;
    return true;
  });
}

function renderLogs() {
  const el = document.getElementById('logs-entries');
  if (!el) return;

  const visible = getVisibleEntries();
  const html = visible.map(e => {
    const color = LEVEL_COLORS[e.level] || '#999';
    const timeStr = e.time ? new Date(e.time).toLocaleTimeString() : '';
    const escapedMsg = escapeHtml(e.msg).substring(0, 500);
    const escapedSub = escapeHtml(e.sub);
    return `<div class="log-line">
      <span class="log-time">${timeStr}</span>
      <span class="log-level" style="color:${color}">${e.level.padEnd(5)}</span>
      ${escapedSub ? `<span class="log-sub">${escapedSub}</span>` : ''}
      <span class="log-msg">${escapedMsg}</span>
    </div>`;
  }).join('');

  el.innerHTML = html || '<div class="log-empty">No log entries.</div>';

  if (logsAutoFollow) scrollToBottom();
}

function scrollToBottom() {
  const scroll = document.getElementById('logs-scroll');
  if (scroll) scroll.scrollTop = scroll.scrollHeight;
}

function escapeHtml(s) {
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

async function fetchLogs() {
  console.log('[logs] fetchLogs called, gateway exists:', !!window.gateway, 'connected:', window.gateway?.connected);
  if (!window.gateway?.connected) return;
  try {
    const params = { limit: LOGS_LIMIT, maxBytes: LOGS_MAX_BYTES };
    if (logsCursor != null) params.cursor = logsCursor;
    console.log('[logs] calling rpc logs.tail...');
    const result = await window.gateway.rpc('logs.tail', params);
    console.log('[logs] rpc result:', result ? 'ok, lines=' + (result.lines?.length || 0) : 'null');
    if (!result) return;

    if (result.reset) {
      logsEntries = [];
      logsCursor = null;
    }

    if (result.lines && result.lines.length > 0) {
      const newEntries = result.lines.map(parseLogLine);
      logsEntries.push(...newEntries);
      // Cap at 2000 entries
      if (logsEntries.length > 2000) {
        logsEntries = logsEntries.slice(logsEntries.length - 2000);
      }
      renderLogs();
    }

    if (typeof result.cursor === 'number') {
      logsCursor = result.cursor;
    }
  } catch (err) {
    console.error('[logs] fetch error:', err);
  }
}

function startLogsPolling() {
  console.log('[logs] startLogsPolling, gateway:', !!window.gateway, 'connected:', window.gateway?.connected);
  // Initial fetch  
  logsCursor = null;
  logsEntries = [];
  
  // If gateway isn't connected yet, wait for it
  if (!window.gateway?.connected) {
    console.log('[logs] gateway not connected, waiting...');
    const waitIv = setInterval(() => {
      console.log('[logs] waiting for gateway... connected:', window.gateway?.connected);
      if (window.gateway?.connected) {
        clearInterval(waitIv);
        console.log('[logs] gateway connected! starting fetch...');
        fetchLogs();
        if (logsTimer) clearInterval(logsTimer);
        logsTimer = setInterval(fetchLogs, LOGS_POLL_MS);
      }
    }, 500);
    setTimeout(() => clearInterval(waitIv), 30000);
    return;
  }
  
  fetchLogs();
  // Poll every few seconds
  if (logsTimer) clearInterval(logsTimer);
  logsTimer = setInterval(fetchLogs, LOGS_POLL_MS);
}

// Public API
window.openNativeLogs = function() {
  createLogsUI();
  startLogsPolling();
};

window.closeNativeLogs = function() {
  destroyLogsUI();
};
