import { Get, UniversalHandler, UniversalFn, UniversalMiddleware, RuntimeAdapter } from '@universal-middleware/core';
import { DataResult, MiddlewareFn } from '@webroute/middleware';
import { RequestCtx } from '@webroute/route';

type WebrouteHandler<InContext extends object, TResult extends DataResult | void = void, TParams = unknown, TQuery = unknown, TBody = unknown, THeaders = unknown, TState extends InContext = InContext, TProviders = unknown> = UniversalFn<UniversalHandler<Extract<InContext, Universal.Context>>, MiddlewareFn<TResult, [ctx: RequestCtx<TParams, TQuery, TBody, THeaders, TState, TProviders>]>>;
type WebrouteMiddleware<InContext extends object, OutContext extends object, TResult extends DataResult | void = void, TParams = unknown, TQuery = unknown, TBody = unknown, THeaders = unknown, TState extends InContext = InContext, TProviders = unknown> = UniversalFn<UniversalMiddleware<Extract<InContext, Universal.Context>, Extract<OutContext, Universal.Context>>, MiddlewareFn<TResult, [ctx: RequestCtx<TParams, TQuery, TBody, THeaders, TState, TProviders>]>>;
type ExtractVoid<T, U> = T extends U ? T : void;
type MiddlewareFactoryReturnType<T extends (...args: any) => any> = ReturnType<T> extends UniversalMiddleware<any, any> ? Awaited<ReturnType<ReturnType<T>>> : never;
type MiddlewareFactoryDataResult<T extends (...args: any) => any> = ExtractVoid<MiddlewareFactoryReturnType<T>, DataResult>;
/**
 * Creates a request handler to be passed to app.all() or any other route function
 */
declare function createHandler<T extends unknown[], InContext extends Universal.Context>(handlerFactory: Get<T, UniversalHandler<InContext>>): Get<T, WebrouteHandler<InContext>>;
/**
 * Creates a middleware to be passed to app.use() or any route function
 */
declare function createMiddleware<T extends unknown[], InContext extends Universal.Context, OutContext extends Universal.Context>(middlewareFactory: Get<T, UniversalMiddleware<InContext, OutContext>>): Get<T, WebrouteMiddleware<InContext, OutContext, MiddlewareFactoryDataResult<typeof middlewareFactory>>>;
declare function getContext<Context extends Universal.Context = Universal.Context>(ctx: RequestCtx<unknown, unknown, unknown, unknown, Context>): Context;
declare function getRuntime(ctx: RequestCtx | undefined): Promise<RuntimeAdapter>;

export { type MiddlewareFactoryDataResult, type WebrouteHandler, type WebrouteMiddleware, createHandler, createMiddleware, getContext, getRuntime };
