import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import clsx from 'clsx';
import { isEqual } from 'lodash-es';
import { Check, ChevronsUpDown, SearchIcon, SquarePlus, X } from 'lucide-react';
import { useState, useEffect, useRef } from 'react';
import { Popover, PopoverContent, PopoverTrigger, PopoverClose } from './popover';
import { Command, CommandEmpty, CommandGroup, CommandItem, CommandList } from './command';
import { Input } from './input';
import { Button } from '@vertesia/ui/core';
export function VSelectBox({ options, optionLabel, value, onChange, addNew, addNewLabel, disabled, filterBy, label, placeholder, className, popupClass, isClearable, border = true, multiple = false, by, inline = false }) {
    const triggerRef = useRef(null);
    const [open, setOpen] = useState(false);
    const [width, setWidth] = useState(0);
    const [filterValue, setFilterValue] = useState('');
    useEffect(() => {
        const element = triggerRef.current;
        if (!element) {
            return;
        }
        const updateWidth = () => {
            const contentWidth = element.getBoundingClientRect().width;
            setWidth(contentWidth);
        };
        const resizeObserver = new ResizeObserver(() => {
            updateWidth();
        });
        updateWidth();
        resizeObserver.observe(element);
        return () => {
            resizeObserver.disconnect();
        };
    }, []);
    const handleTriggerClick = (e) => {
        if (disabled) {
            e.preventDefault();
            return;
        }
        setOpen(!open);
    };
    const _onClick = (opt) => {
        if (multiple) {
            const currentValues = Array.isArray(value) ? value : [];
            const isSelected = isOptionSelected(opt, currentValues);
            if (isSelected) {
                // Remove from selection
                const newValues = currentValues.filter(v => !isOptionsEqual(v, opt));
                onChange(newValues);
            }
            else {
                // Add to selection
                onChange([...currentValues, opt]);
            }
            // Don't close the popover in multiple mode
        }
        else {
            setOpen(false);
            onChange(opt);
        }
    };
    // Helper function to check if an option is selected
    const isOptionSelected = (option, selectedValues) => {
        if (!selectedValues || selectedValues.length === 0)
            return false;
        return selectedValues.some(v => isOptionsEqual(v, option));
    };
    // Helper function to compare options for equality
    const isOptionsEqual = (a, b) => {
        // Handle null/undefined values
        if (a == null || b == null) {
            return a === b;
        }
        if (typeof by === 'string') {
            return a[by] === b[by];
        }
        else if (typeof by === 'function') {
            return by(a, b);
        }
        else {
            return isEqual(a, b);
        }
    };
    let filteredOptions = options || [];
    function getFilterByFn(filterBy) {
        if (!filterBy) {
            return (o) => String(o).toLowerCase();
        }
        else if (typeof filterBy === 'string') {
            return (o) => String(o[filterBy]).toLowerCase();
        }
        else {
            return filterBy;
        }
    }
    const filterLc = filterValue.toLowerCase();
    const filterFn = getFilterByFn(filterBy);
    filteredOptions = filteredOptions.filter(o => filterFn(o).includes(filterLc));
    const renderSingleValue = () => {
        if (!value || (Array.isArray(value) && value.length === 0)) {
            return _jsx("span", { className: "text-muted", children: placeholder });
        }
        const singleValue = Array.isArray(value) ? value[0] : value;
        return optionLabel ? optionLabel(singleValue) : singleValue;
    };
    const renderMultipleValue = () => {
        const arrayValue = Array.isArray(value) ? value : (value ? [value] : []);
        if (arrayValue.length === 0) {
            return _jsx("span", { className: "text-muted", children: placeholder });
        }
        if (arrayValue.length === 1) {
            return optionLabel ? optionLabel(arrayValue[0]) : arrayValue[0];
        }
        return (_jsxs("div", { className: "flex flex-wrap gap-1", children: [arrayValue.slice(0, 1).map((item, index) => (_jsx("span", { className: "inline-flex items-center gap-1 px-2 py-1 text-xs bg-muted rounded", children: optionLabel ? optionLabel(item) : item }, index))), arrayValue.length > 1 && (_jsxs("span", { className: "inline-flex items-center px-2 py-1 text-xs bg-muted rounded", children: ["+", arrayValue.length - 1, " more"] }))] }));
    };
    // Render the options list content
    const renderOptionsContent = () => (_jsxs(_Fragment, { children: [filterBy && (_jsxs("div", { className: 'flex justify-start items-center mb-1', children: [_jsx("div", { className: 'mx-2', children: _jsx(SearchIcon, { className: "size-4" }) }), _jsx(Input, { variant: 'unstyled', value: filterValue, onChange: setFilterValue, className: "w-full p-1 rounded-md", placeholder: "Search..." })] })), _jsx(Command, { className: "overflow-hidden", children: _jsxs(CommandList, { className: inline ? "max-h-full overflow-y-auto" : "max-h-[200px] overflow-y-auto", children: [_jsx(CommandEmpty, { children: "No result found." }), _jsx(CommandGroup, { className: "overflow-visible", children: filteredOptions?.map((opt, index) => {
                                const isSelected = multiple
                                    ? isOptionSelected(opt, Array.isArray(value) ? value : [])
                                    : value != null ? isOptionsEqual(value, opt) : false;
                                return (_jsx(CommandItem, { onSelect: () => _onClick(opt), className: "w-full", children: multiple || inline ? (_jsxs("div", { className: 'w-full flex justify-between items-center cursor-pointer', children: [_jsx("div", { className: 'w-full truncate text-left', children: optionLabel ? optionLabel(opt) : opt }), isSelected && _jsx(Check, { className: "size-4" })] })) : (_jsxs(PopoverClose, { className: 'w-full flex justify-between items-center', children: [_jsx("div", { className: 'w-full truncate text-left', children: optionLabel ? optionLabel(opt) : opt }), isSelected && _jsx(Check, { className: "size-4" })] })) }, index));
                            }) })] }) }), addNew && (_jsx("div", { className: 'p-1', children: _jsxs("a", { onClick: addNew, className: clsx('gap-x-2 px-2 py-1.5 truncate group flex rounded-md items-center text-sm cursor-pointer hover:bg-accent'), children: [_jsx(SquarePlus, { size: 16, strokeWidth: 1.25, absoluteStrokeWidth: true }), addNewLabel] }) }))] }));
    if (inline) {
        return (_jsx("div", { className: clsx(className, border && 'border border-border rounded-md', "bg-popover p-1", popupClass), children: renderOptionsContent() }));
    }
    return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("div", { ref: triggerRef, onClick: handleTriggerClick, className: clsx(className, border && 'border border-border', 'flex flex-row gap-2 items-center justify-between p-2 rounded-md group relative [&:hover_.clear-button]:opacity-100', !disabled ? "cursor-pointer hover:bg-muted" : "cursor-not-allowed text-muted"), children: [_jsxs("div", { className: clsx("flex flex-col w-full rounded-md text-sm items-center justify-center truncate", !disabled && "", isClearable && value && (Array.isArray(value) ? value.length > 0 : true) && "pr-6"), children: [label && _jsx("div", { className: 'w-full text-left text-xs font-semibold', children: label }), _jsx("div", { className: clsx('w-full text-left', !disabled && ''), children: multiple ? renderMultipleValue() : renderSingleValue() })] }), _jsxs("div", { className: "flex items-center gap-1 group", children: [isClearable && value && (Array.isArray(value) ? value.length > 0 : true) && (_jsx(Button, { variant: "link", size: "icon", alt: "Clear selection", onClick: (e) => {
                                        e.stopPropagation();
                                        if (multiple) {
                                            onChange([]);
                                        }
                                        else {
                                            onChange(undefined);
                                        }
                                    }, className: "cursor-pointer hover:bg-muted/20 clear-button opacity-0 transition-opacity duration-200 rounded p-1", children: _jsx(X, { className: "size-4" }) })), !disabled && (_jsx(ChevronsUpDown, { className: "size-4 opacity-50" }))] })] }) }), _jsx(PopoverContent, { style: { width: `${width}px`, zIndex: 1000000 }, className: clsx("min-w-[8rem] w-64 bg-popover p-1 border shadow", "divide-y divide-border", popupClass), children: renderOptionsContent() })] }));
}
//# sourceMappingURL=selectBox.js.map