
"use client"

import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"
import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from "@/components/ui/tooltip"

import { SidebarContext, useSidebar } from "./sidebar-context"

const Sidebar = React.forwardRef<
  HTMLElement,
  React.HTMLAttributes<HTMLElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="root"
    className={cn(
      "group relative grid h-full w-full shrink-0 overflow-hidden border-r border-sidebar-border data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left",
      className
    )}
    {...props}
  />
))
Sidebar.displayName = "Sidebar"

const SidebarRail = React.forwardRef<
  HTMLElement,
  React.HTMLAttributes<HTMLElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="rail"
    className={cn(
      "flex flex-col gap-2 px-2 py-2",
      className
    )}
    {...props}
  />
))
SidebarRail.displayName = "SidebarRail"

const SidebarContent = React.forwardRef<
  HTMLElement,
  React.HTMLAttributes<HTMLElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="content"
    className={cn(
      "flex flex-col gap-2 px-2 py-2",
      className
    )}
    {...props}
  />
))
SidebarContent.displayName = "SidebarContent"

const SidebarFooter = React.forwardRef<
  HTMLElement,
  React.HTMLAttributes<HTMLElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="footer"
    className={cn(
      "mt-auto border-t border-sidebar-border",
      className
    )}
    {...props}
  />
))
SidebarFooter.displayName = "SidebarFooter"

const SidebarHeader = React.forwardRef<
  HTMLElement,
  React.HTMLAttributes<HTMLElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="header"
    className={cn(
      "pb-2",
      className
    )}
    {...props}
  />
))
SidebarHeader.displayName = "SidebarHeader"

const SidebarInset = React.forwardRef<
  HTMLElement,
  React.HTMLAttributes<HTMLElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="inset"
    className={cn(
      "absolute inset-0 bg-sidebar",
      className
    )}
    {...props}
  />
))
SidebarInset.displayName = "SidebarInset"

const SidebarInput = React.forwardRef<
  HTMLInputElement,
  React.ComponentProps<"input">
>(({ className, ...props }, ref) => (
  <input
    ref={ref}
    data-sidebar="input"
    className={cn(
      "flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
      className
    )}
    {...props}
  />
))
SidebarInput.displayName = "SidebarInput"

const SidebarSeparator = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div">
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="separator"
    className={cn(
      "h-px w-full bg-border",
      className
    )}
    {...props}
  />
))
SidebarSeparator.displayName = "SidebarSeparator"

const SidebarTrigger = React.forwardRef<
  HTMLButtonElement,
  React.ComponentProps<"button">
>(({ className, ...props }, ref) => {
  return (
    <button
      ref={ref}
      data-sidebar="trigger"
      className={cn(
        "peer group/sheet absolute left-0 top-0 flex h-12 w-12 items-center justify-center rounded-md outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-5 [&>svg]:transition-transform data-[state=open]:rotate-180 md:hidden",
        className
      )}
      aria-label="Toggle Sidebar"
      {...props}
    />
  )
})
SidebarTrigger.displayName = "SidebarTrigger"

const SidebarProvider = SidebarContext.Provider

const SidebarGroup = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div"> & {
    collapsible?: "icon" | "always"
    defaultCollapsed?: boolean
  }
>(({ className, collapsible = "always", defaultCollapsed = false, ...props }, ref) => {
  const [collapsed, setCollapsed] = React.useState(defaultCollapsed)

  const value = React.useMemo(
    () => ({
      collapsed,
      setCollapsed,
    }),
    [collapsed]
  )

  return (
    <SidebarContext.Group.Provider value={value}>
      <div
        ref={ref}
        data-sidebar="group"
        data-collapsible={collapsible}
        data-state={collapsed ? "collapsed" : "open"}
        className={cn(
          "group/menu relative flex flex-col gap-1 [&:not(:first-child)]:mt-2",
          className
        )}
        {...props}
      />
    </SidebarContext.Group.Provider>
  )
})
SidebarGroup.displayName = "SidebarGroup"

const SidebarGroupLabel = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div">
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="group-label"
    className={cn(
      "flex items-center justify-between px-2 text-sm font-medium text-sidebar-foreground",
      className
    )}
    {...props}
  />
))
SidebarGroupLabel.displayName = "SidebarGroupLabel"

const SidebarGroupContent = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div">
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    data-sidebar="group-content"
    className={cn(
      "animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
      className
    )}
    {...props}
  />
))
SidebarGroupContent.displayName = "SidebarGroupContent"

const SidebarGroupAction = React.forwardRef<
  HTMLButtonElement,
  React.ComponentProps<"button">
>(({ className, ...props }, ref) => {
  const { collapsed, setCollapsed } = SidebarContext.Group.useContext()

  return (
    <button
      ref={ref}
      data-sidebar="group-action"
      aria-label={collapsed ? "Expand Group" : "Collapse Group"}
      className={cn(
        "group/action flex h-9 w-9 items-center justify-center rounded-md text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:transition-transform data-[state=open]:rotate-180",
        className
      )}
      data-state={collapsed ? "collapsed" : "open"}
      onClick={() => setCollapsed(!collapsed)}
      {...props}
    />
  )
})
SidebarGroupAction.displayName = "SidebarGroupAction"

const SidebarMenu = React.forwardRef<
  HTMLUListElement,
  React.ComponentProps<"ul">
>(({ className, ...props }, ref) => (
  <ul
    ref={ref}
    data-sidebar="menu"
    className={cn(
      "group/menu flex flex-col gap-1",
      className
    )}
    {...props}
  />
))
SidebarMenu.displayName = "SidebarMenu"

const SidebarMenuItem = React.forwardRef<
  HTMLLIElement,
  React.ComponentProps<"li">
>(({ className, ...props }, ref) => (
  <li
    ref={ref}
    data-sidebar="menu-item"
    className={cn(
      "group/menu-item relative flex items-center",
      className
    )}
    {...props}
  />
))
SidebarMenuItem.displayName = "SidebarMenuItem"

const sidebarMenuButtonVariants = cva(
  "group/menu-button relative flex h-9 min-w-0 items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
  {
    variants: {
      variant: {
        default: "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
      },
      size: {
        sm: "text-xs",
        default: "text-sm",
        lg: "text-base",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
)

interface SidebarMenuButtonProps
  extends React.HTMLAttributes<HTMLElement>,
    VariantProps<typeof sidebarMenuButtonVariants> {
  asChild?: boolean; // Prop for SidebarMenuButton to behave as a Slot
  tooltip?: string | Omit<React.ComponentProps<typeof TooltipContent>, "children"> & { children?: React.ReactNode };
  href?: string; // Will be passed by <Link asChild>
  isActive?: boolean;
}

const SidebarMenuButton = React.forwardRef<
  HTMLElement, 
  SidebarMenuButtonProps
>(
  (
    {
      className,
      variant,
      size,
      tooltip,
      children,
      href, 
      isActive,
      asChild: isSlotProp, // This is SidebarMenuButton's own instruction to be a Slot
      ...restProps // Contains all other props, including 'asChild' from a parent <Link asChild>
    },
    ref
  ) => {
    const { collapsed } = useSidebar();
    
    // Determine the component to render.
    // If SidebarMenuButton itself is meant to be a Slot, use Slot.
    // Else if an href is present (passed by Link), render as 'a'.
    // Otherwise, render as 'button'.
    const ComponentToRender: React.ElementType = isSlotProp ? Slot : href ? "a" : "button";

    // Make a mutable copy of restProps to potentially remove parent's asChild
    const elementProps = { ...restProps } as any;

    // If we are rendering a DOM element (not Slot), and 'asChild' came from a parent (like Link),
    // we must remove it so it's not passed to the DOM element.
    if (ComponentToRender !== Slot && typeof elementProps.asChild === 'boolean') {
      delete elementProps.asChild;
    }

    // Add standard attributes
    elementProps.ref = ref;
    elementProps["data-sidebar"] = "menu-button";
    elementProps["data-active"] = isActive;
    elementProps.className = cn(sidebarMenuButtonVariants({ variant, size, className }));
    
    if (ComponentToRender === "a" && href) {
      elementProps.href = href;
    }
    
    const buttonContent = (
      <>
        {children}
        {collapsed && tooltip && (
          <span className="sr-only">{typeof tooltip === "string" ? tooltip : "Menu item"}</span>
        )}
      </>
    );

    const element = React.createElement(
      ComponentToRender,
      elementProps,
      buttonContent
    );

    if (collapsed && tooltip) {
      return (
        <TooltipProvider delayDuration={0}>
          <Tooltip>
            <TooltipTrigger asChild>
              {element}
            </TooltipTrigger>
            <TooltipContent
              side="right"
              sideOffset={6}
              align="center"
              {...(typeof tooltip === "object" ? tooltip : {})}
            >
              {typeof tooltip === "string" ? tooltip : (tooltip as any)?.children}
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>
      );
    }
    return element;
  }
);
SidebarMenuButton.displayName = "SidebarMenuButton"

export {
  Sidebar,
  SidebarProvider,
  SidebarHeader,
  SidebarContent,
  SidebarFooter,
  SidebarTrigger,
  SidebarRail,
  SidebarInput,
  SidebarSeparator,
  SidebarGroup,
  SidebarGroupLabel,
  SidebarGroupContent,
  SidebarGroupAction,
  SidebarMenu,
  SidebarMenuItem,
  SidebarMenuButton,
  SidebarInset,
}

export { useSidebar, type SidebarMenuButtonProps }
