"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useAsyncOptions = void 0;
const debounce_1 = require("@astral/utils/debounce");
const react_1 = require("react");
const useLoadingState_1 = require("../useLoadingState");
/**
 * Хук для асинхронной загрузки опций в компонентах с поиском.
 * Управляет задержкой, отменой запросов и состояниями загрузки.
 */
const useAsyncOptions = ({ fetchOptions, fetchDelayMs, minSymbolsToFetch, onDataLoadError, isSmoothLoading, }) => {
    const [isLoadingData, setIsLoadingData] = (0, react_1.useState)(false);
    const [isFirstOpen, setIsFirstOpen] = (0, react_1.useState)(true);
    const [isLoadingError, setIsLoadingError] = (0, react_1.useState)(false);
    const abortControllerRef = (0, react_1.useRef)(null);
    const { isShowLoader } = (0, useLoadingState_1.useLoadingState)(isLoadingData);
    const [options, setOptions] = (0, react_1.useState)({
        options: [],
    });
    const optionsAdapter = (0, react_1.useCallback)((response) => {
        return Array.isArray(response) ? { options: response } : response;
    }, []);
    const debouncedFetchOptions = (0, react_1.useCallback)((0, debounce_1.debounce)((search) => {
        abortControllerRef.current?.abort();
        const controller = new AbortController();
        abortControllerRef.current = controller;
        setIsLoadingError(false);
        fetchOptions(search, controller?.signal)
            .then((response) => {
            const normalizeResponse = optionsAdapter(response);
            setOptions(normalizeResponse);
        })
            .catch((error) => {
            // CanceledError название ошибки в axios для отмены запроса
            if (error.name !== 'AbortError' && error.name !== 'CanceledError') {
                setIsLoadingError(true);
                onDataLoadError?.(error);
            }
        })
            .finally(() => {
            setIsLoadingData(false);
            abortControllerRef.current = null;
        });
    }, fetchDelayMs), [fetchOptions, fetchDelayMs]);
    const onInputChange = (search, reason) => {
        if ((!search.length && minSymbolsToFetch > 0) ||
            search.length < minSymbolsToFetch) {
            if (debouncedFetchOptions.isPending) {
                debouncedFetchOptions.clear();
            }
            setIsLoadingData(false);
            setOptions({ options: [] });
            return;
        }
        if (!isFirstOpen) {
            if (reason === 'input') {
                setIsLoadingData(true);
            }
            debouncedFetchOptions(search);
        }
    };
    const onOpen = (defaultSearch = '', defaultValue, isAlwaysTriggerOnOpen = false) => {
        if (isFirstOpen || isAlwaysTriggerOnOpen) {
            setIsFirstOpen(false);
            if (defaultValue || minSymbolsToFetch === 0) {
                setIsLoadingData(true);
                debouncedFetchOptions(defaultSearch);
            }
        }
    };
    const onRetry = (search) => {
        if (debouncedFetchOptions.isPending) {
            debouncedFetchOptions.clear();
        }
        setIsLoadingData(true);
        debouncedFetchOptions(search);
    };
    return {
        options: options.options,
        meta: options.meta,
        isLoadingData: isSmoothLoading ? isShowLoader : isLoadingData,
        onRetry,
        isLoadingError,
        debouncedFetchOptions,
        onInputChange,
        onOpen,
    };
};
exports.useAsyncOptions = useAsyncOptions;
