import { OperationObject } from '@omer-x/openapi-types/operation';
import { ExampleObject } from '@omer-x/openapi-types/example';
import { MediaTypeObject } from '@omer-x/openapi-types/media-type';
import { ZodType, 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 extends Record<string, string>> = {
    params: Promise<PathParams>;
};
type RouteMethodHandler<PathParamsInput extends Record<string, string>, Req, Res> = ((request: Req, context: RouteHandlerContext<PathParamsInput>) => Promise<Res>) & {
    apiData?: OperationObject;
};
type RouteHandler<HM extends HttpMethod, PathParamsInput extends Record<string, string>, Req, Res> = Record<HM, RouteMethodHandler<PathParamsInput, Req, Res>>;

type FixPathParams<T> = {
    [K in keyof T]: string;
};

type Prettify<T> = {
    [K in keyof T]: T[K];
} & {};

type ResponseDefinition<O, I = O> = {
    description: string;
    /**
     * @deprecated Use `.array()` instead
     */
    isArray?: boolean;
    example?: NoInfer<O>;
    examples?: Record<string, ExampleObject<NoInfer<O>>>;
} & ({
    content?: ZodType<O, I> | string;
    customContent?: never;
} | {
    content?: never;
    customContent?: Record<string, MediaTypeObject>;
});
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, 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, PathParamsInput>;
    queryParams?: ZodType<QueryParamsOutput, 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<FixPathParams<PathParamsInput>, Req, Res>) => RouteMethodHandler<FixPathParams<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, Prettify<FixPathParams<PPI>>, MwReq, MwRes>;

export { defineRoute as default, defineRoute };
