import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useEffect } from "react";
import { cn } from "../../libs/utils";
import { Button } from "../button";
import { Popover, PopoverTrigger, PopoverContent } from "../popover";
import { Command, CommandInput, CommandList, CommandGroup, CommandItem, CommandEmpty } from "../command";
import { ListFilter } from "lucide-react";
import Filters from "./filters";
import TextFilter from "./filter/TextFilter";
import DateFilter from "./filter/dateFilter";
import SelectFilter from "./filter/SelectFilter";
import StringListFilter from "./filter/StringListFilter";
const FilterContext = React.createContext({});
const FilterProvider = ({ filters, setFilters, filterGroups, children }) => {
    const url = new URL(window.location.href);
    const searchParams = url.searchParams;
    const [hasInitialized, setHasInitialized] = React.useState(false);
    useEffect(() => {
        try {
            const params = new URLSearchParams(searchParams.toString());
            if (filters.length > 0) {
                // Convert filters to format with array indicators: filterName:value,value;filterName2:value
                // Arrays are prefixed with []: filterName:[value1,value2]
                const filterString = filters.map(filter => {
                    let values;
                    if (filter.type === 'stringList' && Array.isArray(filter.value) && typeof filter.value[0] === 'string') {
                        // Handle stringList with direct string array - always array format
                        values = `[${filter.value.map(item => encodeURIComponent(item)).join(',')}]`;
                    }
                    else if (Array.isArray(filter.value)) {
                        if (filter.multiple) {
                            // Handle multiple filters - always use array format for multiple=true
                            values = `[${filter.value.map((item) => encodeURIComponent(item.value || item || '')).join(',')}]`;
                        }
                        else if (filter.value.length > 1) {
                            // Handle multiple values for non-multiple filters
                            values = `[${filter.value.map((item) => encodeURIComponent(item.value || item || '')).join(',')}]`;
                        }
                        else {
                            // Single value in array for non-multiple filter - don't use array format
                            const firstValue = filter.value[0];
                            if (typeof firstValue === 'string') {
                                values = encodeURIComponent(firstValue);
                            }
                            else if (typeof firstValue === 'object' && firstValue?.value !== undefined) {
                                // Handle FilterOption object
                                values = encodeURIComponent(String(firstValue.value));
                            }
                            else {
                                values = encodeURIComponent(String(firstValue || ''));
                            }
                        }
                    }
                    else {
                        values = encodeURIComponent(filter.value || '');
                    }
                    return `${encodeURIComponent(filter.name)}:${values}`;
                }).join(';');
                params.set('filters', filterString);
            }
            else {
                params.delete('filters');
            }
            const newUrl = `${window.location.pathname}?${params.toString()}${window.location.hash}`;
            window.history.replaceState(window.history.state || {}, '', newUrl);
        }
        catch (error) {
            console.error("Failed to update URL with filters:", error);
        }
    }, [filters]);
    useEffect(() => {
        const filtersParam = searchParams.get('filters');
        if (filtersParam && filterGroups.length > 0 && !hasInitialized) {
            try {
                // Parse format with array indicators: filterName:value or filterName:[value1,value2]
                const filterPairs = filtersParam.split(';');
                const parsedFilters = filterPairs.map(pair => {
                    const [encodedName, valuesString] = pair.split(':');
                    const name = decodeURIComponent(encodedName);
                    let values;
                    // Check if it's an array format [value1,value2]
                    if (valuesString.startsWith('[') && valuesString.endsWith(']')) {
                        // Array format - remove brackets and split by comma
                        const arrayContent = valuesString.slice(1, -1); // Remove [ and ]
                        values = arrayContent ? arrayContent.split(',').map(encodedValue => decodeURIComponent(encodedValue)) : [];
                    }
                    else {
                        // Single value format
                        values = [decodeURIComponent(valuesString)];
                    }
                    const group = filterGroups.find(g => g.name === name);
                    let filterValue;
                    if (group?.type === 'stringList') {
                        // For stringList, return direct string array
                        filterValue = values;
                    }
                    else if (group?.type === 'text') {
                        // For text, return FilterOption array (single value for text inputs)
                        filterValue = values.length === 1 ? [{ value: values[0], label: values[0] }] :
                            values.map(value => ({ value, label: value }));
                    }
                    else {
                        // For other types, find options with labels
                        filterValue = values.map(value => {
                            const matchingOption = group?.options?.find(opt => opt.value === value);
                            let label = value;
                            if (matchingOption?.label) {
                                label = String(matchingOption.label);
                            }
                            else if (matchingOption?.labelRenderer) {
                                label = String(matchingOption.labelRenderer(value));
                            }
                            else if (group?.labelRenderer) {
                                label = String(group.labelRenderer(value));
                            }
                            return {
                                value,
                                label
                            };
                        });
                    }
                    if (group?.multiple && !valuesString.startsWith('[') && !valuesString.endsWith(']')) {
                        if (group.type === 'stringList') {
                            filterValue = values;
                        }
                        else {
                            if (!Array.isArray(filterValue)) {
                                filterValue = [filterValue];
                            }
                        }
                    }
                    // Fallback: if group not found but we detected array format, assume it should be multiple
                    const shouldBeMultiple = group?.multiple || (!group && valuesString.startsWith('[') && valuesString.endsWith(']'));
                    const filter = {
                        name,
                        type: group?.type || 'select',
                        placeholder: group?.placeholder,
                        value: filterValue,
                        multiple: shouldBeMultiple
                    };
                    return filter;
                });
                setFilters(parsedFilters);
                setHasInitialized(true);
            }
            catch (error) {
                setHasInitialized(true);
            }
        }
        else if (filterGroups.length > 0 && !hasInitialized) {
            // No URL params but we have groups - mark as initialized
            setHasInitialized(true);
        }
    }, [filterGroups, hasInitialized]);
    return (_jsx(FilterContext.Provider, { value: { filters, setFilters, filterGroups }, children: children }));
};
const FilterBtn = ({ className }) => {
    const { filters, setFilters, filterGroups } = React.useContext(FilterContext);
    const [open, setOpen] = React.useState(false);
    const [selectedView, setSelectedView] = React.useState(null);
    const [commandInput, setCommandInput] = React.useState("");
    const commandInputRef = React.useRef(null);
    const [selectedDate, setSelectedDate] = React.useState();
    const [textValue, setTextValue] = React.useState("");
    const handleSelect = (groupName) => {
        setSelectedView(groupName);
        setCommandInput("");
        commandInputRef.current?.focus();
    };
    const getAvailableFilterGroups = () => {
        let options = filterGroups.map(group => ({
            ...group,
            options: (group.options ?? []).filter(option => !filters.some(filter => {
                if (filter.type === "date") {
                    return filter.name === group.name;
                }
                return filter.name === group.name &&
                    (Array.isArray(filter.value) && typeof filter.value[0] === 'string'
                        ? filter.value.some(val => val === option.value)
                        : filter.value.some(val => val.value === option.value));
            }))
        })).filter(group => ((group.options ?? []).length > 0) ||
            (group.type === "date" && !filters.some(filter => filter.name === group.name)) ||
            (group.type === "text" && !filters.some(filter => filter.name === group.name)) ||
            (group.type === "stringList" && !filters.some(filter => filter.name === group.name)));
        if (options.length === 0) {
            return _jsx(CommandEmpty, { children: "No available filters" });
        }
        return options.map((group, index) => (_jsx(CommandItem, { onSelect: () => handleSelect(group.name), className: "group flex gap-2 items-center hover:bg-muted", children: _jsx("span", { children: group.placeholder ?? group.name }) }, index)));
    };
    const handleClose = () => {
        setOpen(false);
        setTimeout(() => {
            setSelectedView(null);
            setCommandInput("");
            setSelectedDate(undefined);
        }, 200);
    };
    const handleOpen = (open) => {
        setOpen(open);
        if (!open) {
            setTimeout(() => {
                setSelectedView(null);
                setCommandInput("");
                setTextValue("");
            }, 200);
        }
    };
    const renderFilterOptions = () => {
        if (!selectedView) {
            return null;
        }
        const selectedGroupType = filterGroups.find(g => g.name === selectedView)?.type;
        switch (selectedGroupType) {
            case "date":
                return (_jsx(DateFilter, { selectedView: selectedView, selectedDate: selectedDate, setSelectedDate: setSelectedDate, setFilters: setFilters, filters: filters, handleClose: handleClose, filterGroups: filterGroups }));
            case "text":
                return (_jsx(TextFilter, { selectedView: selectedView, textValue: textValue, setTextValue: setTextValue, setFilters: setFilters, handleClose: handleClose, filterGroups: filterGroups }));
            case "stringList":
                return (_jsx(StringListFilter, { selectedView: selectedView, setFilters: setFilters, handleClose: handleClose, filterGroups: filterGroups }));
            default:
                return (_jsx(SelectFilter, { selectedView: selectedView, commandInput: commandInput, setFilters: setFilters, handleClose: handleClose, filterGroups: filterGroups }));
        }
    };
    return (_jsxs(Popover, { _open: open, onOpenChange: handleOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", role: "combobox", "aria-expanded": open, size: "md", className: cn("transition group flex gap-1.5", className), children: [_jsx(ListFilter, { className: "size-4 shrink-0 transition-all text-muted" }), "Filter"] }) }), _jsx(PopoverContent, { className: "w-[300px] p-0", align: "start", sideOffset: 4, children: _jsxs(Command, { children: [filterGroups.find(group => group.name === selectedView)?.type === "select" && (_jsx(CommandInput, { placeholder: selectedView ? `Filter by ${selectedView}` : "Filter...", className: "h-9 ring-0", value: commandInput, onValueChange: (value) => {
                                setCommandInput(value);
                            }, ref: commandInputRef, autoFocus: true })), _jsx(CommandList, { children: _jsx(CommandGroup, { children: !selectedView ? getAvailableFilterGroups() : renderFilterOptions() }) })] }) })] }));
};
const FilterBar = ({ className }) => {
    const { filters, setFilters, filterGroups } = React.useContext(FilterContext);
    return (_jsx("div", { className: cn(className), children: _jsx(Filters, { filters: filters, setFilters: setFilters, filterGroups: filterGroups }) }));
};
const FilterClear = ({ className }) => {
    const { filters, setFilters } = React.useContext(FilterContext);
    const hasActiveFilters = filters.filter((filter) => filter.value?.length > 0).length > 0;
    if (!hasActiveFilters) {
        return null;
    }
    return (_jsx(Button, { variant: "outline", size: "xs", className: cn("transition group", className), onClick: () => setFilters([]), children: "Clear All" }));
};
export { FilterProvider, FilterBtn, FilterBar, FilterClear };
//# sourceMappingURL=filterBar.js.map