/**
 * OTS Signage Modern Theme - Client-Side Utilities
 * Sidebar toggle, dropdown menus, and UI interactions
 */

(function() {
  'use strict';

  const STORAGE_KEYS = {
    sidebarCollapsed: 'otsTheme:sidebarCollapsed'
  };

  /**
   * Initialize sidebar toggle functionality
   */
  function initSidebarToggle() {
    const toggleBtn = document.querySelector('[data-action="toggle-sidebar"]');
    const sidebar = document.querySelector('.ots-sidebar');
    const closeBtn = document.querySelector('.ots-sidebar-close');
    const collapseBtn = document.querySelector('.sidebar-collapse-btn-visible');
    const expandBtn = document.querySelector('.sidebar-expand-btn');
    const body = document.body;

    if (!sidebar) return;

    // Handle sidebar close button
    if (closeBtn) {
      closeBtn.addEventListener('click', function(e) {
        e.preventDefault();
        sidebar.classList.remove('active');
      });
    }

    // Mobile-aware toggle: add backdrop, aria-expanded, and focus management
    if (toggleBtn) {
      let lastFocus = null;
      function ensureBackdrop() {
        let bd = document.querySelector('.ots-backdrop');
        if (!bd) {
          bd = document.createElement('div');
          bd.className = 'ots-backdrop';
          bd.addEventListener('click', function() {
            sidebar.classList.remove('active');
            bd.classList.remove('show');
            toggleBtn.setAttribute('aria-expanded', 'false');
            if (lastFocus) lastFocus.focus();
          });
          document.body.appendChild(bd);
        }
        return bd;
      }

      toggleBtn.setAttribute('role', 'button');
      toggleBtn.setAttribute('aria-controls', 'ots-sidebar');
      toggleBtn.setAttribute('aria-expanded', 'false');

      toggleBtn.addEventListener('click', function(e) {
        e.preventDefault();
        const isNowActive = !sidebar.classList.contains('active');
        sidebar.classList.toggle('active');
        // On small screens show backdrop and manage focus
        if (window.innerWidth <= 768) {
          const bd = ensureBackdrop();
          if (isNowActive) {
            bd.classList.add('show');
            toggleBtn.setAttribute('aria-expanded', 'true');
            lastFocus = document.activeElement;
            // move focus into the sidebar
            const firstFocusable = sidebar.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
            if (firstFocusable) firstFocusable.focus(); else sidebar.setAttribute('tabindex', '-1'), sidebar.focus();
            // add escape handler
            document.addEventListener('keydown', escHandler);
          } else {
            bd.classList.remove('show');
            toggleBtn.setAttribute('aria-expanded', 'false');
            if (lastFocus) lastFocus.focus();
            document.removeEventListener('keydown', escHandler);
          }
        }
      });

      function escHandler(e) {
        if (e.key === 'Escape' || e.key === 'Esc') {
          const bd = document.querySelector('.ots-backdrop');
          if (sidebar.classList.contains('active')) {
            sidebar.classList.remove('active');
            if (bd) bd.classList.remove('show');
            toggleBtn.setAttribute('aria-expanded', 'false');
            if (lastFocus) lastFocus.focus();
            document.removeEventListener('keydown', escHandler);
          }
        }
      }
    }

    if (collapseBtn) {
      let isCollapsed = false;
      try { isCollapsed = localStorage.getItem(STORAGE_KEYS.sidebarCollapsed) === 'true'; } catch(e) {}
      if (isCollapsed) {
        sidebar.classList.add('collapsed');
        body.classList.add('ots-sidebar-collapsed');
        document.documentElement.classList.add('ots-sidebar-collapsed');
        updateSidebarStateClass();
      }

      collapseBtn.addEventListener('click', function(e) {
        e.preventDefault();
        const nowCollapsed = !sidebar.classList.contains('collapsed');
        sidebar.classList.toggle('collapsed');
        body.classList.toggle('ots-sidebar-collapsed', nowCollapsed);
        document.documentElement.classList.toggle('ots-sidebar-collapsed', nowCollapsed);
        try { localStorage.setItem(STORAGE_KEYS.sidebarCollapsed, nowCollapsed ? 'true' : 'false'); } catch(e) {}
        syncSubmenuDisplayForState(nowCollapsed);
        updateSidebarNavOffset();
        updateSidebarStateClass();
        updateSidebarWidth();
        setTimeout(updateSidebarWidth, 250);
      });
    }

    if (expandBtn) {
      expandBtn.addEventListener('click', function(e) {
        e.preventDefault();
        sidebar.classList.remove('collapsed');
        body.classList.remove('ots-sidebar-collapsed');
        document.documentElement.classList.remove('ots-sidebar-collapsed');
        try { localStorage.setItem(STORAGE_KEYS.sidebarCollapsed, 'false'); } catch(e) {}
        syncSubmenuDisplayForState(false);
        updateSidebarNavOffset();
        updateSidebarStateClass();
        updateSidebarWidth();
        setTimeout(updateSidebarWidth, 250);
      });
    }

    // Initialize sidebar section toggles
    initSidebarSectionToggles();

    // Inject flyout headers (icon + label) into each submenu for collapsed state
    buildFlyoutHeaders();

    // Close sidebar when clicking outside on mobile
    document.addEventListener('click', function(e) {
      if (window.innerWidth <= 768) {
        const isClickInsideSidebar = sidebar.contains(e.target);
        const isClickOnToggle = toggleBtn && toggleBtn.contains(e.target);
        
        if (!isClickInsideSidebar && !isClickOnToggle && sidebar.classList.contains('active')) {
          sidebar.classList.remove('active');
        }
      }
    });
  }

  /**
   * Sidebar width is now handled purely by CSS classes (.ots-sidebar-collapsed).
   * This function is kept as a no-op for backward compatibility.
   */
  function updateSidebarWidth() {
    const sidebar = document.querySelector('.ots-sidebar');
    if (!sidebar) return;
    const w = sidebar.offsetWidth;
    document.documentElement.style.setProperty('--ots-sidebar-actual-width', w + 'px');
  }

  /**
   * Measure the sidebar header bottom and set the top padding of the nav list
   * so nav items always begin below the header (logo + buttons).
   */
  function updateSidebarNavOffset() {
    /* No-op: sidebar uses flex-direction:column so the header and
       nav content are separate flex children that never overlap.
       Previously this set padding-top:~72px which created a huge gap. */
    var nav = document.querySelector('.ots-sidebar .sidebar-nav, .ots-sidebar .ots-sidebar-nav');
    if (nav) {
      try { nav.style.removeProperty('padding-top'); } catch(e) { nav.style.paddingTop = ''; }
    }
  }

  // simple debounce helper
  function debounce(fn, wait) {
    let t;
    return function () {
      clearTimeout(t);
      t = setTimeout(() => fn.apply(this, arguments), wait);
    };
  }

  function updateSidebarStateClass() {
    const sidebar = document.querySelector('.ots-sidebar');
    if (!sidebar) return;
    const body = document.body;
    const isCollapsed = sidebar.classList.contains('collapsed');
    if (!isCollapsed) {
      body.classList.add('ots-sidebar-open');
    } else {
      body.classList.remove('ots-sidebar-open');
    }
  }

  /**
   * Build flyout headers for each sidebar-submenu.
   * Pulls the icon class(es) and label from the parent group toggle
   * and injects a styled header <li> at the top of the submenu.
   * Idempotent — skips submenus that already have a header.
   */
  function buildFlyoutHeaders() {
    var groups = document.querySelectorAll('.sidebar-group');
    groups.forEach(function(group) {
      var submenu = group.querySelector('.sidebar-submenu');
      if (!submenu) return;
      // Don't inject twice
      if (submenu.querySelector('.flyout-header')) return;

      var toggle = group.querySelector('.sidebar-group-toggle');
      if (!toggle) return;

      // Grab the icon element's class list and the label text
      var iconEl = toggle.querySelector('.ots-nav-icon');
      var textEl = toggle.querySelector('.ots-nav-text');
      if (!textEl) return;

      var label = textEl.textContent.trim();

      // Build the header <li>
      var header = document.createElement('li');
      header.className = 'flyout-header';
      header.setAttribute('aria-hidden', 'true');

      // Clone the icon
      if (iconEl) {
        var icon = document.createElement('span');
        icon.className = iconEl.className; // copies all fa classes
        icon.classList.add('flyout-header-icon');
        icon.setAttribute('aria-hidden', 'true');
        header.appendChild(icon);
      }

      var text = document.createElement('span');
      text.className = 'flyout-header-text';
      text.textContent = label;
      header.appendChild(text);

      submenu.insertBefore(header, submenu.firstChild);
    });
  }

  /**
   * When toggling between collapsed/expanded, sync all submenu inline
   * display styles so that:
   *  - Collapsed: no inline display → CSS :hover handles flyouts
   *  - Expanded:  inline display block/none based on is-open state
   */
  function syncSubmenuDisplayForState(isCollapsed) {
    var groups = document.querySelectorAll('.sidebar-group');
    groups.forEach(function(group) {
      var submenu = group.querySelector('.sidebar-submenu');
      if (!submenu) return;
      if (isCollapsed) {
        // Remove inline display so CSS visibility/opacity hover rules work
        submenu.style.removeProperty('display');
      } else {
        // Expanded mode: show/hide based on is-open class
        var isOpen = group.classList.contains('is-open');
        submenu.style.display = isOpen ? 'block' : 'none';
      }
    });
  }

  /**
   * Initialize sidebar section collapse/expand functionality
   */
  function initSidebarSectionToggles() {
    const groupToggles = document.querySelectorAll('.sidebar-group-toggle');

    syncSidebarActiveStates();

    groupToggles.forEach(toggle => {
      const group = toggle.closest('.sidebar-group');
      const submenu = group ? group.querySelector('.sidebar-submenu') : null;
      const caret = toggle.querySelector('.sidebar-group-caret');
      if (submenu) {
        const isOpen = group.classList.contains('is-open');
        // Only set inline display when sidebar is NOT collapsed;
        // collapsed state uses CSS :hover to show flyout menus.
        const sidebarEl = document.querySelector('.ots-sidebar');
        const isCollapsed = sidebarEl && sidebarEl.classList.contains('collapsed');
        if (!isCollapsed) {
          submenu.style.display = isOpen ? 'block' : 'none';
        } else {
          // Clear any leftover inline display so CSS :hover can work
          submenu.style.removeProperty('display');
        }
        toggle.setAttribute('aria-expanded', isOpen.toString());
      }

      toggle.addEventListener('click', function(e) {
        e.preventDefault();

        const group = toggle.closest('.sidebar-group');
        const submenu = group ? group.querySelector('.sidebar-submenu') : null;
        if (!submenu) return;

        const sidebarEl = document.querySelector('.ots-sidebar');
        const isCollapsed = sidebarEl && sidebarEl.classList.contains('collapsed');

        // When collapsed, don't toggle submenus on click — hover handles it
        if (isCollapsed) return;

        const isOpen = group.classList.contains('is-open');
        group.classList.toggle('is-open', !isOpen);
        toggle.setAttribute('aria-expanded', (!isOpen).toString());
        submenu.style.display = isOpen ? 'none' : 'block';
        syncSidebarActiveStates();
      });

      if (caret) {
        caret.addEventListener('click', function(e) {
          e.preventDefault();
          e.stopPropagation();
          toggle.click();
        });
      }
    });
  }

  function syncSidebarActiveStates() {
    const groups = document.querySelectorAll('.sidebar-group');
    groups.forEach(group => {
      const toggle = group.querySelector('.sidebar-group-toggle');
      if (!toggle) return;

      const hasActiveChild = Boolean(
        group.querySelector('.sidebar-list.active') ||
        group.querySelector('.sidebar-list > a.active')
      );

      toggle.classList.toggle('active', hasActiveChild);

      if (hasActiveChild) {
        group.classList.add('is-open');
        const submenu = group.querySelector('.sidebar-submenu');
        if (submenu) submenu.style.display = 'block';
        toggle.setAttribute('aria-expanded', 'true');
      }
    });
  }

  /**
   * Initialize dropdown menus
   */
  function initDropdowns() {
    // Only handle OTS-specific dropdowns (notifications, etc.).
    // The user menu (#navbarUserMenu) is handled by theme-scripts.twig's
    // initDropdowns() which uses floatMenu() for proper positioning.
    // Let Bootstrap handle topbar nav dropdowns (Schedule, Design, etc.) natively
    // so that links like Dayparting can navigate normally.
    const otsDropdowns = Array.from(
      document.querySelectorAll('.ots-topbar-action .dropdown, .ots-page-actions .dropdown')
    ).filter(function(el) {
      // Exclude the user menu — it has its own dedicated handler in theme-scripts.twig
      return !el.querySelector('#navbarUserMenu');
    });

    otsDropdowns.forEach(dropdown => {
      const toggle = dropdown.querySelector('.dropdown-toggle, [data-toggle="dropdown"]');
      const menu = dropdown.querySelector('.dropdown-menu');

      if (!toggle || !menu) return;

      // Toggle menu on toggle click
      toggle.addEventListener('click', function(e) {
        e.preventDefault();
        e.stopPropagation();
        const isNowActive = dropdown.classList.toggle('active');

        // Close other OTS dropdowns
        otsDropdowns.forEach(other => {
          if (other !== dropdown) other.classList.remove('active');
        });
      });

      // Close menu when clicking outside
      document.addEventListener('click', function(e) {
        if (!dropdown.contains(e.target)) {
          dropdown.classList.remove('active');
        }
      });
    });
    // Support DataTables Buttons collections which are not wrapped by .dropdown
    document.addEventListener('click', function(e) {
      const btn = e.target.closest('.dt-button');

      if (btn) {
        e.preventDefault();
        e.stopPropagation();

        const wrapper = btn.closest('.dt-buttons') || btn.parentElement;

        // close other open dt-buttons collections
        document.querySelectorAll('.dt-buttons.active').forEach(w => {
          if (w !== wrapper) w.classList.remove('active');
        });

        wrapper.classList.toggle('active');

        // If DataTables placed the collection on the body, find it and position it under the clicked button
        const allCollections = Array.from(document.querySelectorAll('.dt-button-collection'));
        let collection = wrapper.querySelector('.dt-button-collection') || allCollections.find(c => !wrapper.contains(c));

        // If DataTables didn't create a collection element, create one as a fallback
        if (!collection) {
          collection = document.createElement('div');
          collection.className = 'dt-button-collection';
          // prefer to append near wrapper for positioning; fallback to body
          (wrapper || document.body).appendChild(collection);
        }

        if (collection) {
          // hide other collections
          allCollections.forEach(c => { if (c !== collection) { c.classList.remove('show'); c.style.display = 'none'; } });

          const rect = btn.getBoundingClientRect();
          const top = rect.bottom + window.scrollY;
          const left = rect.left + window.scrollX;

          collection.style.position = 'absolute';
          collection.style.top = `${top}px`;
          collection.style.left = `${left}px`;
          collection.style.display = 'block';
          collection.classList.add('show');

          // If the collection is empty or visually empty, build a fallback column list from the nearest table
          const isEmpty = collection.children.length === 0 || collection.textContent.trim() === '' || collection.offsetHeight < 10;
          if (isEmpty) {
            try {
              let table = btn.closest('table') || wrapper.querySelector('table') || document.querySelector('table');
              if (table && window.jQuery && jQuery.fn && jQuery.fn.dataTable && jQuery.fn.dataTable.isDataTable(table)) {
                const dt = jQuery(table).DataTable();
                // clear existing
                collection.innerHTML = '';
                const thead = table.querySelectorAll('thead th');
                thead.forEach((th, idx) => {
                  const text = (th.textContent || th.innerText || `Column ${idx+1}`).trim();
                  const item = document.createElement('div');
                  item.style.padding = '6px 12px';
                  item.style.display = 'flex';
                  item.style.alignItems = 'center';
                  item.style.gap = '8px';
                  const checkbox = document.createElement('input');
                  checkbox.type = 'checkbox';
                  checkbox.checked = dt.column(idx).visible();
                  checkbox.addEventListener('change', function() {
                    dt.column(idx).visible(this.checked);
                  });
                  const label = document.createElement('span');
                  label.textContent = text;
                  label.style.color = 'var(--color-text-primary)';
                  item.appendChild(checkbox);
                  item.appendChild(label);
                  collection.appendChild(item);
                });
              } else {
                // no DataTable instance found
              }
            } catch (err) {
              // column list fallback failed
            }
          }
        }

        return;
      }

      // click outside dt-button -> close any open collections
      document.querySelectorAll('.dt-buttons.active').forEach(w => w.classList.remove('active'));
    });
  }

  /**
   * Initialize search functionality
   */
  function initSearch() {
    const searchForm = document.querySelector('.topbar-search');
    if (!searchForm) return;

    const input = searchForm.querySelector('.search-input');
    if (input) {
      input.addEventListener('focus', function() {
        searchForm.style.borderColor = 'var(--color-primary)';
      });
      input.addEventListener('blur', function() {
        searchForm.style.borderColor = 'var(--color-border)';
      });
    }
  }

  /**
   * Initialize page specific interactions
   */
  function initPageInteractions() {
    // Displays page - folder selection
    const folderItems = document.querySelectorAll('.folder-item');
    folderItems.forEach(item => {
      item.addEventListener('click', function() {
        folderItems.forEach(f => f.classList.remove('active'));
        this.classList.add('active');
      });
    });

    // Media page - item selection
    const mediaItems = document.querySelectorAll('.media-item');
    mediaItems.forEach(item => {
      item.addEventListener('click', function() {
        this.style.opacity = '0.7';
        setTimeout(() => this.style.opacity = '1', 200);
      });
    });
  }

  /**
   * Make sidebar responsive
   */
  function makeResponsive() {
    const sidebar = document.querySelector('.ots-sidebar');
    const main = document.querySelector('.ots-main');
    
    if (!sidebar) return;
    
    // Add toggle button for mobile
    if (window.innerWidth <= 768) {
      sidebar.classList.add('mobile');
    }
    
    window.addEventListener('resize', function() {
      if (window.innerWidth > 768) {
        sidebar.classList.remove('mobile', 'active');
      } else {
        sidebar.classList.add('mobile');
      }
      // Recompute sidebar width on resize
      updateSidebarWidth();
    });
  }

  /**
   * Prevent Chart.js errors when chart elements are missing
   */
  function initChartSafeguard() {
    if (!window.Chart) return;

    if (typeof window.Chart.acquireContext === 'function') {
      window.Chart.acquireContext = function(item) {
        if (!item) return null;

        const candidate = item.length ? item[0] : item;
        if (candidate && typeof candidate.getContext === 'function') {
          return candidate.getContext('2d');
        }

        return null;
      };
      return;
    }

    if (window.Chart.prototype && typeof window.Chart.prototype.acquireContext === 'function') {
      window.Chart.prototype.acquireContext = function(item) {
        if (!item) return null;

        const candidate = item.length ? item[0] : item;
        if (candidate && typeof candidate.getContext === 'function') {
          return candidate.getContext('2d');
        }

        return null;
      };
    }
  }

  /**
   * Enhance tables: wrap in card, add per-table search box, client-side filtering
   * Non-destructive: skips tables already enhanced
   */
  function enhanceTables() {
    const selector = '.ots-content table, .content table, .container table, .card table, table';
    const tables = Array.from(document.querySelectorAll(selector));
    let counter = 0;

    tables.forEach(table => {
      // only enhance tables that have a thead and tbody
      if (!table || table.classList.contains('modern-table')) return;
      if (!table.querySelector('thead') || !table.querySelector('tbody')) return;

      counter += 1;
      table.classList.add('modern-table');

      // Build wrapper structure
      const wrapper = document.createElement('div');
      wrapper.className = 'modern-table-card';

      const controls = document.createElement('div');
      controls.className = 'table-controls';

      const input = document.createElement('input');
      input.type = 'search';
      input.placeholder = 'Search…';
      input.className = 'table-search-input';
      input.setAttribute('aria-label', 'Table search');
      input.style.minWidth = '180px';

      controls.appendChild(input);

      const tableWrapper = document.createElement('div');
      tableWrapper.className = 'table-wrapper';
      tableWrapper.style.overflow = 'auto';

      // Insert wrapper into DOM in place of the table
      const parent = table.parentNode;
      parent.replaceChild(wrapper, table);
      wrapper.appendChild(controls);
      wrapper.appendChild(tableWrapper);
      tableWrapper.appendChild(table);

      // Simple, light-weight search filtering for this table only
      input.addEventListener('input', function (e) {
        const term = (e.target.value || '').toLowerCase();
        table.querySelectorAll('tbody tr').forEach(tr => {
          const text = tr.textContent.toLowerCase();
          tr.style.display = term === '' || text.includes(term) ? '' : 'none';
        });
      });
    });
  }

  /**
   * Initialize DataTables for enhanced behavior when available.
   * Falls back gracefully if DataTables or jQuery are not present.
   */
  function initDataTables() {
    if (!window.jQuery) return;
    const $ = window.jQuery;
    if (!$.fn || !$.fn.dataTable) return;

    $('.modern-table, table').each(function () {
      try {
        if (!$.fn.dataTable.isDataTable(this)) {
          $(this).DataTable({
            responsive: true,
            lengthChange: false,
            pageLength: 10,
            autoWidth: false,
            dom: '<"table-controls"f>rt<"table-meta"ip>',
            language: { search: '' }
          });
        }
      } catch (err) {
        // If initialization fails, ignore and allow fallback enhancer
        console.warn('DataTables init failed for table', this, err);
      }
    });
  }

  /**
   * Close every open dropdown / popover on the page.
   * Covers: Bootstrap 4 native dropdowns, OTS custom dropdowns,
   * the user-menu, notification drawer, and DataTable row menus.
   */
  function closeAllDropdowns() {
    try {
      // Row dropdown menus appended to body
      document.querySelectorAll('.ots-row-dropdown').forEach(function(m) {
        m.classList.remove('show', 'ots-row-dropdown');
        m.style.cssText = '';
      });

      document.querySelectorAll('.dropdown.show, .btn-group.show').forEach(function(el) {
        el.classList.remove('show');
        var m = el.querySelector('.dropdown-menu.show');
        if (m) m.classList.remove('show');
      });
      document.querySelectorAll('.dropdown-menu.show').forEach(function(m) {
        m.classList.remove('show');
      });
      document.querySelectorAll('.dropdown.active, .ots-topbar-action .dropdown.active, .ots-page-actions .dropdown.active').forEach(function(el) {
        el.classList.remove('active');
      });
      var userMenu = document.querySelector('.ots-user-menu-body.ots-user-menu-open');
      if (userMenu) {
        userMenu.classList.remove('ots-user-menu-open');
        var userToggle = document.querySelector('#navbarUserMenu');
        if (userToggle) {
          var dd = userToggle.closest('.dropdown');
          if (dd) dd.classList.remove('active', 'show');
        }
      }
      document.querySelectorAll('.dt-buttons.active').forEach(function(w) { w.classList.remove('active'); });
      document.querySelectorAll('.dt-button-collection.show').forEach(function(c) { c.classList.remove('show'); c.style.display = 'none'; });
      if (window.jQuery) {
        window.jQuery('.dropdown-toggle[aria-expanded="true"]').attr('aria-expanded', 'false');
        window.jQuery('.dropdown-menu.show').removeClass('show');
        window.jQuery('.dropdown.show, .btn-group.show').removeClass('show');
      }
    } catch (err) {}
  }

  /**
   * Wire up global listeners that trigger closeAllDropdowns().
   */
  function initGlobalDropdownDismiss() {
    document.addEventListener('show.bs.modal', closeAllDropdowns, true);
    try {
      if (window.jQuery) {
        window.jQuery(document).on('show.bs.modal', closeAllDropdowns);
        window.jQuery(document).on('click', '.XiboFormButton, .XiboAjaxSubmit, .XiboFormRender', function() {
          closeAllDropdowns();
        });
      }
    } catch (e) {}

    document.addEventListener('click', function(e) {
      var link = e.target.closest('.dropdown-menu a, .ots-topbar a.nav-link, .ots-topbar a.dropdown-item, .XiboFormButton');
      if (link && !e.defaultPrevented) {
        closeAllDropdowns();
      }
    });

    window.addEventListener('popstate', closeAllDropdowns);
    try {
      var origPush = history.pushState;
      var origReplace = history.replaceState;
      history.pushState = function() { origPush.apply(this, arguments); closeAllDropdowns(); };
      history.replaceState = function() { origReplace.apply(this, arguments); closeAllDropdowns(); };
    } catch (e) {}

    try {
      var content = document.getElementById('content') || document.querySelector('.ots-content');
      if (content) {
        var contentObs = new MutationObserver(debounce(closeAllDropdowns, 80));
        contentObs.observe(content, { childList: true });
      }
    } catch (e) {}
  }

  /**
   * Initialize all features when DOM is ready
   */
  function init() {
    initSidebarToggle();
    initDropdowns();
    initGlobalDropdownDismiss();
    initSearch();
    initPageInteractions();
    initDataTables();
    enhanceTables();
    makeResponsive();
    initChartSafeguard();
    // Set initial sidebar width variable and keep it updated
    updateSidebarWidth();
    // Set initial nav offset and keep it updated on resize
    updateSidebarNavOffset();
    const debouncedUpdateNavOffset = debounce(function() {
      updateSidebarNavOffset();
      updateSidebarWidth();
    }, 120);
    window.addEventListener('resize', debouncedUpdateNavOffset);
  }

  // Wait for DOM to be ready
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();