"use client"
import React, { ComponentPropsWithoutRef, forwardRef, useState } from "react"
import { tv, type VariantProps } from "tailwind-variants"
import { overlayVariants } from "../../styles/utils/overlay"
import { classNames } from "../../utils"
import { SidebarContext } from "./SidebarContext"
import { SidebarCollapsibleItem, SidebarItem } from "./SidebarItem"
import { SidebarOpen } from "./SidebarOpen"

export type SidebarProps = {
  containerClassName?: string
  className?: string
  children?: React.ReactNode
  /**
   * If true, then when the sidebar expands, it will fill up the space it expands into.
   * This means that content on either side will be pushed to accomodate it.
   */
  fillExpandedSpace?: boolean
} & VariantProps<typeof sidebarVariants> &
  Pick<ComponentPropsWithoutRef<"nav">, "aria-label">

const sidebarVariants = tv({
  variants: {
    side: {
      left: "left-0",
      right: "right-0",
    },
  },
})

const hoverWidthClassName = classNames("hover:w-[225px]")

const SidebarBase = forwardRef<HTMLDivElement, SidebarProps>(function Sidebar(
  {
    className,
    containerClassName,
    children,
    side = "left",
    fillExpandedSpace = false,
    ...rest
  },
  ref,
) {
  const [disableExpand, setDisableExpand] = useState(false)

  return (
    <SidebarContext.Provider value={{ disableExpand, setDisableExpand }}>
      <div
        className={classNames(
          "min-w-[52px] transition-width",
          fillExpandedSpace && !disableExpand && hoverWidthClassName,
          containerClassName,
        )}
      >
        <aside
          className={classNames(
            "group fixed inset-y-0 z-sidebar h-full",
            side === "right" && "right-0",
            sidebarVariants({ side }),
          )}
          ref={ref}
          onPointerLeave={() => {
            setDisableExpand(false)
          }}
        >
          <nav
            className={classNames(
              "flex h-full w-[52px] flex-col gap-2 px-2 py-4 transition-width duration-300 ease-out-quint",
              "bg-bg-primary border-r border-border-1",
              !disableExpand && hoverWidthClassName,
              className,
            )}
            {...rest}
          >
            {children}
          </nav>

          {/* Overlay */}
          <div
            className={classNames(
              overlayVariants(),
              "pointer-events-none z-[-1] bg-transparent transition-colors duration-300 ease-out-quint",
              !disableExpand && "group-hover:bg-overlay",
            )}
          />
        </aside>
      </div>
    </SidebarContext.Provider>
  )
})

/**
 * A sidebar is a vertical navigation component that is used to display a list of links and actions.
 */
export const Sidebar = Object.assign(SidebarBase, {
  Item: SidebarItem,
  Open: SidebarOpen,
  CollapsibleItem: SidebarCollapsibleItem,
})
