// =====================================================
// Search — index across all notes and concepts
// =====================================================

let searchIndex = null;

async function buildSearchIndex() {
  if (searchIndex) return searchIndex;
  const idx = [];

  // Index concepts from THEMES
  Object.values(SMF.THEMES).forEach(theme => {
    theme.keyConcepts.forEach(c => {
      idx.push({
        type: 'concept',
        category: theme.label,
        title: c.term,
        snippet: c.def,
        href: `#/tema/${theme.id}`,
        searchText: `${c.term} ${c.def}`.toLowerCase()
      });
    });
  });

  // Index weeks
  SMF.WEEKS.forEach(w => {
    idx.push({
      type: 'uke',
      category: SMF.themeLabel(w.theme),
      title: `Uke ${w.id}: ${w.title}`,
      snippet: '',
      href: `#/uke/${w.id}`,
      searchText: `uke ${w.id} ${w.title}`.toLowerCase()
    });
  });

  // Load all notes and extract headings + paragraphs
  const noteFiles = ['uke02-03-04.md', 'uke05-06.md', 'uke07-08.md', 'uke10-11.md', 'uke12-16.md', 'uke17-eksamen.md'];
  for (const file of noteFiles) {
    try {
      const md = await SMF.loadNote(file);
      const lines = md.split('\n');
      let currentWeek = null;
      let currentH = null;
      let buffer = [];
      const flush = () => {
        if (buffer.length && currentH) {
          const txt = buffer.join(' ').trim();
          if (txt.length > 20) {
            idx.push({
              type: 'avsnitt',
              category: currentWeek ? `Uke ${currentWeek}` : 'Pensum',
              title: currentH,
              snippet: txt.slice(0, 220) + (txt.length > 220 ? '…' : ''),
              href: currentWeek ? `#/uke/${currentWeek}` : `#/uke/17`,
              searchText: (currentH + ' ' + txt).toLowerCase()
            });
          }
        }
        buffer = [];
      };
      for (const line of lines) {
        const ukeMatch = line.match(/^##\s+Uke\s+(\d+)/i);
        if (ukeMatch) {
          flush();
          currentWeek = parseInt(ukeMatch[1], 10);
          currentH = line.replace(/^#+\s+/, '');
          continue;
        }
        const hMatch = line.match(/^#{3,4}\s+(.+)/);
        if (hMatch) {
          flush();
          currentH = hMatch[1].trim();
          continue;
        }
        if (line.trim() && !line.startsWith('|') && !line.startsWith('---')) {
          buffer.push(line.replace(/[*_`]/g, ''));
        }
      }
      flush();
    } catch (e) {
      console.warn('Could not load note for indexing:', file, e);
    }
  }

  searchIndex = idx;
  return idx;
}

function searchQuery(q) {
  if (!searchIndex || !q || q.length < 2) return [];
  const qLow = q.toLowerCase();
  const terms = qLow.split(/\s+/).filter(t => t.length > 1);
  if (!terms.length) return [];

  const scored = [];
  for (const item of searchIndex) {
    let score = 0;
    let titleHits = 0;
    const titleLow = item.title.toLowerCase();
    terms.forEach(t => {
      if (titleLow.includes(t)) { score += 10; titleHits++; }
      if (item.searchText.includes(t)) { score += 2; }
    });
    // Bonus: type-priority — concepts > weeks > paragraphs
    if (item.type === 'concept') score += 3;
    else if (item.type === 'uke') score += 2;
    // Bonus: title contains whole query
    if (titleLow.includes(qLow)) score += 8;
    if (score > 0) scored.push({ item, score, titleHits });
  }

  scored.sort((a, b) => b.score - a.score);
  return scored.slice(0, 12).map(s => s.item);
}

function highlight(text, q) {
  if (!q) return text;
  const terms = q.toLowerCase().split(/\s+/).filter(t => t.length > 1);
  let out = text;
  terms.forEach(t => {
    const re = new RegExp(`(${t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
    out = out.replace(re, '<mark>$1</mark>');
  });
  return out;
}

function attachSearch() {
  const input = document.getElementById('searchInput');
  const results = document.getElementById('searchResults');
  if (!input || !results) return;

  let timer = null;

  input.addEventListener('input', async (e) => {
    const q = e.target.value.trim();
    if (!q || q.length < 2) {
      results.classList.remove('search-results--open');
      results.innerHTML = '';
      return;
    }
    await buildSearchIndex();
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      const matches = searchQuery(q);
      if (!matches.length) {
        results.innerHTML = `<div class="search-result"><div class="search-result__title">Ingen treff på "${q}"</div></div>`;
      } else {
        results.innerHTML = matches.map(m => `
          <a class="search-result" href="${m.href}">
            <div class="search-result__type">${m.type} · ${m.category}</div>
            <div class="search-result__title">${highlight(m.title, q)}</div>
            ${m.snippet ? `<div class="search-result__snippet">${highlight(m.snippet, q)}</div>` : ''}
          </a>
        `).join('');
      }
      results.classList.add('search-results--open');
    }, 80);
  });

  input.addEventListener('focus', () => {
    if (input.value.length >= 2) {
      results.classList.add('search-results--open');
    }
  });

  // Hide on outside click
  document.addEventListener('click', (e) => {
    if (!input.contains(e.target) && !results.contains(e.target)) {
      results.classList.remove('search-results--open');
    }
  });

  // Click result -> close
  results.addEventListener('click', (e) => {
    const a = e.target.closest('.search-result');
    if (a) {
      results.classList.remove('search-results--open');
      input.value = '';
      input.blur();
    }
  });

  // Keyboard: '/' to focus
  document.addEventListener('keydown', (e) => {
    if (e.key === '/' && document.activeElement !== input && !e.metaKey && !e.ctrlKey) {
      const tag = document.activeElement?.tagName;
      if (tag !== 'INPUT' && tag !== 'TEXTAREA') {
        e.preventDefault();
        input.focus();
        input.select();
      }
    }
    if (e.key === 'Escape') {
      results.classList.remove('search-results--open');
      input.blur();
    }
  });
}

SMF.attachSearch = attachSearch;
SMF.buildSearchIndex = buildSearchIndex;
