'use strict';
/* admin → Cmd+K / Ctrl+K command palette (Phase 4).
 * Self-initialized on DOMContentLoaded. Not a section — it's a global widget.
 * Overrides the generic /js/search.js Ctrl+K handler on admin pages by binding
 * in capture phase and calling stopImmediatePropagation.
 */
(function () {
  'use strict';

  /* ── Hardcoded actions ────────────────────────────────────────────────── */
  const ACTIONS = [
    { id: 'award_coins',   name: 'Выдать монеты',     hint: 'shop',     icon: 'coins',             go: () => navigateTo('#shop') },
    { id: 'award_xp',      name: 'Выдать XP',          hint: 'gam',      icon: 'zap',               go: () => navigateTo('#gam') },
    { id: 'new_class',     name: 'Создать класс',      hint: 'classes',  icon: 'plus-circle',       go: () => { window.location.href = '/classes'; } },
    { id: 'new_test',      name: 'Создать тест',        hint: 'tests',    icon: 'file-plus',         go: () => navigateTo('#tests') },
    { id: 'view_users',    name: 'Все пользователи',   hint: 'users',    icon: 'users',             go: () => navigateTo('#users') },
    { id: 'view_sessions', name: 'Все сессии',         hint: 'sessions', icon: 'history',           go: () => navigateTo('#sessions') },
    { id: 'view_audit',    name: 'Audit log',           hint: 'sublog',   icon: 'shield',            go: () => navigateTo('#sublog') },
    { id: 'view_overview', name: 'Главная',             hint: 'overview', icon: 'layout-dashboard',  go: () => navigateTo('#overview') },
  ];

  /* ── State ────────────────────────────────────────────────────────────── */
  let _overlay  = null;
  let _input    = null;
  let _results  = null;
  let _timer    = null;
  let _items    = [];  // flat list of result items in display order
  let _activeIdx = 0;
  let _lastQuery = '';
  let _reqSeq    = 0;  // race-guard for async fetches

  /* ── Helpers ──────────────────────────────────────────────────────────── */
  function navigateTo(hash) {
    if (window.AdminRouter) AdminRouter.navigate(hash);
    else window.location.hash = hash;
  }

  function esc(s) {
    return (window.LS && LS.esc) ? LS.esc(s) : String(s == null ? '' : s)
      .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  }

  function isOpen() {
    return !!(_overlay && _overlay.classList.contains('open'));
  }

  /* ── Styles (lazy injection) ──────────────────────────────────────────── */
  function ensureStyles() {
    if (document.getElementById('akp-style')) return;
    const s = document.createElement('style');
    s.id = 'akp-style';
    s.textContent = `
      .akp-ov { position: fixed; inset: 0; z-index: 9500;
        display: flex; align-items: flex-start; justify-content: center;
        padding: 96px 20px 20px;
        background: rgba(15,23,42,0.55);
        backdrop-filter: blur(8px);
        opacity: 0; pointer-events: none;
        transition: opacity .15s ease; }
      .akp-ov.open { opacity: 1; pointer-events: auto; }
      .akp-box { width: 100%; max-width: 600px;
        background: var(--surface, #fff);
        border: 1px solid var(--border, rgba(15,23,42,.08));
        border-radius: 16px;
        box-shadow: 0 24px 80px rgba(15,23,42,0.32);
        display: flex; flex-direction: column;
        max-height: calc(100vh - 140px);
        overflow: hidden;
        transform: translateY(-8px) scale(.98);
        transition: transform .18s ease; }
      .akp-ov.open .akp-box { transform: translateY(0) scale(1); }
      .akp-input-wrap { display: flex; align-items: center; gap: 10px;
        padding: 14px 18px; border-bottom: 1px solid var(--border, rgba(15,23,42,.08)); }
      .akp-input-wrap svg.akp-search-icon { width: 18px; height: 18px;
        color: var(--text-3, #64748b); flex-shrink: 0; }
      .akp-input { flex: 1; border: none; outline: none; background: transparent;
        font-family: inherit; font-size: 1.05rem; color: var(--text, #0F172A);
        padding: 4px 0; }
      .akp-input::placeholder { color: var(--text-3, #94a3b8); }
      .akp-kbd { font-family: ui-monospace, monospace; font-size: .7rem;
        background: rgba(15,23,42,.06); color: var(--text-3, #64748b);
        padding: 2px 6px; border-radius: 5px; border: 1px solid var(--border, rgba(15,23,42,.08));
        flex-shrink: 0; }
      .akp-results { flex: 1; overflow-y: auto; padding: 6px 0; }
      .akp-group-label { font-family: 'Unbounded', sans-serif;
        font-size: .68rem; font-weight: 700; text-transform: uppercase;
        letter-spacing: .05em; color: var(--text-3, #64748b);
        padding: 10px 18px 6px; }
      .akp-item { display: flex; align-items: center; gap: 12px;
        padding: 9px 18px; cursor: pointer; user-select: none;
        border-left: 3px solid transparent; }
      .akp-item:hover, .akp-item.active {
        background: rgba(155,93,229,.08); border-left-color: var(--violet, #9B5DE5); }
      .akp-icon { width: 30px; height: 30px; border-radius: 8px;
        display: flex; align-items: center; justify-content: center;
        background: rgba(155,93,229,.1); color: var(--violet, #9B5DE5);
        flex-shrink: 0; }
      .akp-icon svg { width: 16px; height: 16px; }
      .akp-body { flex: 1; min-width: 0; }
      .akp-title { font-size: .92rem; font-weight: 600; color: var(--text, #0F172A);
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
      .akp-sub { font-size: .76rem; color: var(--text-3, #64748b);
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
      .akp-badge { font-size: .68rem; font-weight: 700; text-transform: uppercase;
        letter-spacing: .04em; color: var(--text-3, #64748b);
        padding: 2px 7px; border-radius: 5px;
        background: rgba(15,23,42,.06); border: 1px solid var(--border, rgba(15,23,42,.08));
        flex-shrink: 0; }
      .akp-badge.role-admin   { background: rgba(241,91,181,.1);  color: var(--pink,  #F15BB5); border-color: rgba(241,91,181,.25); }
      .akp-badge.role-teacher { background: rgba(6,214,224,.1);   color: var(--cyan,  #06D6E0); border-color: rgba(6,214,224,.25); }
      .akp-badge.role-student { background: rgba(155,93,229,.1);  color: var(--violet,#9B5DE5); border-color: rgba(155,93,229,.25); }
      .akp-empty { padding: 22px 18px; text-align: center;
        color: var(--text-3, #64748b); font-size: .88rem; }
      .akp-footer { display: flex; align-items: center; gap: 14px;
        padding: 9px 18px; font-size: .72rem; color: var(--text-3, #64748b);
        border-top: 1px solid var(--border, rgba(15,23,42,.08));
        background: rgba(15,23,42,.02); flex-shrink: 0; }
      .akp-footer span { display: inline-flex; align-items: center; gap: 5px; }
      .akp-footer kbd { font-family: ui-monospace, monospace; font-size: .7rem;
        padding: 1px 5px; border-radius: 4px;
        background: var(--surface, #fff);
        border: 1px solid var(--border, rgba(15,23,42,.12)); }
      @media (max-width: 540px) {
        .akp-ov { padding: 40px 12px 12px; }
        .akp-box { max-height: calc(100vh - 60px); }
      }
    `;
    document.head.appendChild(s);
  }

  /* ── Lucide icon helper (inline SVG fallback if Lucide missing) ───────── */
  function iconHtml(name) {
    return `<i data-lucide="${esc(name)}"></i>`;
  }

  /* ── Build DOM ────────────────────────────────────────────────────────── */
  function build() {
    if (_overlay) return;
    ensureStyles();
    _overlay = document.createElement('div');
    _overlay.className = 'akp-ov';
    _overlay.setAttribute('role', 'dialog');
    _overlay.setAttribute('aria-modal', 'true');
    _overlay.setAttribute('aria-label', 'Командная палитра');
    _overlay.innerHTML = `
      <div class="akp-box" role="presentation">
        <div class="akp-input-wrap">
          <svg class="akp-search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.3-4.3"/></svg>
          <input class="akp-input" type="text" autocomplete="off" spellcheck="false"
                 placeholder="Поиск: пользователь, тест, класс, действие…" />
          <span class="akp-kbd">esc</span>
        </div>
        <div class="akp-results"></div>
        <div class="akp-footer">
          <span><kbd>↑</kbd><kbd>↓</kbd> навигация</span>
          <span><kbd>↵</kbd> выбрать</span>
          <span><kbd>esc</kbd> закрыть</span>
        </div>
      </div>
    `;
    document.body.appendChild(_overlay);

    _input   = _overlay.querySelector('.akp-input');
    _results = _overlay.querySelector('.akp-results');

    // Click outside (backdrop) closes
    _overlay.addEventListener('mousedown', (e) => {
      if (e.target === _overlay) close();
    });

    // Box click does not close (handled by stopPropagation on the box)
    _overlay.querySelector('.akp-box').addEventListener('mousedown', (e) => {
      e.stopPropagation();
    });

    // Input handling
    _input.addEventListener('input', () => {
      clearTimeout(_timer);
      _timer = setTimeout(runSearch, 150);
    });

    // Keyboard navigation
    _input.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') { e.preventDefault(); close(); return; }
      if (e.key === 'ArrowDown') { e.preventDefault(); moveActive(1); return; }
      if (e.key === 'ArrowUp')   { e.preventDefault(); moveActive(-1); return; }
      if (e.key === 'Enter') {
        e.preventDefault();
        const it = _items[_activeIdx];
        if (it) fire(it);
        return;
      }
    });

    // Click on result
    _results.addEventListener('click', (e) => {
      const row = e.target.closest('.akp-item');
      if (!row) return;
      const idx = Number(row.dataset.idx);
      const it = _items[idx];
      if (it) fire(it);
    });
  }

  /* ── Matching / filtering ─────────────────────────────────────────────── */
  function filterActions(q) {
    if (!q) return ACTIONS.slice();
    const lq = q.toLowerCase();
    return ACTIONS.filter(a =>
      a.name.toLowerCase().includes(lq) ||
      (a.hint && a.hint.toLowerCase().includes(lq))
    );
  }

  /* ── Fire (handle result selection) ───────────────────────────────────── */
  function fire(item) {
    close();
    try {
      if (item.kind === 'action' && typeof item.go === 'function') {
        item.go();
      } else if (item.kind === 'user') {
        navigateTo('#users/' + item.id);
      } else if (item.kind === 'test') {
        navigateTo('#tests');
      } else if (item.kind === 'class') {
        window.location.href = '/classes#' + item.id;
      }
    } catch (err) {
      if (window.LS && LS.toast) LS.toast('Не удалось открыть: ' + (err && err.message || err), 'error');
    }
  }

  /* ── Render ───────────────────────────────────────────────────────────── */
  function render(groups) {
    _items = [];
    let html = '';
    let idx = 0;

    function pushGroup(label, arr, makeItem) {
      if (!arr || !arr.length) return;
      html += `<div class="akp-group-label">${esc(label)}</div>`;
      for (const x of arr) {
        const item = makeItem(x);
        _items.push(item);
        const isActive = idx === _activeIdx ? ' active' : '';
        html += `<div class="akp-item${isActive}" data-idx="${idx}">
          <div class="akp-icon">${iconHtml(item.icon)}</div>
          <div class="akp-body">
            <div class="akp-title">${esc(item.title)}</div>
            ${item.subtitle ? `<div class="akp-sub">${esc(item.subtitle)}</div>` : ''}
          </div>
          ${item.badge ? `<span class="akp-badge ${item.badgeClass || ''}">${esc(item.badge)}</span>` : ''}
        </div>`;
        idx++;
      }
    }

    pushGroup('Действия', groups.actions, a => ({
      kind: 'action', id: a.id, title: a.name, icon: a.icon, go: a.go,
    }));
    pushGroup('Пользователи', groups.users, u => ({
      kind: 'user', id: u.id, title: u.name || '(без имени)',
      subtitle: u.email || '', icon: 'user',
      badge: u.role || '', badgeClass: u.role ? ('role-' + u.role) : '',
    }));
    pushGroup('Тесты', groups.tests, t => ({
      kind: 'test', id: t.id, title: t.name || '(без названия)',
      subtitle: t.subject_slug ? ('предмет: ' + t.subject_slug) : '',
      icon: 'clipboard-list',
    }));
    pushGroup('Классы', groups.classes, c => ({
      kind: 'class', id: c.id, title: c.name || '(без названия)',
      subtitle: c.code ? ('код: ' + c.code) : '',
      icon: 'graduation-cap',
    }));

    if (!_items.length) {
      _results.innerHTML = '<div class="akp-empty">Ничего не найдено</div>';
      _activeIdx = 0;
      return;
    }

    if (_activeIdx >= _items.length) _activeIdx = 0;
    _results.innerHTML = html;

    if (window.lucide) {
      try { lucide.createIcons({ nodes: _results.querySelectorAll('[data-lucide]') }); } catch {}
    }
  }

  function moveActive(dir) {
    const total = _items.length;
    if (!total) return;
    _activeIdx = (_activeIdx + dir + total) % total;
    // Re-paint active class without rebuilding html
    const rows = _results.querySelectorAll('.akp-item');
    rows.forEach((r, i) => r.classList.toggle('active', i === _activeIdx));
    const cur = rows[_activeIdx];
    if (cur) cur.scrollIntoView({ block: 'nearest' });
  }

  /* ── Search executor ──────────────────────────────────────────────────── */
  async function runSearch() {
    const q = _input.value.trim();
    _lastQuery = q;
    _activeIdx = 0;

    // No query: actions only
    if (q.length < 2) {
      render({ actions: ACTIONS, users: [], tests: [], classes: [] });
      return;
    }

    const localActions = filterActions(q);
    // Show actions immediately, then update with server results
    render({ actions: localActions, users: [], tests: [], classes: [] });

    const seq = ++_reqSeq;
    try {
      const data = (window.LS && LS.adminGlobalSearch)
        ? await LS.adminGlobalSearch(q)
        : { users: [], tests: [], classes: [] };
      // Stale response: ignore
      if (seq !== _reqSeq || q !== _lastQuery) return;
      render({
        actions: localActions,
        users:   data.users   || [],
        tests:   data.tests   || [],
        classes: data.classes || [],
      });
    } catch (err) {
      if (seq !== _reqSeq) return;
      _results.innerHTML = '<div class="akp-empty">Ошибка поиска</div>';
    }
  }

  /* ── Open / close ─────────────────────────────────────────────────────── */
  function open() {
    build();
    _activeIdx = 0;
    _items = [];
    _input.value = '';
    render({ actions: ACTIONS, users: [], tests: [], classes: [] });
    _overlay.classList.add('open');
    setTimeout(() => { try { _input.focus(); _input.select(); } catch {} }, 30);
  }

  function close() {
    if (!_overlay) return;
    _overlay.classList.remove('open');
  }

  /* ── Global shortcut: Ctrl+K / Cmd+K ──────────────────────────────────── */
  // Capture phase + stopImmediatePropagation prevents the generic /js/search.js
  // handler (also on Ctrl+K) from firing on admin pages.
  document.addEventListener('keydown', (e) => {
    if ((e.ctrlKey || e.metaKey) && (e.key === 'k' || e.key === 'K')) {
      e.preventDefault();
      e.stopImmediatePropagation();
      if (isOpen()) close(); else open();
    }
  }, true);

  // Expose for debugging / future cross-section calls
  window.AdminPalette = { open, close, isOpen };
})();
