import { useEffect, useState, type Dispatch, type StateUpdater } from "preact/hooks";
import { useUpdate } from "./useUpdate";

type Query<T, Args extends any[]> = (...args: Args) => (Promise<T> | T);
type Return<T> = [T | undefined, Dispatch<StateUpdater<T | undefined>>, () => void];

export const useAsyncState = <T, Args extends any[]>(query: Query<T, Args>, ...args: Args): Return<T> => {
    const [data, setData] = useState<T>();
    const [update, request] = useUpdate();

    useEffect(() => void Promise.resolve(query?.(...args))
        ?.then(d => setData(d))
        .catch(() => setData(undefined)), [query, ...args, update]);

    return [data, setData, request];
};

export const useQuery = <T, Args extends any[]>(query: Query<T, Args>, ...args: Args): T | undefined => (
    useAsyncState(query, ...args)[0]
);
