"use client"

import * as React from "react"
import { ChevronLeft, ChevronRight } from "lucide-react"
import { DayPicker, getDefaultClassNames } from "react-day-picker"

import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

export type CalendarProps = React.ComponentProps<typeof DayPicker> & {
  buttonVariant?: "ghost" | "outline"
}

function Calendar({
  className,
  classNames,
  showOutsideDays = true,
  captionLayout = "label",
  buttonVariant = "ghost",
  ...props
}: CalendarProps) {
  const defaultClassNames = getDefaultClassNames()

  return (
    <DayPicker
      showOutsideDays={showOutsideDays}
      className={cn(
        "bg-background group/calendar p-3 [--cell-size:2rem]",
        className
      )}
      captionLayout={captionLayout}
      classNames={{
        root: cn("w-fit", defaultClassNames.root),
        months: cn(
          "relative flex flex-col gap-4 md:flex-row",
          defaultClassNames.months
        ),
        month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
        month_caption: cn(
          "flex h-[--cell-size] w-full items-center justify-center px-[--cell-size] text-sm font-medium",
          defaultClassNames.month_caption
        ),
        dropdowns: cn(
          "flex items-center gap-1",
          defaultClassNames.dropdowns
        ),
        dropdown: cn(
          "flex h-[--cell-size] items-center justify-center rounded-md border border-input bg-background px-3 text-sm font-medium ring-offset-background hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
          defaultClassNames.dropdown
        ),
        dropdown_icon: cn("ml-2 h-4 w-4", defaultClassNames.dropdown_icon),
        weekdays: cn(
          "mt-2 flex w-full flex-row",
          defaultClassNames.weekdays
        ),
        weekday: cn(
          "flex h-[--cell-size] w-[--cell-size] items-center justify-center text-xs font-normal text-muted-foreground",
          defaultClassNames.weekday
        ),
        week: cn("mt-0.5 flex w-full flex-row", defaultClassNames.week),
        day: cn(
          "flex h-[--cell-size] w-[--cell-size] items-center justify-center rounded-md p-0 text-sm",
          defaultClassNames.day
        ),
        day_button: cn(
          buttonVariants({ variant: buttonVariant }),
          "h-[--cell-size] w-[--cell-size] select-none p-0 font-normal hover:bg-accent hover:text-accent-foreground focus-visible:z-10 aria-selected:opacity-100",
          defaultClassNames.day_button
        ),
        range_start: cn("day-range-start", defaultClassNames.range_start),
        range_end: cn("day-range-end", defaultClassNames.range_end),
        selected: cn(
          "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
          defaultClassNames.selected
        ),
        today: cn(
          "bg-accent text-accent-foreground",
          defaultClassNames.today
        ),
        outside: cn(
          "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground",
          defaultClassNames.outside
        ),
        disabled: cn(
          "text-muted-foreground opacity-50",
          defaultClassNames.disabled
        ),
        range_middle: cn(
          "aria-selected:bg-accent aria-selected:text-accent-foreground",
          defaultClassNames.range_middle
        ),
        hidden: cn("invisible", defaultClassNames.hidden),
        ...classNames,
      }}
      components={{
        Chevron: ({ orientation }) => {
          const Icon = orientation === "left" ? ChevronLeft : ChevronRight
          return <Icon className="h-4 w-4" />
        },
        Dropdown: (props) => {
          const { value, onChange, options } = props
          const selected = options?.find((option) => option.value === value)
          const handleChange = (newValue: string) => {
            const changeEvent = {
              target: { value: newValue },
            } as React.ChangeEvent<HTMLSelectElement>
            onChange?.(changeEvent)
          }

          return (
            <Select value={value?.toString()} onValueChange={handleChange}>
              <SelectTrigger className="h-7 w-fit gap-1 border-none px-2 py-1 font-medium shadow-none hover:bg-accent focus:ring-0">
                <SelectValue>{selected?.label}</SelectValue>
              </SelectTrigger>
              <SelectContent position="popper" className="min-w-[var(--radix-popper-anchor-width)]">
                {options?.map((option) => (
                  <SelectItem
                    key={option.value}
                    value={option.value?.toString() ?? ""}
                    disabled={option.disabled}
                  >
                    {option.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          )
        },
      }}
      {...props}
    />
  )
}

Calendar.displayName = "Calendar"

export { Calendar }
