import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useInView } from 'react-intersection-observer';
import { alpha, autocompleteClasses, CircularProgress, createFilterOptions, FormControl, formHelperTextClasses, InputAdornment, inputBaseClasses, Autocomplete as MUIAutocomplete, Stack, TextField, Typography, useTheme, } from '@mui/material';
import { IconChevronDown, IconCirclePlus, IconExclamationCircle, IconX, } from '@tabler/icons-react';
import { debounce } from 'lodash';
import Chip from '../../Chip';
import Title from '../../Title';
import CustomHelperText from '../Base/CustomHelperText';
import CustomLabel from '../Base/CustomLabel';
import { getBorderColor } from '../utils';
import AutocompleteItem from './components/AutocompleteItem';
import VirtualizedListbox from './components/VirtualizedListbox';
import { getCreatableInputText, getCreatableValue, isCreatableOption, isEqualText, } from './constants';
const Autocomplete = (props) => {
    const [focused, setFocused] = useState(false);
    const theme = useTheme();
    const { t } = useTranslation('material_hu_only');
    const hasCreateRef = useRef(false);
    const { hasError, helperText, placeholder, label, fieldRef, onCreate, onChange, onLoadMore, hasMoreOptions, onInputChange = () => { }, isServerFiltered = true, renderTags, noOptionsMessage, renderOption, loadMoreIndexOffset = 0, virtualized = false, filterLimit, type, maxLength, startIcon, hidePopupIcon = false, ...fieldProps } = props;
    const [loadMoreRef] = useInView({
        onChange: inView => {
            if (inView) {
                onLoadMore?.();
            }
        },
    });
    const getStatusTextColor = () => {
        if (fieldProps.disabled) {
            return theme.palette.new.text.neutral.disabled;
        }
        return hasError
            ? theme.palette.new.text.feedback.error
            : theme.palette.new.text.neutral.lighter;
    };
    const statusTextColor = getStatusTextColor();
    // Search-style fields (start icon and/or no chevron) match the height and
    // padding of the standard `Inputs/Search` field instead of the shorter
    // default Autocomplete height.
    const isSearchStyle = !!startIcon || hidePopupIcon;
    const hasMultipleSelections = !!fieldProps.multiple &&
        Array.isArray(fieldProps.value) &&
        fieldProps.value.length > 0;
    const debouncedOnInputChange = useMemo(() => debounce(onInputChange, 500), []);
    useEffect(() => () => {
        debouncedOnInputChange.cancel();
    }, []);
    const defaultFilterOptions = createFilterOptions(filterLimit ? { limit: filterLimit } : undefined);
    const renderTagsFn = renderTags ??
        (fieldProps.multiple
            ? (value, getTagProps) => value.map((option, index) => {
                const { key, ...tagProps } = getTagProps({ index });
                return (_jsx(Chip, { label: option.label, sx: { m: 0.25 }, ...tagProps }, key));
            })
            : undefined);
    return (_jsxs(FormControl, { error: hasError, fullWidth: fieldProps.fullWidth ?? true, disabled: fieldProps.disabled, onFocus: () => setFocused(true), onBlur: () => setFocused(false), children: [label && _jsx(CustomLabel, { label: label }), _jsx(MUIAutocomplete, { fullWidth: true, selectOnFocus: true, handleHomeEndKeys: true, clearOnBlur: true, ...(virtualized
                    ? {
                        ListboxComponent: VirtualizedListbox,
                    }
                    : { ListboxProps: { sx: { maxHeight: 240 } } }), sx: {
                    [`& .${autocompleteClasses.inputRoot} .${autocompleteClasses.endAdornment}`]: {
                        color: 'inherit',
                        right: '16px',
                    },
                    [`& .${autocompleteClasses.clearIndicator}`]: {
                        color: 'inherit',
                        padding: '4px',
                        marginRight: 0,
                    },
                    [`& .${autocompleteClasses.popupIndicator}`]: {
                        color: 'inherit',
                        padding: '4px',
                        marginRight: 0,
                    },
                }, forcePopupIcon: hidePopupIcon ? false : 'auto', popupIcon: hidePopupIcon ? null : (_jsx(IconChevronDown, { style: { color: 'inherit' }, size: 20 })), clearIcon: _jsx(IconX, { style: { color: 'inherit' }, size: 20 }), getOptionKey: option => option.value, onInputChange: isServerFiltered ? debouncedOnInputChange : onInputChange, isOptionEqualToValue: (option, selected) => option.value === selected.value, filterOptions: (options, state) => {
                    const nextOptions = isServerFiltered
                        ? Array.from(options)
                        : defaultFilterOptions(options, state);
                    if (onCreate) {
                        const { inputValue, getOptionLabel } = state;
                        const trimmedInput = inputValue
                            .trim()
                            .slice(0, maxLength || Infinity);
                        const isExisting = nextOptions.some(option => isEqualText(inputValue, getOptionLabel(option)));
                        if (!isExisting && trimmedInput) {
                            hasCreateRef.current = true;
                            nextOptions.unshift({
                                label: t('hu_inputs.create_option', { label: inputValue }),
                                value: getCreatableValue(trimmedInput),
                            });
                        }
                        else {
                            hasCreateRef.current = false;
                        }
                    }
                    return nextOptions;
                }, renderOption: (...renderArgs) => {
                    const [{ key, ...optionProps }, option, state] = renderArgs;
                    const { index } = state;
                    const isCreatable = isCreatableOption(option.value);
                    const content = [
                        renderOption?.(...renderArgs) ?? (_jsx(AutocompleteItem, { ...optionProps, children: _jsxs(Stack, { sx: {
                                    flexDirection: 'row',
                                    alignItems: 'center',
                                    gap: 1,
                                    width: '100%',
                                }, children: [isCreatable && (_jsx(IconCirclePlus, { size: 20, color: theme.palette.primary.main })), _jsxs(Stack, { sx: {
                                            flexDirection: 'row',
                                            justifyContent: 'space-between',
                                            flex: 1,
                                        }, children: [_jsx(Title, { title: option.label, description: option.description, variant: "S", fontWeight: "fontWeightRegular", slotProps: {
                                                    title: {
                                                        sx: isCreatable
                                                            ? {
                                                                color: theme.palette.primary.main,
                                                            }
                                                            : undefined,
                                                    },
                                                } }), isCreatable && maxLength && (_jsxs(Typography, { variant: "globalS", children: [getCreatableInputText(option.value.toString()).length, "/", maxLength] }))] })] }) }, key)),
                    ];
                    const optionsLen = hasCreateRef.current
                        ? fieldProps.options.length
                        : fieldProps.options.length - 1;
                    const isLoadMoreVisible = index === optionsLen + loadMoreIndexOffset && hasMoreOptions;
                    const { className } = optionProps;
                    if (isLoadMoreVisible) {
                        content.push(_jsx(AutocompleteItem, { ref: loadMoreRef, className: className, sx: {
                                alignItems: 'center',
                                justifyContent: 'center !important',
                                [`&.${autocompleteClasses.option}:hover`]: {
                                    backgroundColor: 'transparent',
                                },
                            }, children: _jsx(CircularProgress, { size: 24 }) }, "load-more"));
                    }
                    return content;
                }, disableCloseOnSelect: fieldProps.multiple, onChange: (_event, selectedOption, reason) => {
                    const nextValue = fieldProps.multiple
                        ? selectedOption?.[selectedOption?.length - 1]?.value
                        : selectedOption?.value;
                    if (reason === 'selectOption' && isCreatableOption(nextValue)) {
                        onCreate?.(getCreatableInputText(nextValue));
                    }
                    else {
                        onChange?.(selectedOption, reason);
                    }
                }, getOptionLabel: option => isCreatableOption(option.value)
                    ? getCreatableInputText(option.value)
                    : option.label, ...fieldProps, ref: fieldRef, renderInput: params => (_jsx(TextField, { variant: "outlined", type: type, ...params, inputProps: {
                        ...params.inputProps,
                        maxLength,
                    }, error: hasError, FormHelperTextProps: {
                        component: 'div',
                        sx: { display: 'contents' },
                    }, helperText: _jsx(CustomHelperText, { component: "span", helperText: helperText, value: "" }), placeholder: hasMultipleSelections ? undefined : placeholder, sx: {
                        [`& .${formHelperTextClasses.root}`]: {
                            mt: 1,
                            mx: 0,
                            color: theme.palette.new.text.neutral.lighter,
                        },
                        [`.${inputBaseClasses.root}`]: {
                            backgroundColor: fieldProps.disabled
                                ? theme.palette.new.background.elements.disabled
                                : theme.palette.new.background.elements.default,
                            ...(isSearchStyle && {
                                minHeight: 56,
                                pt: 0,
                                pb: 0,
                                // Horizontal padding only matters when a start icon occupies
                                // the leading space; `hidePopupIcon` alone keeps default padding.
                                ...(startIcon && {
                                    pl: 1.75,
                                    [`& .${autocompleteClasses.input}`]: {
                                        pl: 0,
                                    },
                                }),
                            }),
                        },
                        [`.${inputBaseClasses.root} input::placeholder`]: {
                            color: theme.palette.new.text.neutral.lighter,
                            opacity: 1,
                        },
                        [`.${inputBaseClasses.root} fieldset`]: {
                            transition: 'border 125ms ease',
                            borderWidth: '1px !important',
                            borderColor: `${getBorderColor(theme, focused, hasError, false, !!(fieldProps.value && (Array.isArray(fieldProps.value) ? fieldProps.value.length > 0 : true)))} !important`,
                        },
                    }, InputProps: {
                        ...params.InputProps,
                        startAdornment: startIcon ? (_jsxs(_Fragment, { children: [_jsx(InputAdornment, { position: "start", sx: {
                                        alignSelf: 'center',
                                        height: 3,
                                        mr: 1,
                                        color: theme.palette.new.text.neutral.lighter,
                                    }, children: startIcon }), params.InputProps.startAdornment ?? null] })) : (params.InputProps.startAdornment),
                        endAdornment: (_jsxs(InputAdornment, { position: "end", sx: { color: 'inherit' }, children: [params.InputProps.endAdornment, fieldProps.loading && (_jsx(CircularProgress, { sx: { color: 'inherit' }, size: 20 })), hasError && (_jsx(IconExclamationCircle, { size: 20, style: {
                                        color: statusTextColor,
                                    } }))] })),
                        sx: {
                            ...(fieldProps.disabled && {
                                bgcolor: alpha(theme.palette.new.border.neutral.default, 0.5),
                                border: `1px solid ${theme.palette.new.border.neutral.default}`,
                            }),
                            color: theme.palette.new.text.neutral.default,
                            fontSize: 'globalS',
                            transition: 'border 0.3s ease',
                        },
                    }, InputLabelProps: {
                        shrink: params.inputProps.ref
                            .current === document.activeElement ||
                            !!params.inputProps.value ||
                            fieldProps.loading,
                    } })), noOptionsText: _jsx(Title, { variant: "S", title: noOptionsMessage?.title || t('hu_inputs.no_results_found'), description: noOptionsMessage
                        ? noOptionsMessage.description
                        : t('hu_inputs.select_option_in_list') }), loadingText: _jsx(Title, { variant: "S", title: t('hu_inputs.loading') }), renderTags: renderTagsFn, getLimitTagsText: more => (_jsx(Chip, { disabled: fieldProps.disabled, label: `+${more}`, sx: { m: 0.25 } })) })] }));
};
export default Autocomplete;
