import {
    Listbox,
    ListboxButton,
    ListboxOption,
    ListboxOptions,
} from '@headlessui/react';
import { Check, ChevronsUpDown, X } from 'lucide-react';
import React from 'react';

import { Badge } from '@/components/ui/badge';
import { cn } from '@/lib/utils';

export interface Option {
    label: string;
    value: string;
}

interface MultiSelectProps {
    options: Option[];
    value: string[];
    onChange: (value: string[]) => void;
    placeholder?: string;
    className?: string;
    disabled?: boolean;
    ariaLabelledBy?: string;
}

export function MultiSelect({
    options,
    value,
    onChange,
    placeholder = 'Select items',
    className,
    disabled = false,
    ariaLabelledBy,
}: MultiSelectProps) {
    // Map selected value IDs back to their full option objects for pill rendering
    const selectedOptions = options.filter((opt) => value.includes(opt.value));

    const handleRemove = (e: React.MouseEvent, valToRemove: string) => {
        e.preventDefault();
        e.stopPropagation();
        onChange(value.filter((v) => v !== valToRemove));
    };

    return (
        <Listbox
            value={value}
            onChange={onChange}
            multiple
            disabled={disabled}
        >
            <div className="relative">
                <ListboxButton
                    aria-labelledby={ariaLabelledBy}
                    className={cn(
                        'relative flex min-h-11 w-full cursor-pointer items-center justify-between rounded-xl border border-input bg-background px-3 py-2 text-left text-sm shadow-xs transition-colors focus:outline-none focus:ring-2 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
                        className,
                    )}
                >
                    <div className="flex flex-wrap gap-1.5 pr-6">
                        {selectedOptions.length > 0 ? (
                            selectedOptions.map((opt) => (
                                <Badge
                                    key={opt.value}
                                    variant="secondary"
                                    className="flex items-center gap-1 rounded-lg px-2 py-0.5 text-xs font-medium"
                                >
                                    {opt.label}
                                    {!disabled && (
                                        <div
                                            role="button"
                                            onClick={(e) =>
                                                handleRemove(e, opt.value)
                                            }
                                            className="ml-1 rounded-full text-muted-foreground hover:text-foreground"
                                        >
                                            <X size={12} />
                                        </div>
                                    )}
                                </Badge>
                            ))
                        ) : (
                            <span className="text-muted-foreground">
                                {placeholder}
                            </span>
                        )}
                    </div>
                    <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
                        <ChevronsUpDown
                            className="h-4 w-4 text-muted-foreground"
                            aria-hidden="true"
                        />
                    </span>
                </ListboxButton>

                <ListboxOptions
                    transition
                    className="absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-xl border bg-popover py-1 text-base shadow-lg ring-1 ring-black/5 outline-none transition duration-100 ease-in data-closed:opacity-0 sm:text-sm"
                >
                    {options.length === 0 ? (
                        <div className="relative cursor-default select-none px-4 py-2 text-muted-foreground">
                            No options found.
                        </div>
                    ) : (
                        options.map((option) => {
                            const isSelected = value.includes(option.value);

                            return (
                                <ListboxOption
                                    key={option.value}
                                    value={option.value}
                                    className={({ focus }) =>
                                        cn(
                                            'relative cursor-pointer select-none py-2 pl-10 pr-4',
                                            focus
                                                ? 'bg-accent text-accent-foreground'
                                                : 'text-popover-foreground',
                                        )
                                    }
                                >
                                    {({ selected }) => (
                                        <>
                                            <span
                                                className={cn(
                                                    'block truncate',
                                                    selected
                                                        ? 'font-semibold'
                                                        : 'font-normal',
                                                )}
                                            >
                                                {option.label}
                                            </span>
                                            {selected ? (
                                                <span
                                                    className={cn(
                                                        'absolute inset-y-0 left-0 flex items-center pl-3',
                                                        'text-primary',
                                                    )}
                                                >
                                                    <Check
                                                        className="h-4 w-4"
                                                        aria-hidden="true"
                                                    />
                                                </span>
                                            ) : null}
                                        </>
                                    )}
                                </ListboxOption>
                            );
                        })
                    )}
                </ListboxOptions>
            </div>
        </Listbox>
    );
}
