// Topbar component functionality
class TopbarComponent {
  constructor() {
    this.init();
  }

  getCurrentPage() {
    const path = window.location.pathname;
    
    //// // console.log('🔍 Topbar: Detecting page from path:', path);
    
    // PRIMARY: Use path-based detection only (most reliable)
    // This avoids confusion from query parameters like tab=, app=, etc.
    if (path.startsWith('/app') || path === '/app') {
      return 'app';
    }
    if (path.startsWith('/apps') || path === '/apps') {
      return 'apps';
    }
    if (path.startsWith('/admin') || path.startsWith('/config') || path.startsWith('/ssh')) {
      return 'config';
    }
    if (path.startsWith('/tasks') || path === '/tasks') {
      return 'tasks';
    }
    if (path.startsWith('/backup') || path === '/backup') {
      return 'backup';
    }
    if (path.startsWith('/updater') || path === '/updater') {
      return 'updater';
    }
    if (path === '/' || path === '/dashboard') {
      return 'dashboard';
    }
    
    // Fallback to filename extraction for backward compatibility
    const filename = path.split('/').pop() || 'dashboard.html';
    const pageType = filename.replace('.html', '');
    return pageType;
  }

  // Static method to load topbar (only once in SPA)
  static async loadTopbar() {
    const container = document.getElementById('topbar-container');
    if (!container) {
      console.error('Topbar container not found');
      return;
    }

    // Load fresh topbar HTML
    try {
      //// // console.log('Loading topbar HTML (SPA mode)');
      const response = await fetch('/core/topbar/html/topbar.html');
      if (!response.ok) {
        throw new Error(`Failed to load topbar: ${response.status}`);
      }
      
      const html = await response.text();
      container.innerHTML = html;
      
      // Initialize component. Stash on window so other surfaces can reach
      // the canonical _setDevMode path (e.g. the Advanced-toggle 10-tap
      // unlock in services-manager). Otherwise dev-mode would have two
      // setter paths and they could drift.
      window.topbar = new TopbarComponent();

    } catch (error) {
      console.error('Error loading topbar:', error);
    }
  }

  init() {
    this.setupNavigation();
    this.setActiveNav();
    this.setupThemeManager();
    this.setupLogout();
    this.setupConfigUpdateLockout();
    this.setupSetupGate();
    this.setupDevModeEasterEgg();
    this.setupDevBanner();
    this.autoEnableDevModeIfNeeded();
    // Mount the "out of date" badge now that .topbar-controls exists.
    window.updateNotifier?.onTopbarReady();
    // …and the network-drift badge (sits just after the update badge).
    window.networkNotifier?.onTopbarReady();
  }

  // 10-click LibrePortal-logo easter egg → toggles CFG_DEV_MODE. Inspired by
  // Android's "tap Build Number 7 times to become a developer". Same idea:
  // dev-mode shows hidden CFG_* fields marked **DEV** (Installation Mode,
  // Release Channel, etc.) that normal users never need to see. Disabling
  // also via this path — 10 more clicks turns it back off.
  setupDevModeEasterEgg() {
    const TARGET_CLICKS = 10;     // matches Android's pattern (well, 7 there)
    const TOAST_FROM = 6;         // start showing the countdown at click 6
    const RESET_AFTER_MS = 3000;  // idle reset — don't accumulate across sessions

    let count = 0;
    let resetTimer = null;
    let currentToast = null;      // single rolling toast — updated in place

    document.addEventListener('click', (e) => {
      const logo = e.target.closest('.libreportal-logo');
      if (!logo) return;
      count++;

      if (resetTimer) clearTimeout(resetTimer);
      resetTimer = setTimeout(() => {
        count = 0;
        currentToast = null;  // next sequence starts a fresh toast
      }, RESET_AFTER_MS);

      const remaining = TARGET_CLICKS - count;
      const devOn = (window.systemConfigs?.CFG_DEV_MODE === 'true');
      const verb = devOn ? 'disabling' : 'being';
      const noun = devOn ? 'developer mode' : 'a developer';

      if (remaining > 0 && count >= TOAST_FROM) {
        const msg = `You are ${remaining} click${remaining === 1 ? '' : 's'} away from ${verb} ${noun}.`;
        // If the rolling toast is still in the DOM, mutate its message
        // text in place instead of stacking another notification. When
        // it's been auto-removed (10s lifetime) we open a fresh one.
        const msgEl = currentToast && currentToast.parentElement
          ? currentToast.querySelector('.notification-message')
          : null;
        if (msgEl) {
          msgEl.innerHTML = msg;
        } else {
          currentToast = this._devToast(msg, 'info');
        }
      } else if (remaining === 0) {
        count = 0;
        clearTimeout(resetTimer);
        currentToast = null;
        this._setDevMode(!devOn);
      }
    });
  }

  // On WebUI load, if CFG_INSTALL_MODE is git/local but CFG_DEV_MODE is off,
  // auto-enable it. Otherwise dev-install users get locked out of the very
  // fields they need to manage their install. Idempotent — runs once per
  // load; the no-op case (already on, or on release) is silent.
  async autoEnableDevModeIfNeeded() {
    try {
      const r = await fetch(`/data/config/generated/configs.json?t=${Date.now()}`);
      if (!r.ok) return;
      const data = await r.json();
      const installMode = data?.config?.CFG_INSTALL_MODE?.value;
      const devMode     = data?.config?.CFG_DEV_MODE?.value;
      const onDevInstall = (installMode === 'git' || installMode === 'local');
      const devModeOff   = (devMode !== 'true' && devMode !== true);
      if (onDevInstall && devModeOff) {
        this._devToast(`Developer mode auto-enabled — you're on a ${installMode} install.`, 'success');
        await this._setDevMode(true, /*silent*/ true);
      } else if (devMode === 'true' || devMode === true) {
        this._updateDevBanner(true);
      }
    } catch { /* missing configs.json, network blip — leave it; easter egg still works */ }
  }

  // Wires the dismiss button on the developer-mode strip. Dismissal is
  // remembered in localStorage and cleared whenever dev mode is re-enabled
  // (in _setDevMode), so toggling off + back on brings the banner back.
  setupDevBanner() {
    const btn = document.getElementById('dev-banner-close');
    if (!btn) return;
    btn.addEventListener('click', () => {
      try { localStorage.setItem('lp.devBannerDismissed', 'true'); } catch {}
      this._updateDevBanner(false);
    });
  }

  // Show/hide the banner + body padding offset. visible=true only paints
  // it when the user hasn't dismissed for this install.
  _updateDevBanner(visible) {
    const el = document.getElementById('dev-banner');
    if (!el) return;
    let dismissed = false;
    try { dismissed = localStorage.getItem('lp.devBannerDismissed') === 'true'; } catch {}
    const shouldShow = visible && !dismissed;
    el.hidden = !shouldShow;
    document.body.classList.toggle('has-dev-banner', shouldShow);
  }

  // Toast helper — uses the project's notification system if loaded, else
  // a quiet console echo so dev-mode UX never blocks page render. Returns
  // the notification DOM element when the real system is available, so
  // callers (the easter-egg countdown) can mutate the message in place
  // instead of stacking new toasts on each click.
  _devToast(message, kind = 'info') {
    if (window.notificationSystem?.show) {
      return window.notificationSystem.show(message, kind);
    } else if (typeof window.showNotification === 'function') {
      return window.showNotification(message, kind);
    }
    console.log(`[dev-mode] ${message}`);
    return null;
  }

  // Flip CFG_DEV_MODE via the standard config-update task (same path the
  // Config form uses). silent=true suppresses the success toast for the
  // auto-detect path — the auto-detect path emits its own message first.
  async _setDevMode(enabled, silent = false) {
    const value = enabled ? 'true' : 'false';
    try {
      if (!window.tasksManager?.router?.routeAction) {
        this._devToast('Task system not ready — cannot toggle Developer Mode right now.', 'error');
        return;
      }
      const encoded = `CFG_DEV_MODE=${value}`;
      await window.tasksManager.router.routeAction('config_update', {
        changes: `'${encoded.replace(/'/g, "'\\''")}'`
      });
      // Optimistically update the in-process cache so other components
      // (e.g. config-shared.js's _filterDevKeys) see the new value without
      // a full page refresh.
      if (!window.systemConfigs) window.systemConfigs = {};
      window.systemConfigs.CFG_DEV_MODE = value;
      // Mirror the change into the LpUi body-class machinery so CSS
      // gates (e.g. body.lp-ui--dev) flip without a reload. Linking rule
      // is enforced inside LpUi.dev.set: enabling dev auto-enables
      // advanced too.
      if (window.LpUi?.dev) {
        try { window.LpUi.dev.set(enabled); } catch { /* belt + braces */ }
      }
      if (enabled) {
        try { localStorage.removeItem('lp.devBannerDismissed'); } catch {}
        this._updateDevBanner(true);
      } else {
        this._updateDevBanner(false);
      }
      if (!silent) {
        this._devToast(
          enabled
            ? '🛠️  Developer mode unlocked. Reload to see the extra options.'
            : 'Developer mode disabled.',
          'success'
        );
      }
    } catch (err) {
      this._devToast(`Failed to toggle Developer Mode: ${err.message || err}`, 'error');
    }
  }

  // Disable nav items entirely until the Setup Wizard has been completed.
  // The wizard itself runs as a full-screen overlay that blocks interaction;
  // this is a belt-and-braces guard for the brief window before the wizard
  // mounts, and for any nav rendering that happens while it's open.
  async setupSetupGate() {
    try {
      const res = await fetch('/api/setup/status');
      if (!res.ok) return;
      const { complete } = await res.json();
      const nav = document.querySelector('.topbar-nav');
      if (!nav) return;
      if (!complete) {
        nav.classList.add('setup-needed');
      } else {
        nav.classList.remove('setup-needed');
      }
    } catch { /* leave nav enabled if status check fails */ }
  }

  // Disable App Center / Config nav while a config_update task runs.
  setupConfigUpdateLockout() {
    const setLocked = (locked) => {
      ['nav-app-center', 'nav-config'].forEach((id) => {
        const el = document.getElementById(id);
        if (!el) return;
        if (locked) {
          el.classList.add('nav-item-disabled');
          el.setAttribute('aria-disabled', 'true');
          el.title = 'Disabled while configuration is being applied';
        } else {
          el.classList.remove('nav-item-disabled');
          el.removeAttribute('aria-disabled');
          el.title = '';
        }
      });
    };

    window.addEventListener('taskCreated', (event) => {
      if (event.detail?.action === 'config_update') setLocked(true);
    });
    window.addEventListener('taskCompleted', (event) => {
      if (event.detail?.action === 'config_update') setLocked(false);
    });
  }

  setupLogout() {
    const btn = document.getElementById('logout-btn');
    if (btn) {
      btn.addEventListener('click', () => window.authManager?.logout());
    }
  }

  setupNavigation() {
    // Add click handlers to navigation items
    const navItems = document.querySelectorAll('.nav-item');
    navItems.forEach(item => {
      item.addEventListener('click', (e) => {
        e.preventDefault();
        if (item.classList.contains('nav-item-disabled')) return;
        const href = item.getAttribute('href');
        if (href) {
          // Special handling for tasks navigation
          if (item.id === 'nav-tasks' && window.tasksManager) {
            
            // Force clean state
            window.tasksManager.highlightedTaskId = null;
            window.tasksManager.currentCategory = 'all';
            window.tasksManager.tasks = []; // Clear the task list
            
            // Clear URL parameters
            window.history.pushState({ category: 'all', taskId: null }, '', '/tasks/all');
            
            // Clear any localStorage filters
            localStorage.removeItem('tasksDefaultFilter');
            
            // Force reload all tasks
            window.tasksManager.loadTasks().catch(error => {
              console.warn('⚠️ Error refreshing tasks:', error);
            });
          }
          
          // Use shared navigation utility
          navigateToRoute(href);
        }
      });
    });

    // Setup mobile menu
    this.setupMobileMenu();
  }

  setupMobileMenu() {
    const mobileMenuBtn = document.getElementById('mobile-menu-btn');
    const mobileOverlay = document.getElementById('mobile-overlay');
    const sidebar = document.getElementById('sidebar');

    if (mobileMenuBtn && mobileOverlay) {
      mobileMenuBtn.addEventListener('click', () => {
        sidebar.classList.toggle('mobile-open');
        mobileOverlay.classList.toggle('active');
        document.body.style.overflow = sidebar.classList.contains('mobile-open') ? 'hidden' : '';
      });

      mobileOverlay.addEventListener('click', () => {
        sidebar.classList.remove('mobile-open');
        mobileOverlay.classList.remove('active');
        document.body.style.overflow = '';
      });
    }
  }

  setupThemeManager() {
    const themeSelector = document.getElementById('theme-selector');
    if (!themeSelector) return;

    const savedTheme = TopbarComponent.resolveSavedTheme();
    this.setTheme(savedTheme);

    // Populate the dropdown from ThemeRegistry. Called twice — once
    // synchronously with the built-in fallback list, then again after
    // the API discovery resolves with any custom themes.
    const renderOptions = (themes) => {
      const current = localStorage.getItem('theme') || savedTheme;
      themeSelector.innerHTML = '';
      themes.forEach((t) => {
        const opt = document.createElement('option');
        opt.value = t.name;
        opt.textContent = t.displayName || t.name;
        themeSelector.appendChild(opt);
      });
      // If the saved theme is now in the list, select it; otherwise
      // leave whatever the browser chose as the default selection.
      if (themes.some((t) => t.name === current)) {
        themeSelector.value = current;
      }
    };

    if (window.ThemeRegistry && typeof window.ThemeRegistry.onChange === 'function') {
      window.ThemeRegistry.onChange(renderOptions);
    } else {
      // ThemeRegistry didn't load — fall back to the built-in three.
      renderOptions([
        { name: 'nebula',    displayName: 'Nebula' },
        { name: 'dark-blue', displayName: 'Dark Blue' },
        { name: 'light',     displayName: 'Light' },
      ]);
    }

    themeSelector.addEventListener('change', (e) => {
      this.setTheme(e.target.value);
    });
  }

  // Reads localStorage, migrates legacy values, and returns the canonical
  // theme name. Old "dark" / "blue" both map to the new "dark-blue".
  // An earlier dead initializer wrote to "selectedTheme" — fold that in
  // and drop it. We don't validate against a fixed list anymore because
  // custom themes are discovered at runtime — any string is accepted.
  static resolveSavedTheme() {
    const legacy = localStorage.getItem('selectedTheme');
    if (legacy && !localStorage.getItem('theme')) {
      localStorage.setItem('theme', legacy);
    }
    if (legacy) localStorage.removeItem('selectedTheme');

    let theme = localStorage.getItem('theme');
    if (theme === 'dark' || theme === 'blue') {
      theme = 'dark-blue';
      localStorage.setItem('theme', theme);
    }
    if (!theme) {
      theme = 'nebula';
      localStorage.setItem('theme', theme);
    }
    return theme;
  }

  setActiveNav() {
    // Remove active class from all nav items
    document.querySelectorAll('.nav-item').forEach(item => {
      item.classList.remove('active');
    });

    // Use path-based detection only for consistency
    const path = window.location.pathname;
    
    let activeNavId;
    
    // PRIMARY: Use path-based detection only (most reliable). Overview + the
    // backup center live under App Center now; /updater redirects to /overview.
    if (path.startsWith('/app') || path.startsWith('/apps') || path.startsWith('/overview') || path.startsWith('/backup')) {
      activeNavId = 'nav-app-center';
    } else if (path.startsWith('/admin') || path.startsWith('/config') || path.startsWith('/ssh')) {
      activeNavId = 'nav-config'; // Admin area (config + SSH live here)
    } else if (path.startsWith('/tasks')) {
      activeNavId = 'nav-tasks';
    } else if (path === '/' || path === '/dashboard') {
      activeNavId = 'nav-dashboard';
    } else {
      // Fallback to page detection
      if (this.currentPage === 'dashboard') {
        activeNavId = 'nav-dashboard';
      } else if (this.currentPage === 'index' || this.currentPage === 'app' || this.currentPage === 'apps') {
        activeNavId = 'nav-app-center';
      } else if (this.currentPage === 'config') {
        activeNavId = 'nav-config';
      } else if (this.currentPage === 'tasks') {
        activeNavId = 'nav-tasks';
      } else if (this.currentPage === 'backup') {
        activeNavId = 'nav-backup';
      } else if (this.currentPage === 'updater') {
        activeNavId = 'nav-updater';
      } else {
        activeNavId = 'nav-dashboard'; // default
      }
    }

    // Add active class to current page nav
    if (activeNavId) {
      const activeNav = document.getElementById(activeNavId);
      if (activeNav) {
        activeNav.classList.add('nav-active');
      } else {
        console.warn(`❌ Nav element not found: ${activeNavId}`);
      }
    } else {
      console.warn(`❌ Could not determine active nav for path: ${path}`);
    }
  }

  setTheme(theme) {
    localStorage.setItem('theme', theme);
    document.documentElement.setAttribute('data-theme', theme);
    document.body.setAttribute('data-theme', theme);
  }

}
