import { router } from '@inertiajs/react';
import { useCallback, useEffect, useRef, useState } from 'react';

type PaginatedData<T> = {
    data: T[];
    current_page: number;
    last_page: number;
    per_page: number;
    total: number;
};

type UseInfiniteScrollOptions<T> = {
    initialData: PaginatedData<T>;
    fetchUrl: string;
    perPage?: number;
};

export function useInfiniteScroll<T>({
    initialData,
    fetchUrl,
    perPage = 20,
}: UseInfiniteScrollOptions<T>) {
    const [items, setItems] = useState<T[]>(initialData.data);
    const [currentPage, setCurrentPage] = useState(initialData.current_page);
    const [lastPage, setLastPage] = useState(initialData.last_page);
    const [loading, setLoading] = useState(false);
    const sentinelRef = useRef<HTMLDivElement | null>(null);

    const loadMore = useCallback(() => {
        if (loading || currentPage >= lastPage) {
return;
}

        setLoading(true);

        const url = new URL(fetchUrl, window.location.origin);
        url.searchParams.set('page', String(currentPage + 1));
        url.searchParams.set('per_page', String(perPage));

        router.get(
            url.pathname + url.search,
            {},
            {
                preserveState: true,
                replace: true,
                only: ['mutations'],
                 
                onSuccess: (page: any) => {
                    const newMutations = (page.props as Record<string, unknown>)
                        .mutations as PaginatedData<T>;

                    setItems((prev) => [...prev, ...newMutations.data]);
                    setCurrentPage(newMutations.current_page);
                    setLastPage(newMutations.last_page);
                    setLoading(false);
                },
                onError: () => {
                    setLoading(false);
                },
            },
        );
    }, [fetchUrl, currentPage, lastPage, loading, perPage]);

    useEffect(() => {
        const sentinel = sentinelRef.current;

        if (!sentinel) {
return;
}

        const observer = new IntersectionObserver(
            (entries) => {
                if (entries[0].isIntersecting) {
                    loadMore();
                }
            },
            { threshold: 0.1 },
        );

        observer.observe(sentinel);

        return () => observer.disconnect();
    }, [loadMore]);

    const hasNextPage = currentPage < lastPage;

    return {
        items,
        loading,
        hasNextPage,
        sentinelRef,
    };
}
