<!-- #region Sidebar [C:4] [TYPE Component] [SEMANTICS sidebar, navigation, sections, toggle, resource] -->
<!-- @BRIEF Persistent left sidebar with grouped sections (Resources/Operations/System), expand/collapse, health indicators, RBAC filtering, profile footer. -->
<!-- @LAYER UI -->
<!-- @RELATION BINDS_TO -> [EXT:frontend:sidebarStore] -->
<!-- @RELATION BINDS_TO -> [EXT:frontend:healthStore] -->
<!-- @RELATION BINDS_TO -> [EXT:frontend:authStore] -->
<!-- @RELATION DEPENDS_ON -> [Icon] -->
<!-- @UX_STATE Idle -> Sidebar visible with current state. -->
<!-- @UX_STATE Toggling -> Animation plays for 200ms on expand/collapse. -->
<!-- @UX_STATE MobileOpen -> Overlay and sidebar visible until dismissed. -->
<!-- @UX_FEEDBACK Active item highlighted with different background; section labels visible when expanded. -->
<!-- @UX_FEEDBACK Badge count shown on failing dashboards. -->
<!-- @UX_FEEDBACK Profile footer shows user avatar and username. -->
<!-- @UX_RECOVERY Click outside on mobile closes overlay. -->
<script lang="ts">
  import { page } from "$app/state";
  import {
    sidebarStore,
    toggleSidebar,
    setActiveItem,
    closeMobile,
  } from "$lib/stores/sidebar.svelte.js";
  import { healthStore, failingCount } from "$lib/stores/health.svelte.js";
  import { onMount } from "svelte";
  import { t } from "$lib/i18n/index.svelte.js";
  import { auth } from "$lib/auth/store.svelte.js";
  import { buildSidebarSections } from "$lib/components/layout/sidebarNavigation.js";
  import { fetchApi } from "$lib/api.js";
  import { browser } from "$app/environment";
  import { goto } from "$app/navigation";
  import Icon from "$lib/ui/Icon.svelte";

  let _authState = $state({ user: null, token: null, isAuthenticated: false, loading: true });
  $effect(() => {
    const unsub = auth.subscribe(v => { _authState = v; });
    return unsub;
  });

  let features = $state({});
  let cleanupInterval = null;

  let sections = $derived(
    buildSidebarSections(
      t,
      _authState.user || null,
      features,
    ),
  );

  // Flat categories list for fallback resolution
  let allCategories = $derived(sections.flatMap((s) => s.categories));

  let isExpanded = $derived(sidebarStore.value?.isExpanded ?? true);
  let activeCategory = $derived(
    sidebarStore.value?.activeCategory || "dashboards",
  );
  let activeItem = $derived(sidebarStore.value?.activeItem || "/dashboards");
  let isMobileOpen = $derived(Boolean(sidebarStore.value?.isMobileOpen));
  let failingDashboardCount = $derived(failingCount.current || 0);
  let expandedCategories = $state(new Set(["dashboards"]));
  let expandedSections = $state(new Set(["resources", "operations", "system"]));

  let user = $derived(_authState.user || null);

  function withExpandedCategory(categoryId) {
    const next = new Set(expandedCategories);
    next.add(categoryId);
    expandedCategories = next;
  }

  function toggleExpandedCategory(categoryId) {
    const next = new Set(expandedCategories);
    if (next.has(categoryId)) {
      next.delete(categoryId);
    } else {
      next.add(categoryId);
    }
    expandedCategories = next;
  }

  function toggleExpandedSection(sectionId) {
    const next = new Set(expandedSections);
    if (next.has(sectionId)) {
      next.delete(sectionId);
    } else {
      next.add(sectionId);
    }
    expandedSections = next;
  }

  // Keep active category valid after RBAC filtering.
  $effect(() => {
    if (
      allCategories.length > 0 &&
      !allCategories.some((cat) => cat.id === activeCategory)
    ) {
      const fallbackCategory = allCategories[0];
      const fallbackPath =
        fallbackCategory.subItems?.[0]?.path || fallbackCategory.path;
      setActiveItem(fallbackCategory.id, fallbackPath);
    }
  });

  // Keep active category expanded after route/user change.
  $effect(() => {
    if (activeCategory && !expandedCategories.has(activeCategory)) {
      withExpandedCategory(activeCategory);
    }
  });

  // Update active item when page changes
  $effect(() => {
    if (page.url.pathname !== activeItem) {
      const matched = allCategories.find((cat) => {
        if (page.url.pathname.startsWith(cat.path)) return true;
        return (cat.subItems || []).some((item) =>
          page.url.pathname.startsWith(item.path),
        );
      });
      if (matched) {
        setActiveItem(matched.id, page.url.pathname);
      }
    }
  });

  function handleCategoryToggle(categoryId, event) {
    event.stopPropagation();

    if (!isExpanded) {
      toggleSidebar();
      withExpandedCategory(categoryId);
      return;
    }

    toggleExpandedCategory(categoryId);
  }

  function handleSubItemClick(categoryId, path) {
    setActiveItem(categoryId, path);
    closeMobile();
    if (browser) {
      window.location.href = path;
    }
  }

  function handleToggleClick(event) {
    event.stopPropagation();
    toggleSidebar();
  }

  function handleOverlayClick() {
    closeMobile();
  }

  function handleProfileClick() {
    closeMobile();
    if (browser) {
      window.location.href = "/profile";
    }
  }

  function handleSettingsClick(e) {
    e.stopPropagation();
    closeMobile();
    if (browser) {
      window.location.href = "/settings";
    }
  }

  function getInitials(user) {
    if (!user) return "?";
    if (user.display_name) return user.display_name.charAt(0).toUpperCase();
    if (user.username) return user.username.charAt(0).toUpperCase();
    if (user.email) return user.email.charAt(0).toUpperCase();
    return "?";
  }

  // Close mobile overlay on route change
  $effect(() => {
    const _pathname = page.url.pathname;
    closeMobile();
  });

  onMount(() => {
    fetchApi("/settings/features")
      .then((res) => {
        features = res;
        if (res.health_monitor) {
          healthStore.refresh();
          const interval = setInterval(() => healthStore.refresh(), 5 * 60 * 1000);
          cleanupInterval = interval;
        }
      })
      .catch(() => {
        features = {};
        healthStore.refresh().then(() => {
          const interval = setInterval(() => healthStore.refresh(), 5 * 60 * 1000);
          cleanupInterval = interval;
        }).catch(() => {});
      });

    return () => {
      if (cleanupInterval) clearInterval(cleanupInterval);
    };
  });
</script>

<!-- Mobile overlay (only on mobile) -->
{#if isMobileOpen}
  <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
  <div
    class="fixed inset-0 bg-black/50 z-20 md:hidden"
    onclick={handleOverlayClick}
    role="presentation"
  ></div>
{/if}

<!-- Sidebar -->
<div
  class="fixed left-0 top-0 z-30 flex h-screen flex-col border-r border-slate-200 bg-white shadow-sm transition-[width] duration-200 ease-in-out
    {isExpanded ? 'w-sidebar' : 'w-sidebar-collapsed'}
    {isMobileOpen
    ? 'translate-x-0 w-sidebar'
    : '-translate-x-full md:translate-x-0'}"
>
  <!-- ═══ HEADER: Logo + Collapse ═══ -->
  <div
    class="flex items-center border-b border-slate-200 px-3 py-3 {isExpanded
      ? 'justify-between'
      : 'justify-center'}"
  >
    {#if isExpanded}
      <span class="font-semibold text-gray-800 flex items-center gap-2 text-sm">
        <span
          class="inline-flex h-7 w-7 items-center justify-center rounded-md bg-gradient-to-br from-primary-light to-blue-100 text-primary ring-1 ring-primary-ring"
        >
          <Icon name="layers" size={15} />
        </span>
        {t.nav?.menu || "Menu"}
      </span>
      <button
        onclick={handleToggleClick}
        class="flex h-7 w-7 items-center justify-center rounded-md text-gray-400 hover:bg-gray-100 hover:text-gray-600 transition-colors"
        aria-label={t.nav?.collapse}
        title={t.nav?.collapse}
      >
        <Icon name="chevronLeft" size={15} />
      </button>
    {:else}
      <span
        class="inline-flex h-7 w-7 items-center justify-center rounded-md bg-gradient-to-br from-primary-light to-blue-100 text-primary ring-1 ring-primary-ring"
      >
        <Icon name="layers" size={15} />
      </span>
      <button
        onclick={handleToggleClick}
        class="flex h-7 w-7 items-center justify-center rounded-md text-gray-400 hover:bg-gray-100 hover:text-gray-600 transition-colors ml-1"
        aria-label={t.nav?.expand}
        title={t.nav?.expand}
      >
        <Icon name="chevronRight" size={15} />
      </button>
    {/if}
  </div>

  <!-- ═══ NAVIGATION: Sections with categories ═══ -->
  <nav class="flex-1 overflow-y-auto py-1">
    {#each sections as section}
      <!-- Section label (only when expanded) -->
      {#if isExpanded}
        <div
          class="flex items-center justify-between px-4 pt-4 pb-1 cursor-pointer select-none"
          onclick={() => toggleExpandedSection(section.id)}
          onkeydown={(e) => (e.key === "Enter") && toggleExpandedSection(section.id)}
          role="button"
          tabindex="0"
          aria-expanded={expandedSections.has(section.id)}
        >
          <span class="text-[11px] font-semibold uppercase tracking-widest text-gray-400">
            {section.label}
          </span>
          <Icon
            name="chevronDown"
            size={12}
            className="text-gray-300 transition-transform duration-200 {expandedSections.has(section.id) ? '' : '-rotate-90'}"
          />
        </div>
      {/if}

      <!-- Section categories -->
      {#if !isExpanded || expandedSections.has(section.id)}
        {#each section.categories as category}
          <div>
            <!-- Category Header -->
            <div
              class="mx-2 flex cursor-pointer items-center justify-between rounded-lg px-2 py-2 transition-colors hover:bg-slate-100
                {activeCategory === category.id
                ? 'bg-primary-light text-primary'
                : 'text-gray-600'}"
              onclick={(e) => handleCategoryToggle(category.id, e)}
              onkeydown={(e) =>
                (e.key === "Enter" || e.key === " ") &&
                handleCategoryToggle(category.id, e)}
              role="button"
              tabindex="0"
              aria-label={category.label}
              aria-expanded={expandedCategories.has(category.id)}
            >
              <div class="flex items-center min-w-0">
                <span
                  class="relative inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br ring-1 transition-all {category.tone}"
                >
                  <Icon name={category.icon} size={15} strokeWidth={2} />
                  {#if !isExpanded && category.id === "dashboards" && failingDashboardCount > 0}
                    <span
                      class="absolute -top-1 -right-1 flex h-2.5 w-2.5 items-center justify-center rounded-full bg-red-500 ring-2 ring-white"
                    ></span>
                  {/if}
                </span>
                {#if isExpanded}
                  <span class="ml-3 text-sm font-medium truncate"
                    >{category.label}</span
                  >
                  {#if category.id === "dashboards" && failingDashboardCount > 0}
                    <span
                      class="ml-auto mr-1 inline-flex items-center justify-center px-1.5 py-0.5 text-[10px] font-bold leading-none text-white bg-red-500 rounded-full"
                      title="{failingDashboardCount} failing dashboards"
                    >
                      {failingDashboardCount}
                    </span>
                  {/if}
                {/if}
              </div>
              {#if isExpanded}
                <Icon
                  name="chevronDown"
                  size={14}
                  className="shrink-0 text-gray-400 transition-transform duration-200 {expandedCategories.has(
                    category.id,
                  )
                    ? 'rotate-180'
                    : ''}"
                />
              {/if}
            </div>

            <!-- Sub Items (only when expanded) -->
            {#if isExpanded && expandedCategories.has(category.id)}
              <div class="overflow-hidden transition-all duration-200">
                {#each category.subItems as subItem}
                  <div
                    class="mx-2 flex items-center rounded-md px-2 py-1.5 pl-10 cursor-pointer transition-colors text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-900
                      {activeItem === subItem.path
                      ? 'bg-primary-light text-primary font-medium'
                      : ''}"
                    onclick={() => handleSubItemClick(category.id, subItem.path)}
                    onkeydown={(e) =>
                      (e.key === "Enter" || e.key === " ") &&
                      handleSubItemClick(category.id, subItem.path)}
                    role="button"
                    tabindex="0"
                  >
                    {subItem.label}
                  </div>
                {/each}
              </div>
            {/if}
          </div>
        {/each}
      {/if}
    {/each}
  </nav>

  <!-- ═══ FOOTER: Profile + Settings + Collapse ═══ -->
  <div class="border-t border-gray-200">
    {#if isExpanded}
      <!-- Expanded footer: profile info + settings gear -->
      <div class="flex items-center justify-between px-3 py-3">
        <button
          onclick={handleProfileClick}
          class="flex items-center gap-2 min-w-0 rounded-lg px-2 py-1.5 text-sm text-gray-600 hover:bg-gray-100 transition-colors"
        >
          <span
            class="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-indigo-100 to-indigo-200 text-indigo-700 text-xs font-bold ring-1 ring-indigo-200"
          >
            {getInitials(user)}
          </span>
          <span class="truncate max-w-[120px]">
            {user?.display_name || user?.username || user?.email || "Profile"}
          </span>
        </button>
        <div class="flex items-center gap-1">
          <button
            onclick={handleSettingsClick}
            class="flex h-7 w-7 items-center justify-center rounded-md text-gray-400 hover:bg-gray-100 hover:text-gray-600 transition-colors"
            aria-label={t.nav?.settings}
            title={t.nav?.settings}
          >
            <Icon name="settings" size={15} />
          </button>
        </div>
      </div>
    {:else}
      <!-- Collapsed footer: just avatar + expand -->
      <div class="flex flex-col items-center gap-1 px-2 py-3">
        <button
          onclick={handleProfileClick}
          class="flex items-center justify-center rounded-lg px-1 py-1 hover:bg-gray-100 transition-colors"
          aria-label={t.nav?.profile}
          title={t.nav?.profile}
        >
          <span
            class="inline-flex h-7 w-7 items-center justify-center rounded-full bg-gradient-to-br from-indigo-100 to-indigo-200 text-indigo-700 text-xs font-bold ring-1 ring-indigo-200"
          >
            {getInitials(user)}
          </span>
        </button>
        <button
          onclick={handleToggleClick}
          class="flex h-7 w-7 items-center justify-center rounded-md text-gray-400 hover:bg-gray-100 hover:text-gray-600 transition-colors"
          aria-label={t.nav?.expand}
          title={t.nav?.expand}
        >
          <Icon name="chevronRight" size={15} />
        </button>
      </div>
    {/if}
  </div>
</div>

<!-- #endregion Sidebar -->
