<!-- [DEF:Sidebar:Component] -->
<script>
  /**
   * @TIER: CRITICAL
   * @PURPOSE: Persistent left sidebar with resource categories navigation
   * @LAYER: UI
   * @RELATION: BINDS_TO -> sidebarStore
   * @SEMANTICS: Navigation
   * @INVARIANT: Always shows active category and item
   *
   * @UX_STATE: Idle -> Sidebar visible with current state
   * @UX_STATE: Toggling -> Animation plays for 200ms
   * @UX_FEEDBACK: Active item highlighted with different background
   * @UX_RECOVERY: Click outside on mobile closes overlay
   *
   * @TEST_CONTRACT Component_Sidebar ->
   * {
   *   required_props: {},
   *   optional_props: {},
   *   invariants: [
   *       "Highlights active category and sub-item based on current page URL",
   *       "Toggles sidebar via toggleSidebar store action",
   *       "Closes mobile overlay on click outside"
   *   ]
   * }
   * @TEST_FIXTURE idle_state -> {}
   * @TEST_EDGE mobile_open -> shows mobile overlay mask
   * @TEST_INVARIANT navigation -> verifies: [idle_state]
   */

  import { page } from "$app/state";
  import { fromStore } from "svelte/store";
  import {
    sidebarStore,
    toggleSidebar,
    setActiveItem,
    closeMobile,
  } from "$lib/stores/sidebar.js";
  import { healthStore, failingCount } from "$lib/stores/health.js";
  import { onMount } from "svelte";
  import { t } from "$lib/i18n";
  import { auth } from "$lib/auth/store.js";
  import { buildSidebarCategories } from "$lib/components/layout/sidebarNavigation.js";
  import { browser } from "$app/environment";
  import Icon from "$lib/ui/Icon.svelte";

  const sidebarState = fromStore(sidebarStore);
  const translationState = fromStore(t);
  const authState = fromStore(auth);
  const failingCountState = fromStore(failingCount);

  let categories = $derived(
    buildSidebarCategories(
      translationState.current,
      authState.current?.user || null,
    ),
  );

  let isExpanded = $derived(sidebarState.current?.isExpanded ?? true);
  let activeCategory = $derived(
    sidebarState.current?.activeCategory || "dashboards",
  );
  let activeItem = $derived(sidebarState.current?.activeItem || "/dashboards");
  let isMobileOpen = $derived(Boolean(sidebarState.current?.isMobileOpen));
  let failingDashboardCount = $derived(failingCountState.current || 0);
  let expandedCategories = $state(new Set(["dashboards"]));

  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;
  }

  // Keep active category valid after RBAC filtering.
  $effect(() => {
    if (
      categories.length > 0 &&
      !categories.some((category) => category.id === activeCategory)
    ) {
      const fallbackCategory = categories[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 = categories.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 handleItemClick(category) {
    console.log(`[Sidebar][Action] Clicked category ${category.id}`);
    setActiveItem(category.id, category.path);
    closeMobile();
    if (browser) {
      window.location.href = category.path;
    }
  }

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

    if (!isExpanded) {
      console.log(
        `[Sidebar][Action] Expand sidebar and category ${categoryId}`,
      );
      toggleSidebar();
      withExpandedCategory(categoryId);
      return;
    }

    console.log(`[Sidebar][Action] Toggle category ${categoryId}`);
    toggleExpandedCategory(categoryId);
  }

  function handleSubItemClick(categoryId, path) {
    console.log(`[Sidebar][Action] Clicked sub-item ${path}`);
    setActiveItem(categoryId, path);
    closeMobile();
    if (browser) {
      window.location.href = path;
    }
  }

  function handleToggleClick(event) {
    event.stopPropagation();
    console.log("[Sidebar][Action] Toggle sidebar");
    toggleSidebar();
  }

  function handleOverlayClick() {
    console.log("[Sidebar][Action] Close mobile overlay");
    closeMobile();
  }

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

  onMount(() => {
    healthStore.refresh();
    // Refresh every 5 minutes
    const interval = setInterval(() => healthStore.refresh(), 5 * 60 * 1000);
    return () => clearInterval(interval);
  });
</script>

<!-- Mobile overlay (only on mobile) -->
{#if isMobileOpen}
  <div
    class="fixed inset-0 bg-black/50 z-20 md:hidden"
    onclick={handleOverlayClick}
    onkeydown={(e) => e.key === "Escape" && 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 -->
  <div
    class="flex items-center border-b border-slate-200 p-4 {isExpanded
      ? 'justify-between'
      : 'justify-center'}"
  >
    {#if isExpanded}
      <span class="font-semibold text-gray-800 flex items-center gap-2">
        <span
          class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br from-slate-100 to-slate-200 text-slate-700 ring-1 ring-slate-200"
        >
          <Icon name="layers" size={14} />
        </span>
        {translationState.current?.nav?.menu}
      </span>
    {:else}
      <span class="text-xs text-gray-500">M</span>
    {/if}
  </div>

  <!-- Navigation items -->
  <nav class="flex-1 overflow-y-auto py-2">
    {#each categories as category}
      <div>
        <!-- Category Header -->
        <div
          class="flex cursor-pointer items-center justify-between px-4 py-3 transition-colors hover:bg-slate-100
            {activeCategory === category.id
            ? 'bg-primary-light text-primary md:border-r-2 md:border-primary'
            : ''}"
          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">
            <span
              class="relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br ring-1 transition-all {category.tone}"
            >
              <Icon name={category.icon} size={16} strokeWidth={2} />
              {#if !isExpanded && category.id === "dashboards" && failingDashboardCount > 0}
                <span
                  class="absolute -top-1 -right-1 flex h-3 w-3 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-2 inline-flex items-center justify-center px-2 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={16}
              className="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="bg-gray-50 overflow-hidden transition-all duration-200">
            {#each category.subItems as subItem}
              <div
                class="flex items-center px-4 py-2 pl-12 cursor-pointer transition-colors text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900
                  {activeItem === subItem.path
                  ? 'bg-primary-light text-primary'
                  : ''}"
                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}
  </nav>

  <!-- Footer with Collapse button -->
  {#if isExpanded}
    <div class="border-t border-gray-200 p-4">
      <button
        class="flex items-center justify-center w-full px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
        onclick={handleToggleClick}
      >
        <span
          class="mr-2 inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-100 text-slate-600"
        >
          <Icon name="chevronLeft" size={14} />
        </span>
        {translationState.current?.nav?.collapse}
      </button>
    </div>
  {:else}
    <div class="border-t border-gray-200 p-4">
      <button
        class="flex items-center justify-center w-full px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
        onclick={handleToggleClick}
        aria-label={translationState.current?.nav?.expand_sidebar}
      >
        <Icon name="chevronRight" size={16} />
        <span class="ml-2">{translationState.current?.nav?.expand}</span>
      </button>
    </div>
  {/if}
</div>

<!-- [/DEF:Sidebar:Component] -->
