import {useEffect, useRef, useState} from "@wordpress/element";
import {__} from "@wordpress/i18n";
import useClickOutside from "../../../../components/hooks/use-click-outside";

export default function Select({defaultValue, value, setValue, options, searchable, addNew, loadMore, filters, placeholder, className, validate, children, hasDeselect, deselectOptionLabel, disabled}) {
    const selectRef = useRef(null);
    const [isOpened, setIsOpened] = useState(false);
    const [inputValue, setInputValue] = useState('');
    const [searchTerm, setSearchTerm] = useState('');
    const [filteredOptions, setFilteredOptions] = useState(options);
    const pagination = useRef({
        page: 1,
        perPage: 10,
    });
    const [showLoadMore, setShowLoadMore] = useState(false);

    useClickOutside([selectRef], () => setIsOpened(false));

    useEffect(() => {
        pagination.current.page = 1;
    }, [filters]);

    useEffect(() => {
        // Update input value
        if (options?.length) {
            const selectedOption = options.find(option => isSelectedOption(option));
            setInputValue(selectedOption?.label || (defaultValue?.name || defaultValue?.title || defaultValue?.label) || '')
        } else {
            setInputValue('');
        }
    }, [value, options, defaultValue]);

    useEffect(() => {
        if (searchTerm?.length && options?.length) {
            setFilteredOptions(options.filter(option => option.label.toLowerCase().includes(searchTerm.toLowerCase())));
        } else {
            setFilteredOptions(options);
        }
    }, [searchTerm, options]);

    useEffect(() => {
        if (typeof loadMore === 'function' && options?.length >= (pagination.current.page * pagination.current.perPage)) {
            setShowLoadMore(true);
        } else {
            setShowLoadMore(false);
        }
    }, [options, pagination.current.page, pagination.current.perPage]);

    /**
     * Is selected option
     *
     * @param {object} option Option
     * @return {boolean}
     */
    const isSelectedOption = (option) => {
        if (!isNaN(option.value) || !isNaN(value)) {
            // Numeric
            return +option.value === +value;
        } else {
            return option.value === value;
        }
    }

    /**
     * Search an option(s)
     *
     * @param {Event} e Event
     */
    const searching = (e) => {
        setSearchTerm(e.target.value);
        // Keep opened if searching
        if (e.target.value) {
            setIsOpened(true);
        }
    }

    /**
     * Load more options
     */
    const loadMoreOptions = () => {
        loadMore(pagination.current.page + 1, pagination.current.perPage)?.then(res => {
            if (res) {
                pagination.current.page++;
            }
        });
    }

    /**
     * Update value
     *
     * @param {object} option Option data
     */
    const updateValue = (option) => {
        if (!option.disabled) {
            const newValue = option.extra || option.value;
            setValue(newValue);
            setIsOpened(false);
            setSearchTerm('');
            // Validate
            if (typeof validate === 'function') {
                validate(newValue);
            }
        }
    }

    /**
     * Render option
     *
     * @param {object} option Option data
     * @param {number} i Option index
     * @return {JSX.Element}
     */
    const renderOption = (option, i) => {
        return (
            <div key={i}
                 className={`lbaic-settings-select-menu-item${isSelectedOption(option) ? ' active' : ''}${option.disabled ? ' disabled' : ''}`}
                 onClick={() => updateValue(option)}>
                {!!option.icon &&
                    <svg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24'
                         className='lbaic-settings-select-menu-item-i'>
                        <use href={`#lbaic-settings-${option.icon}`}/>
                    </svg>}
                <span className='lbaic-settings-select-menu-item-label'>{option.label}</span>
                {option.badge || false}
            </div>
        );
    }

    return (
        <div ref={selectRef} className={`lbaic-settings-select-holder${className ? ' ' + className : ''}${isOpened ? ' opened' : ''}${disabled ? ' lbaic-settings-select-disabled' : ''}`}>
            <div className='lbaic-settings-select lbaic-settings-select-h-40' onClick={() => setIsOpened(!isOpened)}>
                {children}
                <div className='lbaic-settings-select-placeholder'>
                    <span className='lbaic-settings-select-placeholder-in'>{placeholder}</span>
                </div>
                <div className='lbaic-settings-select-arrow'>
                    <svg className='lbaic-settings-select-arrow-in' xmlns='http://www.w3.org/2000/svg' fill='none'
                         viewBox='0 0 24 24'>
                        <use href='#lbaic-settings-arrow'/>
                    </svg>
                </div>
            </div>
            <div className='lbaic-settings-select-menu'>
                <div className='lbaic-settings-select-menu-in lbaic-settings-scroll-y lbaic-settings-scroll-style'>
                    {hasDeselect &&
                        <div className='lbaic-settings-select-menu-item'
                             onClick={() => {
                                 setValue('');
                                 setIsOpened(false);
                             }}>
                            <span className='lbaic-settings-select-menu-item-label'>{deselectOptionLabel || placeholder}</span>
                        </div>}
                    {!!filteredOptions?.length && filteredOptions.map(renderOption)}
                    {!filteredOptions?.length &&
                        <div className='lbaic-settings-select-menu-item disabled'>
                            <span className='lbaic-settings-select-menu-item-label'>{__("No options available.", 'limb-chatbot')}</span>
                        </div>}
                    {showLoadMore &&
                        <div className='lbaic-settings-select-menu-action'>
                            <button type='button'
                                    className='lbaic-settings-button-reset lbaic-settings-select-menu-action-in'
                                    onClick={loadMoreOptions}>
                                <span className='lbaic-settings-select-menu-action-label'>{__("Load more", 'limb-chatbot')}</span>
                            </button>
                        </div>}
                    {typeof addNew === 'function' &&
                        <div className='lbaic-settings-select-menu-action'>
                            <button type='button'
                                    className='lbaic-settings-button-reset lbaic-settings-select-menu-action-in' onClick={addNew}>
                                <span className='lbaic-settings-select-menu-action-label'>{__("Add new", 'limb-chatbot')}</span>
                            </button>
                        </div>}
                </div>
            </div>
        </div>
    )
}