import { useCallback, useRef } from "react";

/**
 * Wraps a function to single-flight invocations, using the latest args.
 *
 * Copied from @convex-dev/presence/dist/react/useSingleFlight.js
 */
export default function useSingleFlight(fn) {
    const flightStatus = useRef({
        inFlight: false,
        upNext: null,
    });
    return useCallback((...args) => {
        if (flightStatus.current.inFlight) {
            return new Promise((resolve, reject) => {
                flightStatus.current.upNext = { fn, resolve, reject, args };
            });
        }
        flightStatus.current.inFlight = true;
        const firstReq = fn(...args);
        void (async () => {
            try {
                await firstReq;
            }
            finally {
                // If it failed, we naively just move on to the next request.
            }
            while (flightStatus.current.upNext) {
                const cur = flightStatus.current.upNext;
                flightStatus.current.upNext = null;
                await cur
                    .fn(...cur.args)
                    .then(cur.resolve)
                    .catch(cur.reject);
            }
            flightStatus.current.inFlight = false;
        })();
        return firstReq;
    }, [fn]);
}
