"use client"

import * as React from "react"
import { Combobox as ComboboxPrimitive } from "@base-ui/react/combobox"
import { ChevronDownIcon, CheckIcon } from "lucide-react"

import { cn } from "@/lib/utils"

export interface ComboboxOption<Value> {
  value: Value
  label: string
}

interface ComboboxProps<Value> {
  items: ComboboxOption<Value>[]
  value: Value | null
  onValueChange: (value: Value | null) => void
  placeholder?: string
  emptyText?: string
  disabled?: boolean
  className?: string
  "aria-invalid"?: boolean
}

/** Searchable dropdown for long option lists (items, vendors, …) — a `Select` swap-in
 * built on Base UI's Combobox, styled to match `select.tsx`'s trigger/popup/item look. */
export function Combobox<Value>({
  items,
  value,
  onValueChange,
  placeholder = "Search…",
  emptyText = "No results found.",
  disabled,
  className,
  ...rest
}: ComboboxProps<Value>) {
  const itemToStringLabel = React.useCallback(
    (v: Value) => items.find((i) => i.value === v)?.label ?? "",
    [items]
  )

  return (
    <ComboboxPrimitive.Root<Value>
      items={items}
      value={value}
      onValueChange={(v) => onValueChange(v ?? null)}
      itemToStringLabel={itemToStringLabel}
      disabled={disabled}
    >
      <ComboboxPrimitive.InputGroup
        data-slot="combobox-input-group"
        className={cn(
          "flex h-9 w-full items-center gap-1.5 rounded-lg border border-input bg-transparent pr-2 pl-2.5 text-sm transition-colors focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 has-disabled:cursor-not-allowed has-disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:bg-input/30",
          className
        )}
        {...rest}
      >
        <ComboboxPrimitive.Input
          placeholder={placeholder}
          disabled={disabled}
          className="h-full w-full min-w-0 bg-transparent text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed"
        />
        <ComboboxPrimitive.Icon
          render={<ChevronDownIcon className="pointer-events-none size-4 shrink-0 text-muted-foreground" />}
        />
      </ComboboxPrimitive.InputGroup>
      <ComboboxPrimitive.Portal>
        <ComboboxPrimitive.Positioner side="bottom" sideOffset={4} className="isolate z-50">
          <ComboboxPrimitive.Popup
            data-slot="combobox-content"
            className="max-h-(--available-height) w-(--anchor-width) min-w-48 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95"
          >
            <ComboboxPrimitive.Empty className="px-2.5 py-6 text-center text-sm text-muted-foreground">
              {emptyText}
            </ComboboxPrimitive.Empty>
            <ComboboxPrimitive.List>
              {(item: ComboboxOption<Value>) => (
                <ComboboxPrimitive.Item
                  key={String(item.value)}
                  value={item.value}
                  className="relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1.5 pr-8 pl-2.5 text-sm outline-hidden select-none data-highlighted:bg-violet-100 data-highlighted:text-violet-900 dark:data-highlighted:bg-violet-500/25 dark:data-highlighted:text-violet-200"
                >
                  {item.label}
                  <ComboboxPrimitive.ItemIndicator className="pointer-events-none absolute right-2 flex size-4 items-center justify-center">
                    <CheckIcon className="size-4 text-violet-600 dark:text-violet-300" />
                  </ComboboxPrimitive.ItemIndicator>
                </ComboboxPrimitive.Item>
              )}
            </ComboboxPrimitive.List>
          </ComboboxPrimitive.Popup>
        </ComboboxPrimitive.Positioner>
      </ComboboxPrimitive.Portal>
    </ComboboxPrimitive.Root>
  )
}
