import { useIntersectionObserver } from "@vertesia/ui/core";
import { useEffect, useRef, useState } from "react";
/**
 * A hook that provides paginated search functionality with infinite scrolling support.
 */
export function useScrollableSearch(opts, dependencies = []) {
    const pageSize = opts.pageSize || 50;
    const [page, setPage] = useState(null);
    const [lastPayload, setLastPayload] = useState(opts.payload);
    const [error, setError] = useState(null);
    const [results, setResults] = useState([]);
    const [nextPage, setNextPage] = useState(null);
    const [isSearching, setIsSearching] = useState(false);
    // Track current request to prevent stale results
    const requestIdRef = useRef(0);
    const search = (payload) => {
        setPage(null);
        setResults([]); // Clear old results immediately
        setNextPage(null);
        setLastPayload(payload);
    };
    const searchMore = () => {
        if (nextPage !== null) {
            setPage(nextPage);
        }
    };
    useEffect(() => {
        // Increment request ID to mark previous requests as stale
        requestIdRef.current += 1;
        const currentRequestId = requestIdRef.current;
        setIsSearching(true);
        opts.search(lastPayload, page, pageSize).then(r => {
            // Only update state if this is still the current request
            if (currentRequestId !== requestIdRef.current) {
                return; // Stale request, ignore results
            }
            // If page is null, it's a new search - replace results
            // Otherwise, it's loading more - append results
            if (page === null) {
                setResults(r.result);
            }
            else {
                setResults(prev => [...prev, ...r.result]);
            }
            setNextPage(r.nextPage);
            setError(null);
        }).catch(error => {
            // Only update error if this is still the current request
            if (currentRequestId !== requestIdRef.current) {
                return; // Stale request, ignore error
            }
            setError(error);
        }).finally(() => {
            // Only update isSearching if this is still the current request
            if (currentRequestId === requestIdRef.current) {
                setIsSearching(false);
            }
        });
    }, [...dependencies, lastPayload, page]);
    // Intersection observer for infinite scrolling
    useIntersectionObserver(opts.nextPageTrigger, () => {
        if (!isSearching && nextPage) {
            searchMore();
        }
    }, { threshold: 0.1, deps: [nextPage, isSearching] });
    return {
        search,
        refresh: () => search(lastPayload),
        searchMore,
        result: results,
        page,
        hasMore: nextPage !== null,
        error,
        isSearching,
    };
}
export function useDefaultScrollableSearch(opts, dependencies = []) {
    const actualOpts = {
        ...opts,
        async search(payload, page, pageSize) {
            const currentPage = page ?? 0;
            const offset = currentPage * pageSize;
            const result = await opts.search(payload, offset, pageSize);
            return {
                result,
                nextPage: result.length === 0 ? null : currentPage + 1
            };
        }
    };
    return useScrollableSearch(actualOpts, dependencies);
}
//# sourceMappingURL=useScrollableSearch.js.map