"use client"

import * as React from "react"
import { useEffect, useRef, useState } from "react"
import { cn } from "@/lib/utils"

// ─── Types ────────────────────────────────────────────────────────────────────

export type DropdownOption = {
  value: string
  label: string
  description?: string  // optional sub-label
  icon?: React.ReactNode // optional leading icon/avatar
}

type DropdownProps = {
  options: DropdownOption[]
  value?: string
  onChange?: (value: string) => void
  placeholder?: string
  searchPlaceholder?: string
  disabled?: boolean
  className?: string
  /** Label shown above the trigger */
  label?: string
  /** Show a clear button when a value is selected */
  clearable?: boolean
  /** Empty state message */
  emptyMessage?: string
}

// ─── Component ───────────────────────────────────────────────────────────────

export function Dropdown({
  options,
  value,
  onChange,
  placeholder = "Select an option…",
  searchPlaceholder = "Search…",
  disabled = false,
  className,
  label,
  clearable = false,
  emptyMessage = "No results found.",
}: DropdownProps) {
  const [open, setOpen]       = useState(false)
  const [query, setQuery]     = useState("")
  const containerRef          = useRef<HTMLDivElement>(null)
  const inputRef              = useRef<HTMLInputElement>(null)
  const listRef               = useRef<HTMLUListElement>(null)
  const [highlighted, setHighlighted] = useState<number>(-1)

  const selected = options.find((o) => o.value === value)

  // Filter
  const filtered = query.trim()
    ? options.filter(
        (o) =>
          o.label.toLowerCase().includes(query.toLowerCase()) ||
          o.description?.toLowerCase().includes(query.toLowerCase())
      )
    : options

  // Open → focus input
  useEffect(() => {
    if (open) {
      setTimeout(() => inputRef.current?.focus(), 10)
      setHighlighted(-1)
    } else {
      setQuery("")
    }
  }, [open])

  // Click outside → close
  useEffect(() => {
    function onDown(e: MouseEvent) {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setOpen(false)
      }
    }
    document.addEventListener("mousedown", onDown)
    return () => document.removeEventListener("mousedown", onDown)
  }, [])

  // Keyboard nav
  function onKeyDown(e: React.KeyboardEvent) {
    if (!open) {
      if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
        e.preventDefault()
        setOpen(true)
      }
      return
    }
    if (e.key === "ArrowDown") {
      e.preventDefault()
      setHighlighted((h) => Math.min(h + 1, filtered.length - 1))
    } else if (e.key === "ArrowUp") {
      e.preventDefault()
      setHighlighted((h) => Math.max(h - 1, 0))
    } else if (e.key === "Enter") {
      e.preventDefault()
      if (highlighted >= 0 && filtered[highlighted]) {
        select(filtered[highlighted].value)
      }
    } else if (e.key === "Escape") {
      setOpen(false)
    }
  }

  // Scroll highlighted item into view
  useEffect(() => {
    if (highlighted >= 0 && listRef.current) {
      const item = listRef.current.children[highlighted] as HTMLElement
      item?.scrollIntoView({ block: "nearest" })
    }
  }, [highlighted])

  function select(val: string) {
    onChange?.(val)
    setOpen(false)
  }

  function clear(e: React.MouseEvent) {
    e.stopPropagation()
    onChange?.("")
  }

  // Highlight matched characters in label
  function highlight(text: string, q: string) {
    if (!q.trim()) return <>{text}</>
    const idx = text.toLowerCase().indexOf(q.toLowerCase())
    if (idx === -1) return <>{text}</>
    return (
      <>
        {text.slice(0, idx)}
        <mark className="bg-primary/15 text-primary rounded-[2px] font-semibold not-italic">
          {text.slice(idx, idx + q.length)}
        </mark>
        {text.slice(idx + q.length)}
      </>
    )
  }

  return (
    <div ref={containerRef} className={cn("relative w-full", className)}>
      {/* Label */}
      {label && (
        <label className="mb-1.5 block text-xs font-medium text-muted-foreground">
          {label}
        </label>
      )}

      {/* Trigger */}
      <button
        type="button"
        disabled={disabled}
        aria-haspopup="listbox"
        aria-expanded={open}
        onClick={() => !disabled && setOpen((o) => !o)}
        onKeyDown={onKeyDown}
        className={cn(
          "flex h-9 w-full items-center justify-between gap-2 rounded-lg border border-border/60 bg-background px-3 text-sm",
          "shadow-[0_1px_2px_0_rgb(0,0,0,0.04)]",
          "transition-all duration-150",
          "hover:border-border hover:shadow-[0_1px_4px_0_rgb(0,0,0,0.07)]",
          "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/25 focus-visible:border-primary/50",
          open && "border-primary/50 ring-2 ring-primary/20 shadow-[0_1px_4px_0_rgb(0,0,0,0.07)]",
          disabled && "cursor-not-allowed opacity-50",
        )}
      >
        {/* Left side */}
        <span className="flex min-w-0 flex-1 items-center gap-2">
          {selected?.icon && (
            <span className="shrink-0 text-muted-foreground">{selected.icon}</span>
          )}
          {selected ? (
            <span className="truncate text-foreground">{selected.label}</span>
          ) : (
            <span className="truncate text-muted-foreground/60">{placeholder}</span>
          )}
        </span>

        {/* Right side */}
        <span className="flex shrink-0 items-center gap-1">
          {clearable && selected && (
            <span
              role="button"
              tabIndex={0}
              onClick={clear}
              onKeyDown={(e) => e.key === "Enter" && clear(e as any)}
              className="rounded p-0.5 text-muted-foreground/50 hover:text-foreground transition-colors"
            >
              <XIcon />
            </span>
          )}
          <ChevronIcon open={open} />
        </span>
      </button>

      {/* Dropdown */}
      {open && (
        <div
          className={cn(
            "absolute left-0 right-0 z-50 mt-1.5",
            "rounded-xl border border-border/50 bg-popover",
            "shadow-[0_4px_6px_-1px_rgb(0,0,0,0.07),0_16px_40px_-4px_rgb(0,0,0,0.12)]",
            "animate-in fade-in-0 zoom-in-95 duration-100",
          )}
          style={{ transformOrigin: "top" }}
        >
          {/* Search input */}
          <div className="flex items-center gap-2 border-b border-border/40 px-3 py-2.5">
            <SearchIcon />
            <input
              ref={inputRef}
              value={query}
              onChange={(e) => { setQuery(e.target.value); setHighlighted(0) }}
              onKeyDown={onKeyDown}
              placeholder={searchPlaceholder}
              className="flex-1 bg-transparent text-sm text-foreground placeholder:text-muted-foreground/50 focus:outline-none"
            />
            {query && (
              <button
                onClick={() => { setQuery(""); setHighlighted(-1); inputRef.current?.focus() }}
                className="text-muted-foreground/40 hover:text-muted-foreground transition-colors"
              >
                <XIcon size={13} />
              </button>
            )}
          </div>

          {/* Options list */}
          <ul
            ref={listRef}
            role="listbox"
            className="max-h-56 overflow-y-auto py-1.5 overscroll-contain"
          >
            {filtered.length === 0 ? (
              <li className="px-3 py-6 text-center text-xs text-muted-foreground/60">
                {emptyMessage}
              </li>
            ) : (
              filtered.map((opt, i) => {
                const isSelected   = opt.value === value
                const isHighlighted = i === highlighted
                return (
                  <li
                    key={opt.value}
                    role="option"
                    aria-selected={isSelected}
                    onMouseEnter={() => setHighlighted(i)}
                    onClick={() => select(opt.value)}
                    className={cn(
                      "mx-1.5 flex cursor-pointer items-center gap-2.5 rounded-lg px-2.5 py-2 text-sm transition-colors duration-75",
                      isHighlighted && !isSelected && "bg-muted/60",
                      isSelected && "bg-primary/8 text-primary",
                    )}
                  >
                    {/* Icon */}
                    {opt.icon && (
                      <span className={cn("shrink-0", isSelected ? "text-primary" : "text-muted-foreground/70")}>
                        {opt.icon}
                      </span>
                    )}

                    {/* Text */}
                    <span className="flex min-w-0 flex-1 flex-col">
                      <span className={cn("truncate font-medium leading-tight", isSelected ? "text-primary" : "text-foreground")}>
                        {highlight(opt.label, query)}
                      </span>
                      {opt.description && (
                        <span className="truncate text-[11px] text-muted-foreground/60 leading-tight mt-0.5">
                          {highlight(opt.description, query)}
                        </span>
                      )}
                    </span>

                    {/* Check */}
                    {isSelected && (
                      <span className="ml-auto shrink-0 text-primary">
                        <CheckIcon />
                      </span>
                    )}
                  </li>
                )
              })
            )}
          </ul>

          {/* Footer count */}
          {query && filtered.length > 0 && (
            <div className="border-t border-border/30 px-3 py-1.5 text-[10px] text-muted-foreground/40 tabular-nums">
              {filtered.length} of {options.length} results
            </div>
          )}
        </div>
      )}
    </div>
  )
}

// ─── Icons ────────────────────────────────────────────────────────────────────

function SearchIcon() {
  return (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="shrink-0 text-muted-foreground/50">
      <circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>
    </svg>
  )
}

function XIcon({ size = 14 }: { size?: number }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
      <path d="M18 6 6 18M6 6l12 12"/>
    </svg>
  )
}

function ChevronIcon({ open }: { open: boolean }) {
  return (
    <svg
      width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
      className={cn("text-muted-foreground/50 transition-transform duration-200", open && "rotate-180")}
    >
      <path d="m6 9 6 6 6-6"/>
    </svg>
  )
}

function CheckIcon() {
  return (
    <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M20 6 9 17l-5-5"/>
    </svg>
  )
}