import { ResponseType, FetchOptions, MappedResponseType } from 'ofetch';
import { MaybeRefOrGetter, Ref, ComputedRef, WatchSource } from 'vue';

type UseAsyncDataStatus = 'idle' | 'pending' | 'success' | 'error';
interface UseAsyncData {
    <ResT = any, DataT = ResT>(request: () => Promise<ResT>, options?: UseAsyncDataOptions<ResT, DataT>): UseAsyncDataReturns<DataT>;
    create: (options?: UseAsyncDataOptions<any, any>) => UseAsyncData;
}
interface UseAsyncDataOptions<ResT, DataT> {
    /** If make a request during initialization */
    immediate?: boolean;
    /** Same as Vue's `watch`. Refresh when watch source updated */
    watch?: MultiWatchSource | MultiWatchSource[] | false;
    /** Indicate the interval time for polling in millisecond */
    pollingInterval?: MaybeRefOrGetter<number>;
    /** Indicate the debounce delay time in millisecond */
    debounceInterval?: MaybeRefOrGetter<number>;
    /** Indicate the throttle wait time in millisecond */
    throttleInterval?: MaybeRefOrGetter<number>;
    /** Only request if true. Request will be prevented if false. */
    ready?: MaybeRefOrGetter<boolean>;
    /** A function that can be used to alter handler function result after resolving. */
    transform?: (input: ResT) => DataT | PromiseLike<DataT>;
    /** a factory function to set the default value of the data, before the async function resolves */
    default?: () => DataT | null;
}
interface UseAsyncDataReturns<Data> {
    /** The data which the async function returns */
    data: Ref<Data | null>;
    /** A boolean value indicating whether the data is still being fetched */
    pending: Ref<boolean>;
    /** A function used to manually trigger the request */
    refresh: () => Promise<void>;
    /** A function used to manually trigger the request */
    execute: () => Promise<void>;
    /** The error object if the data fetch fails, otherwise `null`. */
    error: Ref<Error | null>;
    /**
     * A string representing the state of the data request.
     * @example
     * 'idle', 'pending', 'success', 'error'
     */
    status: Ref<UseAsyncDataStatus>;
}
interface UseFetch {
    <ResT = any, DataT = ResT, R extends ResponseType = 'json'>(_req: UseFetchParams, options?: UseFetchOptions<ResT, DataT, R>): UseFetchReturns<R, DataT>;
    create: (options?: UseFetchOptions<any, any>) => UseFetch;
}
type UseFetchParams = MaybeRefOrGetter<string | Request>;
interface UseFetchReactiveOptions {
    method?: MaybeRefOrGetter<FetchOptions['method']>;
    query?: MaybeRefOrGetter<FetchOptions['query']>;
    params?: MaybeRefOrGetter<FetchOptions['params']>;
    body?: MaybeRefOrGetter<FetchOptions['body']>;
    headers?: MaybeRefOrGetter<FetchOptions['headers']>;
    baseURL?: MaybeRefOrGetter<FetchOptions['baseURL']>;
}
type UseFetchOptions<ResT, DataT, R extends ResponseType = ResponseType> = UseAsyncDataOptions<ResT, DataT> & UseFetchReactiveOptions & Omit<FetchOptions<R>, keyof UseFetchReactiveOptions>;
type UseFetchReturns<R extends ResponseType = ResponseType, T = any> = UseAsyncDataReturns<MappedResponseType<R, T>>;
interface UsePagination {
    <ResT = any, DataT = ResT, R extends ResponseType = 'json'>(_req: UseFetchParams, options?: UsePaginationOptions<ResT, DataT, R>): UsePaginationReturns<R, DataT>;
    create: (options?: UsePaginationOptions<any, any>) => UsePagination;
}
interface UsePaginationOptions<ResT, DataT, R extends ResponseType = ResponseType> extends UseFetchOptions<ResT, DataT, R> {
    pageCurrentKey?: string;
    pageSizeKey?: string;
    defaultPageSize?: number;
    totalKey?: string;
    pageTotalKey?: string;
}
interface UsePaginationReturns<R extends ResponseType = ResponseType, T = any> extends UseFetchReturns<R, T> {
    /** A number to indicate which page you are on */
    pageCurrent: Ref<number>;
    /** A number to indicate the size of a page */
    pageSize: Ref<number>;
    /** Readonly number to indicate how many items of the data */
    total: ComputedRef<number>;
    /** Readonly number to indicate how many pages here */
    pageTotal: ComputedRef<number>;
}
type MultiWatchSource = WatchSource<unknown> | object;

declare const useAsyncData: UseAsyncData;
declare const useFetch: UseFetch;
declare const usePagination: UsePagination;

export { type MultiWatchSource, type UseAsyncData, type UseAsyncDataOptions, type UseAsyncDataReturns, type UseAsyncDataStatus, type UseFetch, type UseFetchOptions, type UseFetchParams, type UseFetchReactiveOptions, type UseFetchReturns, type UsePagination, type UsePaginationOptions, type UsePaginationReturns, useAsyncData, useFetch, usePagination };
