/* Sage — knowledge base app */

let allArticles = [];
let navIndex = null;
let currentArticleId = null;

async function loadData() {
  const [indexRes, ...articleRes] = await Promise.all([
    fetch('/sage/api/_index.json'),
    ...ARTICLE_IDS.map(id => fetch(`/sage/api/${id}.json`))
  ]);
  navIndex = await indexRes.json();
  allArticles = await Promise.all(articleRes.map(r => r.json()));
}

const ARTICLE_IDS = [
  'ssh-keys', 'ssh-access-controls', 'nginx-config',
  'disk-logs', 'file-permissions', 'cron-jobs',
  'time-sync', 'package-management'
];

const CATEGORY_LABELS = {
  access: 'Access & Authentication',
  web: 'Web Services',
  storage: 'Storage & Logs',
  sysadmin: 'System Administration',
  packages: 'Package Management'
};

// ── Sidebar ───────────────────────────────────────────────────────────────────

function buildNav() {
  const sidebar = document.getElementById('sidebar');
  sidebar.innerHTML = '';

  // Home link
  const homeWrap = document.createElement('div');
  homeWrap.className = 'nav-section';
  const homeLink = document.createElement('a');
  homeLink.className = 'nav-link';
  homeLink.textContent = '⌂  Home';
  homeLink.dataset.home = '1';
  homeLink.onclick = (e) => { e.preventDefault(); showHome(); };
  homeWrap.appendChild(homeLink);
  sidebar.appendChild(homeWrap);

  navIndex.categories.forEach(cat => {
    const section = document.createElement('div');
    section.className = 'nav-section';

    const label = document.createElement('div');
    label.className = 'nav-category';
    label.textContent = cat.label;
    section.appendChild(label);

    cat.articles.forEach(id => {
      const article = allArticles.find(a => a.id === id);
      if (!article) return;
      const link = document.createElement('a');
      link.className = 'nav-link';
      link.textContent = article.title;
      link.dataset.articleId = id;
      link.onclick = (e) => { e.preventDefault(); showArticle(id); };
      section.appendChild(link);
    });

    sidebar.appendChild(section);
  });
}

function setActiveNav(articleId) {
  document.querySelectorAll('.nav-link').forEach(el => {
    el.classList.toggle('active',
      articleId ? el.dataset.articleId === articleId : !!el.dataset.home
    );
  });
}

// ── Home ──────────────────────────────────────────────────────────────────────

function showHome() {
  currentArticleId = null;
  clearSearch();
  setActiveNav(null);
  const main = document.getElementById('main');
  main.classList.remove('hidden');
  document.getElementById('search-results').classList.remove('visible');

  main.innerHTML = '';
  const home = document.createElement('div');
  home.id = 'home-page';

  const h1 = document.createElement('h1');
  h1.textContent = 'Sage — Internal Knowledge Base';
  const subtitle = document.createElement('p');
  subtitle.className = 'home-subtitle';
  subtitle.textContent = 'Runbooks, reference guides, and procedures for Axiom Works infrastructure.';

  home.appendChild(h1);
  home.appendChild(subtitle);

  const grid = document.createElement('div');
  grid.className = 'home-grid';

  navIndex.categories.forEach(cat => {
    const catLabel = document.createElement('div');
    catLabel.className = 'home-category-label';
    catLabel.textContent = cat.label;
    home.appendChild(catLabel);

    const catGrid = document.createElement('div');
    catGrid.className = 'home-grid';

    cat.articles.forEach(id => {
      const article = allArticles.find(a => a.id === id);
      if (!article) return;
      const card = document.createElement('div');
      card.className = 'home-card';
      card.innerHTML = `
        <div class="home-card-title">${esc(article.title)}</div>
        <div class="home-card-summary">${esc(article.summary)}</div>
      `;
      card.onclick = () => showArticle(id);
      catGrid.appendChild(card);
    });

    home.appendChild(catGrid);
  });

  main.appendChild(home);
  main.scrollTop = 0;
}

// ── Article ───────────────────────────────────────────────────────────────────

function showArticle(id) {
  const article = allArticles.find(a => a.id === id);
  if (!article) return;
  currentArticleId = id;
  clearSearch();
  setActiveNav(id);

  const main = document.getElementById('main');
  main.classList.remove('hidden');
  document.getElementById('search-results').classList.remove('visible');

  const catLabel = CATEGORY_LABELS[article.category] ?? article.category;

  let html = `
    <h1 class="article-title">${esc(article.title)}</h1>
    <div class="article-meta">
      <span class="article-category-badge">${esc(catLabel)}</span>
      <span class="article-updated">${esc(article.updated)}</span>
    </div>
    <p class="article-summary">${esc(article.summary)}</p>
  `;

  article.sections.forEach(section => {
    html += `<div class="section">`;
    if (section.heading) {
      html += `<h2>${esc(section.heading)}</h2>`;
    }
    if (section.body) {
      html += `<div class="section-body">${section.body}</div>`;
    }
    if (section.code) {
      html += `<pre><code>${esc(section.code)}</code></pre>`;
    }
    html += `</div>`;
  });

  if (article.tags?.length) {
    html += `<div class="article-tags">${article.tags.map(t => `<span class="tag">${esc(t)}</span>`).join('')}</div>`;
  }

  main.innerHTML = html;
  main.scrollTop = 0;
}

// ── Search ────────────────────────────────────────────────────────────────────

let searchTimer = null;

function onSearchInput(e) {
  const q = e.target.value.trim();
  clearTimeout(searchTimer);
  if (!q) { clearSearch(); return; }
  searchTimer = setTimeout(() => runSearch(q), 120);
}

function clearSearch() {
  document.getElementById('search').value = '';
  document.getElementById('search-results').classList.remove('visible');
  const main = document.getElementById('main');
  main.classList.remove('hidden');
}

function runSearch(q) {
  const terms = q.toLowerCase().split(/\s+/).filter(Boolean);
  const results = [];

  for (const article of allArticles) {
    const haystack = [
      article.title,
      article.summary,
      ...(article.tags ?? []),
      ...article.sections.flatMap(s => [s.heading ?? '', textFromHtml(s.body ?? ''), s.code ?? ''])
    ].join(' ').toLowerCase();

    const score = terms.filter(t => haystack.includes(t)).length;
    if (score === 0) continue;

    // Find a snippet with the first matching term
    let snippet = article.summary;
    const firstTerm = terms[0];
    for (const section of article.sections) {
      const text = textFromHtml(section.body ?? '') + ' ' + (section.code ?? '');
      const idx = text.toLowerCase().indexOf(firstTerm);
      if (idx !== -1) {
        const start = Math.max(0, idx - 60);
        const end = Math.min(text.length, idx + 120);
        snippet = (start > 0 ? '…' : '') + text.slice(start, end) + (end < text.length ? '…' : '');
        break;
      }
    }

    results.push({ article, score, snippet });
  }

  results.sort((a, b) => b.score - a.score);

  const container = document.getElementById('search-results');
  container.classList.add('visible');
  document.getElementById('main').classList.add('hidden');

  if (results.length === 0) {
    container.innerHTML = `<div class="no-results">No articles matched "<strong>${esc(q)}</strong>".</div>`;
    return;
  }

  container.innerHTML = results.map(({ article, snippet }) => {
    const highlighted = highlightTerms(esc(snippet), terms);
    return `
      <div class="search-result" data-id="${esc(article.id)}">
        <div class="search-result-title">${esc(article.title)}</div>
        <div class="search-result-snippet">${highlighted}</div>
      </div>
    `;
  }).join('');

  container.querySelectorAll('.search-result').forEach(el => {
    el.onclick = () => showArticle(el.dataset.id);
  });
}

function highlightTerms(text, terms) {
  let out = text;
  terms.forEach(term => {
    const re = new RegExp(`(${escapeRegex(term)})`, 'gi');
    out = out.replace(re, '<mark>$1</mark>');
  });
  return out;
}

// ── Utilities ─────────────────────────────────────────────────────────────────

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

function textFromHtml(html) {
  const div = document.createElement('div');
  div.innerHTML = html;
  return div.textContent ?? '';
}

function escapeRegex(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

// ── Init ──────────────────────────────────────────────────────────────────────

async function init() {
  const main = document.getElementById('main');
  main.innerHTML = '<p style="color:var(--text-muted);padding:20px">Loading…</p>';

  try {
    await loadData();
  } catch (err) {
    main.innerHTML = `<p style="color:var(--text-muted);padding:20px">Failed to load knowledge base: ${esc(err.message)}</p>`;
    return;
  }

  buildNav();
  showHome();

  document.getElementById('search').addEventListener('input', onSearchInput);

  // Keyboard shortcut: / to focus search
  document.addEventListener('keydown', e => {
    if (e.key === '/' && document.activeElement !== document.getElementById('search')) {
      e.preventDefault();
      document.getElementById('search').focus();
    }
    if (e.key === 'Escape') {
      clearSearch();
      if (currentArticleId) setActiveNav(currentArticleId);
      else showHome();
    }
  });
}

document.addEventListener('DOMContentLoaded', init);
