import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions, Transition } from '@headlessui/react'
import { CheckIcon, ChevronUpDownIcon, XMarkIcon } from '@heroicons/react/20/solid'
import { Fragment, useState, useMemo } from 'react'
import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

export interface SearchableSelectOption {
    value: string | number
    label: string
}

interface SearchableSelectProps {
    options: SearchableSelectOption[]
    value: string | number | null
    onChange: (value: string | number | null) => void
    placeholder?: string
    className?: string
    nullable?: boolean
}

export default function SearchableSelect({
    options,
    value,
    onChange,
    placeholder = "Select...",
    className,
    nullable = true
}: SearchableSelectProps) {
    const [query, setQuery] = useState('')

    const selectedOption = useMemo(() =>
        options.find(opt => String(opt.value) === String(value)) || null,
        [options, value]);

    const filteredOptions = query === ''
        ? options
        : options.filter((option) =>
            option.label
                .toLowerCase()
                .replace(/\s+/g, '')
                .includes(query.toLowerCase().replace(/\s+/g, ''))
        )

    return (
        <div className={twMerge("w-full relative", className)}>
            <Combobox value={selectedOption} onChange={(val) => onChange(val ? val.value : null)}>
                <div className="relative mt-1">
                    <div className="relative w-full cursor-default overflow-hidden rounded-md bg-white text-left border border-gray-300 focus-within:ring-2 focus-within:ring-vulncheck-blue focus-within:border-vulncheck-blue sm:text-sm">
                        <ComboboxInput
                            className="w-full border-none py-2 pl-3 pr-10 text-sm leading-5 text-gray-900 focus:ring-0 font-mono placeholder:text-gray-400"
                            displayValue={(option: SearchableSelectOption | null) => option ? option.label : ''}
                            onChange={(event) => setQuery(event.target.value)}
                            placeholder={placeholder}
                        />
                        <ComboboxButton className="absolute inset-y-0 right-0 flex items-center pr-2">
                            <ChevronUpDownIcon
                                className="h-5 w-5 text-gray-400"
                                aria-hidden="true"
                            />
                        </ComboboxButton>
                    </div>
                    <Transition
                        as={Fragment}
                        leave="transition ease-in duration-100"
                        leaveFrom="opacity-100"
                        leaveTo="opacity-0"
                        afterLeave={() => setQuery('')}
                    >
                        <ComboboxOptions className="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black/5 focus:outline-none sm:text-sm z-50">
                            {filteredOptions.length === 0 && query !== '' ? (
                                <div className="relative cursor-default select-none px-4 py-2 text-gray-700 font-mono">
                                    Nothing found.
                                </div>
                            ) : (
                                filteredOptions.map((option) => (
                                    <ComboboxOption
                                        key={option.value}
                                        className={({ active }) =>
                                            `relative cursor-default select-none py-2 pl-10 pr-4 font-mono ${active ? 'bg-vulncheck-blue text-white' : 'text-gray-900'
                                            }`
                                        }
                                        value={option}
                                    >
                                        {({ selected, active }) => (
                                            <>
                                                <span
                                                    className={`block truncate ${selected ? 'font-medium' : 'font-normal'
                                                        }`}
                                                >
                                                    {option.label}
                                                </span>
                                                {selected ? (
                                                    <span
                                                        className={`absolute inset-y-0 left-0 flex items-center pl-3 ${active ? 'text-white' : 'text-vulncheck-blue'
                                                            }`}
                                                    >
                                                        <CheckIcon className="h-5 w-5" aria-hidden="true" />
                                                    </span>
                                                ) : null}
                                            </>
                                        )}
                                    </ComboboxOption>
                                ))
                            )}
                        </ComboboxOptions>
                    </Transition>
                </div>
            </Combobox>
            {nullable && value && (
                <button
                    onClick={(e) => {
                        e.stopPropagation();
                        onChange(null)
                    }}
                    className="absolute inset-y-0 right-8 flex items-center pr-2 text-gray-400 hover:text-gray-600 z-10"
                    title="Clear selection"
                >
                    <XMarkIcon className="h-4 w-4" />
                </button>
            )}
        </div>
    )
}
