import { OperationObject } from '@omer-x/openapi-types/operation';
import { ExampleObject } from '@omer-x/openapi-types/example';
import { ZodType, ZodTypeDef, ZodIssue } from 'zod';

declare const customErrorTypes: ("PARSE_FORM_DATA" | "PARSE_REQUEST_BODY" | "PARSE_SEARCH_PARAMS" | "PARSE_PATH_PARAMS" | "UNNECESSARY_PATH_PARAMS")[];

type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";

type RouteHandlerContext<PathParams> = {
    params: Promise<PathParams>;
};
type RouteMethodHandler<PathParamsInput, Req, Res> = ((request: Req, context: RouteHandlerContext<PathParamsInput>) => Promise<Res>) & {
    apiData?: OperationObject;
};
type RouteHandler<HM extends HttpMethod, PathParamsInput, Req, Res> = Record<HM, RouteMethodHandler<PathParamsInput, Req, Res>>;

type ResponseDefinition<O, I = O> = {
    description: string;
    isArray?: boolean;
    content?: ZodType<O, ZodTypeDef, I> | string;
    example?: NoInfer<O>;
    examples?: Record<string, ExampleObject<NoInfer<O>>>;
};
type ResponseCollection<T extends Record<string, unknown>> = {
    [K in keyof T]: ResponseDefinition<T[K]>;
};

type ActionSource<PathParams, QueryParams, RequestBody> = {
    pathParams: PathParams;
    queryParams: QueryParams;
    body: RequestBody;
};
type RouteWithoutBody = {
    method: Extract<HttpMethod, "GET" | "DELETE" | "HEAD">;
    requestBody?: never;
    requestBodyExample?: never;
    requestBodyExamples?: never;
    hasFormData?: never;
};
type RouteWithBody<I, O> = {
    method: Exclude<HttpMethod, "GET" | "DELETE" | "HEAD">;
    requestBody?: ZodType<O, ZodTypeDef, I> | string;
    requestBodyExample?: NoInfer<O>;
    requestBodyExamples?: Record<string, ExampleObject<NoInfer<O>>>;
    hasFormData?: boolean;
};
type RouteOptions<Method, PathParamsInput, PathParamsOutput, QueryParamsInput, QueryParamsOutput, RequestBodyInput, RequestBodyOutput, Req extends Request, Res extends Response, ResponseDefinitions extends Record<string, unknown>> = {
    operationId: string;
    method: Method;
    summary: string;
    description: string;
    tags: string[];
    pathParams?: ZodType<PathParamsOutput, ZodTypeDef, PathParamsInput>;
    queryParams?: ZodType<QueryParamsOutput, ZodTypeDef, QueryParamsInput>;
    action: (source: ActionSource<PathParamsOutput, QueryParamsOutput, RequestBodyOutput>, request: Req) => Res | Promise<Res>;
    responses: ResponseCollection<ResponseDefinitions>;
    handleErrors?: (errorType: typeof customErrorTypes[number] | "UNKNOWN_ERROR", issues?: ZodIssue[]) => Res;
    middleware?: (hander: RouteMethodHandler<PathParamsInput, Req, Res>) => RouteMethodHandler<PathParamsInput, Req, Res>;
    security?: OperationObject["security"];
} & (RouteWithBody<RequestBodyInput, RequestBodyOutput> | RouteWithoutBody);
declare function defineRoute<M extends HttpMethod, PPI, PPO, QPI, QPO, RBI, RBO, MwReq extends Request, MwRes extends Response, ResDef extends Record<string, unknown>>(input: RouteOptions<M, PPI, PPO, QPI, QPO, RBI, RBO, MwReq, MwRes, ResDef>): RouteHandler<M, PPI, MwReq, MwRes>;

export { defineRoute as default, defineRoute };
