'use strict';
/* AdminRouter — hash-based router for admin panel.
 * Wraps the existing switchTab() flow without replacing it.
 *
 * Hash format: #<route>[/<param1>[/<param2>...]]
 *   #stats              → { route: 'stats',    params: [] }
 *   #users              → { route: 'users',    params: [] }
 *   #users/123          → { route: 'users',    params: ['123'] }
 *   #sessions/456/foo   → { route: 'sessions', params: ['456','foo'] }
 *
 * Public API: window.AdminRouter
 *   parse(hash)                       → route object
 *   current()                         → route object for location.hash
 *   navigate(hash, { replace, silent })
 *   on(event, fn)  / off(event, fn)   — 'change' event only
 *
 * Recursion guard: programmatic navigate() sets a flag so the hashchange
 * listener does not re-emit 'change' for our own writes.
 */
(function () {
  'use strict';

  const listeners = { change: new Set() };
  let _navigating = false;

  function parse(hash) {
    const raw = String(hash || '');
    const stripped = raw.charAt(0) === '#' ? raw.slice(1) : raw;
    const parts = stripped.split('/').filter(Boolean);
    const route = parts.length ? decodeURIComponent(parts[0]) : '';
    const params = parts.slice(1).map(p => {
      try { return decodeURIComponent(p); } catch { return p; }
    });
    return { route, params, raw: raw || '' };
  }

  function current() {
    return parse(location.hash);
  }

  function normalizeHash(input) {
    const s = String(input || '');
    if (!s) return '';
    return s.charAt(0) === '#' ? s : '#' + s;
  }

  function emit(event, payload) {
    const set = listeners[event];
    if (!set) return;
    set.forEach(fn => {
      try { fn(payload); } catch (e) { console.error('AdminRouter listener error', e); }
    });
  }

  function navigate(routeOrHash, opts) {
    const options = opts || {};
    const target = normalizeHash(routeOrHash);
    const currentHash = location.hash || '';

    // Same hash → no-op (avoids spurious listener fires).
    if (target === currentHash) {
      if (!options.silent) emit('change', { ...parse(target), silent: false });
      return;
    }

    _navigating = true;
    try {
      if (options.replace && typeof history !== 'undefined' && history.replaceState) {
        // Preserve current path/query, swap hash without adding history entry.
        const url = location.pathname + location.search + target;
        history.replaceState(history.state, '', url);
      } else {
        location.hash = target;
      }
    } finally {
      // hashchange fires async; clear flag after dispatch.
      setTimeout(() => { _navigating = false; }, 0);
    }

    if (!options.silent) {
      emit('change', { ...parse(target), silent: false });
    }
  }

  function on(event, fn) {
    if (!listeners[event] || typeof fn !== 'function') return;
    listeners[event].add(fn);
  }

  function off(event, fn) {
    if (!listeners[event]) return;
    listeners[event].delete(fn);
  }

  window.addEventListener('hashchange', () => {
    if (_navigating) return;
    emit('change', { ...current(), silent: false });
  });

  window.AdminRouter = { parse, current, navigate, on, off };
})();
