import { jsx } from "react/jsx-runtime";
import { useLingui } from "@lingui/react";
import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef } from "react";
import { useResourcePickerState } from "../hooks/use-resource-picker-state.js";
import { CHAT_RESOURCE_PICKER_SEARCH_DEBOUNCE_MS } from "../service/index.js";
import { useResourceData } from "./resource-data-provider.js";
function isResourceSelector(item) {
    return 'hasNestedResources' in item && true === item.hasNestedResources;
}
const PICKER_VERTICAL_OFFSET = 8;
const AutopilotChatResourcePickerContext = /*#__PURE__*/ createContext(null);
function AutopilotChatResourcePickerProvider({ children, onResourceSelect, onDrillDown, onClose }) {
    const { hasResources, topLevelResources, paginatedResources, getNestedResources, globalSearch, onResourceSelected } = useResourceData();
    const { _ } = useLingui();
    const [state, dispatch] = useResourcePickerState();
    const { anchorPosition, query, drillDown, loading, loadingMore, searchInProgress, error, searchResults, searchDone, previousDisplayCount } = state;
    const mentionRangeRef = useRef(null);
    const drillDownActiveRef = useRef(false);
    const isOpen = null !== anchorPosition;
    const isOpenRef = useRef(isOpen);
    useLayoutEffect(()=>{
        isOpenRef.current = isOpen;
    }, [
        isOpen
    ]);
    const searchQuery = useMemo(()=>query.trim().toLowerCase(), [
        query
    ]);
    const errorMessages = useMemo(()=>({
            load: _({
                id: 'autopilot-chat.resource-picker.error'
            }),
            loadMore: _({
                id: 'autopilot-chat.resource-picker.load-more-error'
            }),
            search: _({
                id: 'autopilot-chat.resource-picker.search-error'
            })
        }), [
        _
    ]);
    const open = useCallback((range, coords)=>{
        if (!hasResources) return;
        mentionRangeRef.current = range;
        dispatch({
            type: 'OPEN',
            coords: {
                top: coords.top - PICKER_VERTICAL_OFFSET,
                left: coords.left
            }
        });
    }, [
        hasResources,
        dispatch
    ]);
    const close = useCallback(()=>{
        if (!isOpenRef.current) return;
        isOpenRef.current = false;
        onClose?.();
        drillDownActiveRef.current = false;
        mentionRangeRef.current = null;
        dispatch({
            type: 'CLOSE'
        });
    }, [
        dispatch,
        onClose
    ]);
    const handleMentionEnd = useCallback(()=>{
        if (drillDownActiveRef.current) {
            drillDownActiveRef.current = false;
            return;
        }
        close();
    }, [
        close
    ]);
    const setQuery = useCallback((newQuery, range)=>{
        if (!hasResources) return;
        mentionRangeRef.current = range;
        dispatch({
            type: 'SET_QUERY',
            query: newQuery
        });
    }, [
        hasResources,
        dispatch
    ]);
    const loadNestedResources = useCallback(async (category)=>{
        dispatch({
            type: 'LOAD_START'
        });
        try {
            const result = await getNestedResources(category.id);
            dispatch({
                type: 'DRILL_DOWN_SUCCESS',
                category,
                resources: result.items,
                done: result.done ?? true
            });
        } catch  {
            dispatch({
                type: 'LOAD_ERROR',
                error: errorMessages.load
            });
        }
    }, [
        getNestedResources,
        errorMessages.load,
        dispatch
    ]);
    const handleItemClick = useCallback((item)=>{
        if (isResourceSelector(item)) {
            drillDownActiveRef.current = true;
            onDrillDown?.();
            dispatch({
                type: 'SET_QUERY',
                query: ''
            });
            loadNestedResources(item);
            return;
        }
        onResourceSelected(item);
        onResourceSelect(item, mentionRangeRef.current ?? void 0);
        close();
    }, [
        loadNestedResources,
        onResourceSelect,
        onResourceSelected,
        onDrillDown,
        close,
        dispatch
    ]);
    const goBackOrClose = useCallback(()=>{
        if (drillDown) {
            drillDownActiveRef.current = false;
            dispatch({
                type: 'GO_BACK'
            });
            return;
        }
        close();
    }, [
        drillDown,
        close,
        dispatch
    ]);
    const loadMore = useCallback(async ()=>{
        if (!paginatedResources || loadingMore) return;
        const isSearch = !!searchQuery;
        if (isSearch && searchDone) return;
        if (!isSearch && (!drillDown || drillDown.done)) return;
        dispatch({
            type: 'LOAD_MORE_START'
        });
        try {
            const result = isSearch ? drillDown ? await getNestedResources(drillDown.category.id, {
                searchText: searchQuery,
                skip: searchResults.length
            }) : await globalSearch({
                searchText: searchQuery,
                skip: searchResults.length
            }) : await getNestedResources(drillDown.category.id, {
                skip: drillDown.resources.length
            });
            dispatch({
                type: 'LOAD_MORE_SUCCESS',
                target: isSearch ? 'search' : 'drillDown',
                items: result.items,
                done: result.done ?? true
            });
        } catch  {
            dispatch({
                type: 'LOAD_ERROR',
                error: errorMessages.loadMore
            });
        }
    }, [
        paginatedResources,
        loadingMore,
        searchQuery,
        searchDone,
        drillDown,
        searchResults.length,
        getNestedResources,
        globalSearch,
        errorMessages.loadMore,
        dispatch
    ]);
    const performPaginatedSearch = useCallback(async ()=>{
        try {
            const result = drillDown ? await getNestedResources(drillDown.category.id, {
                searchText: searchQuery
            }) : await globalSearch({
                searchText: searchQuery
            });
            dispatch({
                type: 'SEARCH_SUCCESS',
                results: result.items,
                done: result.done ?? true
            });
        } catch  {
            dispatch({
                type: 'LOAD_ERROR',
                error: errorMessages.search
            });
        }
    }, [
        drillDown,
        searchQuery,
        getNestedResources,
        globalSearch,
        errorMessages.search,
        dispatch
    ]);
    const performLocalSearch = useCallback(async ()=>{
        if (drillDown) {
            const filtered = drillDown.resources.filter((item)=>item.displayName.toLowerCase().includes(searchQuery));
            dispatch({
                type: 'SEARCH_SUCCESS',
                results: filtered,
                done: true
            });
            return;
        }
        const results = [];
        for (const topLevel of topLevelResources){
            if (topLevel.displayName.toLowerCase().includes(searchQuery)) results.push(topLevel);
            if (topLevel.hasNestedResources) try {
                const result = await getNestedResources(topLevel.id);
                for (const item of result.items)if (item.displayName.toLowerCase().includes(searchQuery)) results.push(item);
            } catch  {}
        }
        dispatch({
            type: 'SEARCH_SUCCESS',
            results,
            done: true
        });
    }, [
        drillDown,
        searchQuery,
        topLevelResources,
        getNestedResources,
        dispatch
    ]);
    const retryLoad = useCallback(()=>{
        if (searchQuery) {
            dispatch({
                type: 'SEARCH_START'
            });
            paginatedResources ? performPaginatedSearch() : performLocalSearch();
        } else if (drillDown) loadNestedResources(drillDown.category);
    }, [
        searchQuery,
        drillDown,
        paginatedResources,
        dispatch,
        loadNestedResources,
        performPaginatedSearch,
        performLocalSearch
    ]);
    const displayedItems = useMemo(()=>{
        if (searchQuery) return searchResults;
        if (drillDown) return drillDown.resources;
        return topLevelResources;
    }, [
        searchQuery,
        searchResults,
        drillDown,
        topLevelResources
    ]);
    useEffect(()=>{
        if (!isOpen) return;
        if (!searchQuery) return void dispatch({
            type: 'CLEAR_SEARCH'
        });
        dispatch({
            type: 'SEARCH_START'
        });
        const debounceTimer = setTimeout(paginatedResources ? performPaginatedSearch : performLocalSearch, CHAT_RESOURCE_PICKER_SEARCH_DEBOUNCE_MS);
        return ()=>clearTimeout(debounceTimer);
    }, [
        isOpen,
        searchQuery,
        paginatedResources,
        performPaginatedSearch,
        performLocalSearch,
        dispatch
    ]);
    const hasMore = useMemo(()=>{
        if (!paginatedResources) return false;
        if (searchQuery) return !searchDone;
        if (drillDown) return !drillDown.done;
        return false;
    }, [
        paginatedResources,
        searchQuery,
        searchDone,
        drillDown
    ]);
    const contextValue = useMemo(()=>({
            isOpen,
            isOpenRef,
            anchorPosition,
            query,
            displayedItems,
            drillDown,
            loading,
            loadingMore,
            searchInProgress,
            hasMore,
            error,
            previousDisplayCount,
            open,
            close,
            handleMentionEnd,
            setQuery,
            handleItemClick,
            goBackOrClose,
            retryLoad,
            loadMore
        }), [
        isOpen,
        anchorPosition,
        query,
        displayedItems,
        drillDown,
        loading,
        loadingMore,
        searchInProgress,
        hasMore,
        error,
        previousDisplayCount,
        open,
        close,
        handleMentionEnd,
        setQuery,
        handleItemClick,
        goBackOrClose,
        retryLoad,
        loadMore
    ]);
    return /*#__PURE__*/ jsx(AutopilotChatResourcePickerContext.Provider, {
        value: contextValue,
        children: children
    });
}
function useAutopilotChatResourcePicker() {
    const context = useContext(AutopilotChatResourcePickerContext);
    if (!context) throw new Error('useAutopilotChatResourcePicker must be used within an AutopilotChatResourcePickerProvider');
    return context;
}
export { AutopilotChatResourcePickerProvider, isResourceSelector, useAutopilotChatResourcePicker };
