"use client"

import { useEffect, useMemo, useRef, useState } from "react"
import { createPortal } from "react-dom"
import { Check, ChevronDown, X } from "lucide-react"

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

export type SearchableSelectOption = {
  value: string
  label: string
  description?: string
}

type Props = {
  id: string
  label: string
  value: string
  options: SearchableSelectOption[]
  onChange: (value: string) => void
  placeholder?: string
  required?: boolean
  disabled?: boolean
}

export function SearchableSelectField({
  id,
  label,
  value,
  options,
  onChange,
  placeholder = "Search...",
  required,
  disabled,
}: Props) {
  const [open, setOpen] = useState(false)
  const [query, setQuery] = useState("")
  const [menuRect, setMenuRect] = useState<{ top: number; left: number; width: number } | null>(null)
  const inputWrapRef = useRef<HTMLDivElement | null>(null)

  const selected = options.find((option) => option.value === value)
  const displayValue = open ? query : selected?.label || ""

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase()
    if (!q) return options.slice(0, 20)
    return options
      .filter((option) => `${option.label} ${option.description || ""}`.toLowerCase().includes(q))
      .slice(0, 20)
  }, [options, query])

  useEffect(() => {
    if (!open) return

    const updateMenuRect = () => {
      const rect = inputWrapRef.current?.getBoundingClientRect()
      if (!rect) return
      setMenuRect({
        top: rect.bottom + 4,
        left: rect.left,
        width: rect.width,
      })
    }

    updateMenuRect()
    window.addEventListener("resize", updateMenuRect)
    window.addEventListener("scroll", updateMenuRect, true)
    return () => {
      window.removeEventListener("resize", updateMenuRect)
      window.removeEventListener("scroll", updateMenuRect, true)
    }
  }, [open])

  const menu = open && !disabled && menuRect && typeof document !== "undefined" ? createPortal(
    <div
      className="fixed z-[1000] max-h-64 overflow-y-auto rounded-lg border border-border bg-card py-1 shadow-lg"
      style={{ top: menuRect.top, left: menuRect.left, width: menuRect.width }}
    >
      {filtered.length === 0 ? (
        <div className="px-3 py-2 text-sm text-muted-foreground">No matches</div>
      ) : (
        filtered.map((option) => (
          <button
            key={option.value}
            type="button"
            onMouseDown={(event) => event.preventDefault()}
            onClick={() => {
              onChange(option.value)
              setQuery("")
              setOpen(false)
            }}
            className={cn(
              "flex w-full items-start gap-2 px-3 py-2 text-right text-sm hover:bg-muted",
              option.value === value && "bg-gold-50 text-gold-800",
            )}
          >
            <Check className={cn("mt-0.5 h-4 w-4 shrink-0", option.value === value ? "opacity-100" : "opacity-0")} />
            <span className="min-w-0 flex-1">
              <span className="block truncate font-medium">{option.label}</span>
              {option.description && <span className="block truncate text-xs text-muted-foreground">{option.description}</span>}
            </span>
          </button>
        ))
      )}
    </div>,
    document.body,
  ) : null

  return (
    <div className="relative space-y-1">
      <label htmlFor={id} className="block text-sm font-medium text-foreground">
        {label}
        {required && <span className="text-destructive mr-1">*</span>}
      </label>
      <div className="relative" ref={inputWrapRef}>
        <input
          id={id}
          value={displayValue}
          onChange={(event) => {
            setQuery(event.target.value)
            setOpen(true)
          }}
          onFocus={() => {
            setQuery("")
            setOpen(true)
          }}
          onBlur={() => window.setTimeout(() => setOpen(false), 120)}
          placeholder={placeholder}
          disabled={disabled}
          className="w-full rounded-lg border border-border bg-background px-3 py-2.5 pl-16 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary disabled:cursor-not-allowed disabled:opacity-50"
          autoComplete="off"
        />
        <div className="absolute inset-y-0 left-2 flex items-center gap-1">
          {value && (
            <button
              type="button"
              onMouseDown={(event) => event.preventDefault()}
              onClick={() => {
                onChange("")
                setQuery("")
              }}
              className="rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
              aria-label="Clear"
            >
              <X className="h-3.5 w-3.5" />
            </button>
          )}
          <ChevronDown className="h-4 w-4 text-muted-foreground" />
        </div>
      </div>
      {menu}
    </div>
  )
}
