import { UseQueryOptions, UseMutationOptions, QueryObserverResult, UseMutationResult } from 'react-query';
export * from 'react-query';
import { AbortSignal } from 'abort-controller';
import { IdTokenClaims, UserinfoResponse } from 'openid-client';

interface ServerAuthAuthenticated {
    isAuthenticated: true;
    credentials: ServerAuthCredentials;
}
interface ServerAuthUnauthenticated {
    error?: unknown;
    isAuthenticated: false;
}
declare type ServerAuth = ServerAuthAuthenticated | ServerAuthUnauthenticated;
interface ServerAuthCredentials {
    audience?: string;
    accessToken: string;
    claims: IdTokenClaims;
    expiresAt: number;
    idToken: string;
    scope: string[];
    user: UserinfoResponse;
}

interface FunctionQueryOptions extends Omit<UseQueryOptions, 'queryFn'> {
}
interface FunctionMutationOptions<TData = unknown, TError = unknown, TVariables = void, TContext = unknown> extends UseMutationOptions<TData, TError, TVariables, TContext> {
}
declare type NonContextFunctionArgs<T extends ServerFunction> = T extends (ctx: ServerFunctionContext, ...args: infer U) => any ? U : never;
declare type FunctionReturnType<T extends ServerFunction> = ReturnType<T> extends PromiseLike<infer U> ? U : ReturnType<T>;
interface ServerFunctionContext {
    auth: ServerAuth;
    signal?: AbortSignal;
}
interface ServerFunction {
    (ctx: ServerFunctionContext, ...args: any[]): any;
}

/**
 * Create a `react-query` `useQuery` hook function suitable for reading data from a
 * Nostalgie Function
 *
 * @param fn A reference to a Nostalgie Function exposed via the Functions Entrypoint
 * @param factoryOptions Default options to apply to all invocations of the actual
 * query. You might use this to set default cache values like `stateTime`.
 *
 * @example
 * ```ts
 * import * as React from 'react';
 * import { createFunctionQuery } from 'nostalgie/functions';
 * import { listBlogPosts } from './functions.ts';
 *
 * const useBlogPosts = createFunctionQuery(listBlogPosts, { staleTime: 30000 });
 *
 * export default function BlogPosts() {
 *   const posts = useBlogPosts([]);
 *
 *   if (posts.isLoading) return <div>Loading...</div>;
 *   if (posts.isError) return <div>{`Error: ${data.error}`</div>
 *
 *   return posts.data.map(post => (
 *     <BlogPost key={post.id} post={post} />
 *   ));
 * }
 * ```
 */
declare function createQueryFunction<T extends ServerFunction>(fn: T, factoryOptions?: FunctionQueryOptions): (args: NonContextFunctionArgs<T>, options?: FunctionQueryOptions | undefined) => QueryObserverResult<FunctionReturnType<T>, unknown>;
declare function useQueryFunction<T extends ServerFunction>(fn: T, args: NonContextFunctionArgs<T>, options?: FunctionQueryOptions): QueryObserverResult<FunctionReturnType<T>, unknown>;
/**
 *
 * @param fn A reference to a Nostalgie Function exposed via the Functions Entrypoint
 * @param factoryOptions Default options to apply to all invocations of the actual
 * mutation. You might use this to set default observer hooks like `onError`.
 *
 * @example
 * ```ts
 * import * as React from 'react';
 * import { createFunctionQuery } from 'nostalgie/functions';
 * import { likeBlogPost } from './functions.ts';
 * import type { BlogPost } from './functions.ts';
 *
 * const useLikePost = createFunctionMutation(likeBlogPost);
 *
 * export default function BlogPost(props: React.PropsWithChildren<{ post: BlogPost }>) {
 *   const likePost = useLikePost();
 *   const onClickLike = (e: React.MouseEvent) => {
 *     e.preventDefault();
 *     likePost.mutate([post.id]);
 *   }
 *
 *   return (
 *     <div>
 *       <h3>{post.title}</h3>
 *       <p>{post.body}</p>
 *       <div className="actions">
 *         <button onClick={onClickLike}>Like</button>
 *         {likePost.isLoading ? '...' : null}
 *         {likePost.isError ? likePost.error.message : null}
 *       </div>
 *     </div>
 *   );
 * }
 * ```
 */
declare function createMutationFunction<T extends ServerFunction>(fn: T, factoryOptions?: FunctionMutationOptions<FunctionReturnType<T>, unknown, NonContextFunctionArgs<T>>): (options?: FunctionMutationOptions<FunctionReturnType<T>, unknown, NonContextFunctionArgs<T>, unknown> | undefined) => void | UseMutationResult<FunctionReturnType<T>, unknown, NonContextFunctionArgs<T>, unknown>;

export { ServerFunction, ServerFunctionContext, createMutationFunction, createQueryFunction, useQueryFunction };
