<template>
  <!-- Mobile Toggle Button when menu is closed: shows a hamburger button at top-left -->
  <button
    v-if="!mobileOpen"
    @click="toggleMobile"
    :class="[theme.hamburgerButtonBg, 'sm:hidden fixed top-4 left-4 z-40 p-2 rounded focus:outline-none']">
    <!-- Hamburger Icon -->
    <span class="block w-6 h-0.5 bg-current mb-1"></span>
    <span class="block w-6 h-0.5 bg-current mb-1"></span>
    <span class="block w-6 h-0.5 bg-current"></span>
  </button>

  <!-- Sidebar container -->
  <!-- In mobile view, the sidebar overlays content; in desktop (sm and up), it's static -->
  <nav :class="sidebarClasses">
    <!-- Desktop Header: Branding (optional) and Minimize Toggle -->
    <div class="hidden sm:flex justify-between items-center p-2">
      <!-- Optional Branding Slot: only shown when sidebar is expanded -->
      <div v-if="!minimized && $slots.brand" class="flex-shrink-0">
        <!-- Wrap branding in a container that controls size -->
        <div class="w-32 h-10 overflow-hidden">
          <slot name="brand"></slot>
        </div>
      </div>
      <!-- Minimize Toggle Button -->
      <button
        @click="toggleMinimized"
        :class="[theme.toggleButtonBg, 'p-2 rounded hover:opacity-80 focus:outline-none']">
        <!-- Toggle icon: changes based on minimized state -->
        <svg v-if="minimized" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6"
             fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                d="M15 19l-7-7 7-7" />
        </svg>
        <svg v-else xmlns="http://www.w3.org/2000/svg" class="h-6 w-6"
             fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                d="M9 5l7 7-7 7" />
        </svg>
      </button>
    </div>

    <!-- Mobile Close Button (X icon) displayed when menu is open -->
    <button
      v-if="mobileOpen"
      @click="toggleMobile"
      :class="[theme.toggleButtonBg, 'sm:hidden absolute top-4 right-4 z-50 p-2 rounded focus:outline-none']">
      <!-- X Icon -->
      <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none"
           viewBox="0 0 24 24" stroke="currentColor">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
              d="M6 18L18 6M6 6l12 12" />
      </svg>
    </button>

    <!-- Navigation Links -->
    <ul>
      <li v-for="(link, i) in links" :key="i" class="my-1">
        <RouterLink
          :to="link.route || '#'"
          class="flex items-center p-2 transition-colors"
          :class="[isActive(link) ? theme.sidebarActive : theme.sidebarHover, theme.sidebarLink]">
          <span class="flex-shrink-0" :class="minimized ? 'mx-auto' : 'mr-3'">
            <!-- Render icon provided in the link -->
            <component :is="link.icon" class="w-6 h-6" />
          </span>
          <span v-if="!minimized" class="flex-1">
            {{ link.title }}
          </span>
        </RouterLink>

        <!-- Sub-links; visible only when the sidebar is not minimized -->
        <ul v-if="link.subLinks && link.subLinks.length" v-show="!minimized" class="ml-8">
          <li v-for="(sub, j) in link.subLinks" :key="j" class="my-1">
            <RouterLink
              :to="sub.route || '#'"
              class="flex items-center p-2 transition-colors"
              :class="[isActive(sub) ? theme.sidebarActive : theme.sidebarHover, theme.sidebarLink]">
              <span v-if="sub.icon" class="flex-shrink-0 mr-3">
                <component :is="sub.icon" class="w-5 h-5" />
              </span>
              <span>{{ sub.title }}</span>
            </RouterLink>
          </li>
        </ul>
      </li>
    </ul>
  </nav>
</template>

<script lang="ts" setup>
import { ref, computed } from 'vue';
import { RouterLink, useRoute } from 'vue-router';

// Define the interface for navigation links.
export interface NavLink {
  title: string;
  icon?: any; // Vue component, SVG, or any renderable element.
  route?: string;
  subLinks?: Omit<NavLink, 'subLinks'>[];
}

// Define the interface for theming the component.
export interface Theme {
  // Sidebar container background and text colors.
  sidebarBg?: string;        // e.g. "bg-gray-800"
  sidebarText?: string;      // e.g. "text-white"
  // Classes for links (default state)
  sidebarLink?: string;      // e.g. "rounded"
  // Classes on hover state
  sidebarHover?: string;     // e.g. "hover:bg-gray-700"
  // Classes for the active link
  sidebarActive?: string;    // e.g. "bg-gray-900"
  // Toggle button (used for mobile hamburger & desktop minimize toggle)
  toggleButtonBg?: string;   // e.g. "bg-gray-700"
  hamburgerButtonBg?: string;
}

// Accept props: links are required; theme is optional.
const props = defineProps<{
  links: NavLink[];
  theme?: Partial<Theme>;
}>();

// Provide default theme values.
const defaultTheme: Theme = {
  sidebarBg: "bg-gray-800",
  sidebarText: "text-white",
  sidebarLink: "",
  sidebarHover: "hover:bg-gray-700",
  sidebarActive: "bg-gray-900",
  toggleButtonBg: "bg-gray-700",
  hamburgerButtonBg: "bg-white"
};

// Merge provided theme with defaults.
const theme = {
  ...defaultTheme,
  ...props.theme
};

// Get current route to highlight active links.
const route = useRoute();

// Local state: mobile sidebar open/closed and desktop minimized state.
const mobileOpen = ref(false);
const minimized = ref(false);

// Toggle mobile sidebar visibility.
const toggleMobile = () => {
  mobileOpen.value = !mobileOpen.value;
};

// Toggle desktop minimized state.
const toggleMinimized = () => {
  minimized.value = !minimized.value;
};

// Check if a given link (or any of its sub-links) is active based on the current route.
const isActive = (link: NavLink) => {
  if (link.route && route.path === link.route) return true;
  if (link.subLinks) {
    return link.subLinks.some(sub => sub.route === route.path);
  }
  return false;
};

// Compute sidebar classes with a 200ms transition for both mobile sliding and desktop width changes.
const sidebarClasses = computed(() => {
  let classes = `${theme.sidebarBg} ${theme.sidebarText} transition-all duration-200 overflow-y-auto shadow-lg z-30`;
  // On mobile: fixed positioning to overlay content.
  classes += " fixed sm:static top-0 h-screen";
  // Mobile: animate slide in/out.
  classes += mobileOpen.value ? " transform translate-x-0" : " transform -translate-x-full";
  // On desktop, ensure sidebar is visible.
  classes += " sm:translate-x-0";
  // Animate width change on desktop for minimized/expanded states.
  classes += minimized.value ? " w-20" : " w-64";
  return classes;
});
</script>

<style scoped>
/* Styling for internal scrolling within the sidebar */
nav::-webkit-scrollbar {
  width: 6px;
}

nav::-webkit-scrollbar-thumb {
  background-color: rgba(255, 255, 255, 0.3);
  border-radius: 3px;
}
</style>
