<script setup lang="ts">
import type { HTMLAttributes } from "vue";
import { cn } from "@/lib/utils";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
} from "../sheet";
import { useSidebar } from "./utils";
import { SIDEBAR_WIDTH_MOBILE } from "./utils";

defineOptions({ inheritAttrs: false });

const props = withDefaults(
  defineProps<{
    side?: "left" | "right";
    variant?: "sidebar" | "floating" | "inset";
    collapsible?: "offcanvas" | "icon" | "none";
    class?: HTMLAttributes["class"];
  }>(),
  {
    side: "left",
    variant: "sidebar",
    collapsible: "offcanvas",
  },
);

const { state, isMobile, openMobile, setOpenMobile } = useSidebar();
</script>

<template>
  <!-- Non-collapsible sidebar -->
  <div
    v-if="collapsible === 'none'"
    data-slot="sidebar"
    :class="
      cn(
        'bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col',
        props.class,
      )
    "
    v-bind="$attrs"
  >
    <slot />
  </div>

  <!-- Mobile sidebar — Sheet drawer -->
  <Sheet
    v-else-if="isMobile"
    :open="openMobile"
    v-bind="$attrs"
    @update:open="setOpenMobile"
  >
    <SheetContent
      data-sidebar="sidebar"
      data-slot="sidebar"
      data-mobile="true"
      :side="side"
      class="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
      :style="{ '--sidebar-width': SIDEBAR_WIDTH_MOBILE }"
    >
      <SheetHeader class="sr-only">
        <SheetTitle>Sidebar</SheetTitle>
        <SheetDescription>Displays the mobile sidebar.</SheetDescription>
      </SheetHeader>
      <div class="flex h-full w-full flex-col">
        <slot />
      </div>
    </SheetContent>
  </Sheet>

  <!-- Collapsible sidebar (desktop) -->
  <div
    v-else
    class="group peer text-sidebar-foreground hidden md:block"
    data-slot="sidebar"
    :data-state="state"
    :data-collapsible="state === 'collapsed' ? collapsible : ''"
    :data-variant="variant"
    :data-side="side"
  >
    <!-- Gap div — in-flow placeholder that collapses with the sidebar -->
    <div
      :class="
        cn(
          'relative bg-transparent transition-[width] duration-200 ease-linear',
          state === 'collapsed' && collapsible === 'offcanvas'
            ? 'w-0'
            : state === 'collapsed' && collapsible === 'icon'
              ? variant === 'floating' || variant === 'inset'
                ? 'w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]'
                : 'w-(--sidebar-width-icon)'
              : 'w-(--sidebar-width)',
          side === 'right' ? 'rotate-180' : '',
        )
      "
    />
    <!-- Fixed sidebar panel -->
    <div
      :class="
        cn(
          'fixed inset-y-0 z-10 hidden h-svh transition-[left,right,width] duration-200 ease-linear md:flex',
          state === 'collapsed' && collapsible === 'icon'
            ? variant === 'floating' || variant === 'inset'
              ? 'p-2 w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
              : 'w-(--sidebar-width-icon)'
            : 'w-(--sidebar-width)',
          side === 'left'
            ? state === 'collapsed' && collapsible === 'offcanvas'
              ? 'left-[calc(var(--sidebar-width)*-1)]'
              : 'left-0'
            : state === 'collapsed' && collapsible === 'offcanvas'
              ? 'right-[calc(var(--sidebar-width)*-1)]'
              : 'right-0',
          variant !== 'floating' && variant !== 'inset' && side === 'left'
            ? 'border-r'
            : '',
          variant !== 'floating' && variant !== 'inset' && side === 'right'
            ? 'border-l'
            : '',
          props.class,
        )
      "
      v-bind="$attrs"
    >
      <div
        data-sidebar="sidebar"
        class="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
      >
        <slot />
      </div>
    </div>
  </div>
</template>
