import { AnyApiReferenceConfiguration } from "./openapi.scalar.mjs";
import { Box, Constructor } from "getbox";
import { EventHandlerResponse, H3, H3Event, H3Plugin, RouteOptions } from "h3";
import { ZodType, output } from "zod";
import { CreateDocumentOptions, CreateDocumentOptions as CreateDocumentOptions$1, ZodOpenApiMediaTypeObject, ZodOpenApiMetadata, ZodOpenApiMetadata as ZodOpenApiMetadata$1, ZodOpenApiObject, ZodOpenApiObject as ZodOpenApiObject$1, ZodOpenApiOperationObject, ZodOpenApiPathsObject, ZodOpenApiRequestBodyObject, ZodOpenApiResponseObject, createDocument } from "zod-openapi";

//#region src/openapi.d.ts
/** Infer the Zod output type from `requestParams.path`. */
type InferParams<T> = T extends {
  requestParams: {
    path: infer S;
  };
} ? output<S> : Record<string, string>;
/** Infer the Zod output type from `requestParams.query`. */
type InferQuery<T> = T extends {
  requestParams: {
    query: infer S;
  };
} ? output<S> : Record<string, string>;
/** Infer the Zod output type from `requestBody.content["application/json"].schema`. */
type InferBody<T> = T extends {
  requestBody: {
    content: {
      "application/json": {
        schema: infer S;
      };
    };
  };
} ? output<S> : unknown;
/** Resolve a response object from `responses` by numeric status code, handling both numeric and string keys. */
type LookupResponseByStatus<R$1, Status extends number> = Status extends keyof R$1 ? R$1[Status] : `${Status}` extends keyof R$1 ? R$1[`${Status}`] : never;
/** Infer the Zod output type from `responses[status].content["application/json"].schema`. */
type InferResponse<T, Status extends number> = T extends {
  responses: infer R;
} ? LookupResponseByStatus<R, Status> extends {
  content: {
    "application/json": {
      schema: infer S;
    };
  };
} ? output<S> : unknown : unknown;
/** Infer the Zod output type from `responses[status].headers`. Falls back to `Record<string, string>` when no headers schema is defined. */
type InferResponseHeaders<T, Status extends number> = T extends {
  responses: infer R;
} ? LookupResponseByStatus<R, Status> extends {
  headers: infer H;
} ? output<H> : Record<string, string> : Record<string, string>;
/** Extract the raw Zod schema from `requestBody.content["application/json"].schema`, or `undefined` if absent. */
type ExtractBodySchema<T> = T extends {
  requestBody: {
    content: {
      "application/json": {
        schema: infer S;
      };
    };
  };
} ? S extends {
  _zod: any;
} ? S : undefined : undefined;
/** Extract the raw Zod schema from `requestParams.path`, or `undefined` if absent. */
type ExtractParamsSchema<T> = T extends {
  requestParams: {
    path: infer S;
  };
} ? S extends {
  _zod: any;
} ? S : undefined : undefined;
/** Extract the raw Zod schema from `requestParams.query`, or `undefined` if absent. */
type ExtractQuerySchema<T> = T extends {
  requestParams: {
    query: infer S;
  };
} ? S extends {
  _zod: any;
} ? S : undefined : undefined;
/** Extract the raw Zod schema from `requestParams.header`, or `undefined` if absent. */
type ExtractHeadersSchema<T> = T extends {
  requestParams: {
    header: infer S;
  };
} ? S extends {
  _zod: any;
} ? S : undefined : undefined;
/** Extract the raw Zod schema from `requestParams.cookie`, or `undefined` if absent. */
type ExtractCookiesSchema<T> = T extends {
  requestParams: {
    cookie: infer S;
  };
} ? S extends {
  _zod: any;
} ? S : undefined : undefined;
/** Extract numeric status codes from `responses`, normalizing string keys like `"200"` to `200`. */
type ResponseStatusKeys<T> = T extends {
  responses: infer R;
} ? keyof R extends infer K ? K extends number ? K : K extends `${infer N extends number}` ? N : never : never : never;
/**
 * Typed context returned from operation registration.
 *
 * Provides access to raw Zod schemas for manual validation and
 * convenience methods for extracting validated request data.
 *
 * - `schemas` — raw Zod schemas for use with H3 validation utilities (e.g. `getValidatedRouterParams`)
 *   - `schemas.params` — path parameters schema
 *   - `schemas.query` — query parameters schema
 *   - `schemas.headers` — request headers schema
 *   - `schemas.cookies` — cookies schema
 *   - `schemas.body` — request body schema
 * - `params()` — validates and returns route parameters
 * - `query()` — validates and returns query string parameters
 * - `body()` — validates and returns the JSON request body
 * - `reply()` — sets the response status, optional headers, and returns typed response data
 * - `validReply()` — validates the response data and headers, then sets the response status and returns typed response data
 */
type RouterContext<T extends ZodOpenApiOperationObject = ZodOpenApiOperationObject> = {
  schemas: {
    params: ExtractParamsSchema<T>;
    query: ExtractQuerySchema<T>;
    headers: ExtractHeadersSchema<T>;
    cookies: ExtractCookiesSchema<T>;
    body: ExtractBodySchema<T>;
  };
  /**
   * Validates and returns route parameters.
   * Uses `getValidatedRouterParams()` from H3 when schema is present,
   * otherwise uses `getRouterParams()`.
   */
  params(event: H3Event): Promise<InferParams<T>>;
  /**
   * Validates and returns query string parameters.
   * Uses `getValidatedQuery()` from H3 when schema is present,
   * otherwise uses `getQuery()`.
   */
  query(event: H3Event): Promise<InferQuery<T>>;
  /**
   * Validates and returns the request body.
   * Uses `readValidatedBody()` from H3 when schema is present,
   * otherwise uses `readBody()`.
   * Reads request body and tries to parse using JSON.parse or URLSearchParams.
   */
  body(event: H3Event): Promise<InferBody<T>>;
  /**
   * Sets the response status and optional headers, then returns the typed response data.
   * Does not perform runtime validation on the response data.
   */
  reply<S$1 extends ResponseStatusKeys<T>>(event: H3Event, status: S$1, data: InferResponse<T, S$1>, headers?: InferResponseHeaders<T, S$1>): InferResponse<T, S$1>;
  /**
   * Validates the response data, sets the response status and optional headers, then returns the typed response data.
   * Throws an error if validation fails.
   */
  validReply<S$1 extends ResponseStatusKeys<T>>(event: H3Event, status: S$1, data: InferResponse<T, S$1>, headers?: InferResponseHeaders<T, S$1>): InferResponse<T, S$1>;
};
type Controller = Constructor<H3>;
type Route<T extends ZodOpenApiOperationObject = ZodOpenApiOperationObject> = Constructor<RoutePlugin<T>>;
type RoutePlugin<_T extends ZodOpenApiOperationObject> = (paths: OpenApiPaths) => H3Plugin;
declare const HTTP_METHODS: readonly ["get", "post", "put", "delete", "patch"];
type HttpMethod = (typeof HTTP_METHODS)[number];
/**
 * Collects OpenAPI operation definitions for document generation.
 *
 * Register operations by HTTP method and path. The accumulated `paths`
 * object can be passed to `createDocument()` to generate the OpenAPI spec.
 *
 * Each registration returns a typed {@link RouterContext} for use in route handlers.
 *
 * @example
 * ```ts
 * const paths = new OpenApiPaths();
 *
 * const getPost = paths.get("/posts/{id}", { ... });
 *
 * // Generate OpenAPI document
 * createDocument({ openapi: "3.1.0", info: { ... }, paths: paths.paths });
 * ```
 */
declare class OpenApiPaths {
  /** Accumulated OpenAPI paths object. */
  paths: ZodOpenApiPathsObject;
  /** Register an operation for the GET method. */
  get<T extends ZodOpenApiOperationObject>(path: string, operation: T): RouterContext<T>;
  /** Register an operation for the POST method. */
  post<T extends ZodOpenApiOperationObject>(path: string, operation: T): RouterContext<T>;
  /** Register an operation for the PUT method. */
  put<T extends ZodOpenApiOperationObject>(path: string, operation: T): RouterContext<T>;
  /** Register an operation for the DELETE method. */
  delete<T extends ZodOpenApiOperationObject>(path: string, operation: T): RouterContext<T>;
  /** Register an operation for the PATCH method. */
  patch<T extends ZodOpenApiOperationObject>(path: string, operation: T): RouterContext<T>;
  /** Register an operation for all standard HTTP methods (get, post, put, delete, patch). */
  all<T extends ZodOpenApiOperationObject>(path: string, operation: T): RouterContext<T>;
  /** Register an operation for specific HTTP methods. */
  on<T extends ZodOpenApiOperationObject>(methods: readonly HttpMethod[], path: string, operation: T): RouterContext<T>;
  /**
   * Mount all paths from `sub` with a base prefix.
   *
   * Existing entries on the same path and method are not overwritten.
   *
   * @example
   * ```ts
   * const subPaths = new OpenApiPaths();
   *
   * subPaths.get("/", { operationId: "getUsers", responses: {} });
   *
   * const basePaths = new OpenApiPaths();
   * basePaths.mount("/users", subPaths);
   * ```
   */
  mount(base: string, sub: OpenApiPaths): void;
}
/**
 * Combines OpenAPI path registration with H3 route registration.
 *
 * Each method registers the operation in {@link OpenApiPaths} (converting the
 * H3 path syntax to OpenAPI format) and simultaneously registers the route
 * handler on the H3 app. The handler receives the typed {@link RouterContext}.
 *
 * @example
 * ```ts
 * const router = useRouter(app);
 *
 * router.get("/posts/:id", {
 *   operationId: "getPost",
 *   requestBody: jsonRequest(inputSchema),
 *   responses: {
 *     200: jsonResponse(outputSchema, { description: "Success" }),
 *   },
 * }, async (event, ctx) => {
 *   const body = await ctx.body(event);
 *   return ctx.reply(event, 200, { message: "ok" });
 * });
 * ```
 */
declare class OpenApiRouter {
  protected _app: H3;
  protected _paths: OpenApiPaths;
  private static key;
  /**
   * Returns the existing router for `app`, or creates and attaches a new one.
   * Multiple calls on the same app return the same instance.
   */
  static from(app: H3): OpenApiRouter;
  private constructor();
  /** Register a route and operation for the GET method. */
  get<T extends ZodOpenApiOperationObject>(path: string, operation: T, handler: (event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse, opts?: RouteOptions): this;
  /** Register a route and operation for the POST method. */
  post<T extends ZodOpenApiOperationObject>(path: string, operation: T, handler: (event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse, opts?: RouteOptions): this;
  /** Register a route and operation for the PUT method. */
  put<T extends ZodOpenApiOperationObject>(path: string, operation: T, handler: (event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse, opts?: RouteOptions): this;
  /** Register a route and operation for the DELETE method. */
  delete<T extends ZodOpenApiOperationObject>(path: string, operation: T, handler: (event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse, opts?: RouteOptions): this;
  /** Register a route and operation for the PATCH method. */
  patch<T extends ZodOpenApiOperationObject>(path: string, operation: T, handler: (event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse, opts?: RouteOptions): this;
  /** Register a route and operation for all standard HTTP methods. */
  all<T extends ZodOpenApiOperationObject>(path: string, operation: T, handler: (event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse, opts?: RouteOptions): this;
  /** Register a route and operation for specific HTTP methods. */
  on<T extends ZodOpenApiOperationObject>(methods: readonly HttpMethod[], path: string, operation: T, handler: (event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse, opts?: RouteOptions): this;
  /**
   * Registers routes and operations for standalone {@link RoutePlugin} definitions.
   */
  route(...routes: RoutePlugin<any>[]): this;
  /**
   * Mounts a sub-app and adds all paths with a base prefix.
   *
   * When mounting a sub-app, all routes will be added with base prefix and global middleware will be added as one prefixed middleware.
   *
   * **Note:** Sub-app options and global hooks are not inherited when mounted consider setting them in the main app directly.
   */
  mount(base: string, sub: H3): this;
  /**
   * Mounts sub-apps resolved from a {@link Box} under their respective base prefixes.
   *
   * When mounting a sub-app, all routes will be added with base prefix and global middleware will be added as one prefixed middleware.
   *
   * **Note:** Sub-app options and global hooks are not inherited when mounted consider setting them in the main app directly.
   */
  mount(box: Box, routes: Record<string, Controller>): this;
  /** Returns the accumulated OpenAPI paths object. */
  paths(): ZodOpenApiPathsObject;
  /**
   * Mounts a handler at `path` that serves the OpenAPI document.
   * Also mounts a Scalar API reference UI at `{path}/reference` by default.
   * Pass `reference: false` to disable, or provide options to configure it.
   */
  document(path: string, options: RouterDocumentOptions): this;
}
/** API document options. */
interface RouterDocumentOptions extends Omit<ZodOpenApiObject$1, "paths"> {
  options?: CreateDocumentOptions$1;
  reference?: false | RouterReferenceOptions;
}
/** API reference options. */
interface RouterReferenceOptions {
  /** Path to mount the Scalar UI. Defaults to `{documentPath}/reference`. */
  path?: string;
  /** Scalar configuration options (excluding `url`, which is set automatically). */
  configuration?: Omit<AnyApiReferenceConfiguration, "url">;
  /** Page title. Defaults to "Scalar API Reference". */
  pageTitle?: string;
  /** CDN URL for the standalone bundle. Defaults to jsDelivr. */
  cdn?: string;
  /** Custom CSS theme for the Scalar UI. */
  customTheme?: string;
}
/**
 * Creates an {@link OpenApiRouter} that combines H3 route registration with OpenAPI path collection.
 *
 * Multiple calls on the same app return the same instance.
 *
 * @param app - H3 application instance.
 * @returns An {@link OpenApiRouter} instance.
 *
 * @example
 * ```ts
 * const router = useRouter(app);
 *
 * router.get("/posts/:id", {
 *   operationId: "getPost",
 *   responses: { 200: jsonResponse(postSchema, { description: "Success" }) },
 * }, async (event, ctx) => {
 *   const { id } = await ctx.params(event);
 *   return ctx.reply(event, 200, { id });
 * });
 * ```
 */
declare function useRouter(app: H3): OpenApiRouter;
/**
 * Creates a RoutePlugin constructor.
 *
 * `setup` is called once with the Box to resolve dependencies. Return a handler function
 * directly, or an object with a `handler` and other route options (e.g. `meta`, `middleware`).
 *
 * @param options.setup - Returns the handler or `{ handler, ...RouteOptions }`.
 * @returns A Constructor that produces a {@link RoutePlugin}. Not cached by Box.
 *
 * @example
 * ```ts
 * const getPost = route({
 *   method: "get",
 *   path: "/posts/:id",
 *   operation: {
 *     operationId: "getPost",
 *     responses: { 200: jsonResponse(postSchema, { description: "Success" }) },
 *   },
 *   setup(box) {
 *     const db = box.get(Database);
 *     return async (event, ctx) => {
 *       const { id } = await ctx.params(event);
 *       return ctx.reply(event, 200, await db.getPost(id));
 *     };
 *   },
 * });
 *
 * const getPostRoute = box.get(getPost);
 *
 * const router = useRouter(app);
 * router.route(getPostRoute);
 * ```
 */
declare function route<T extends ZodOpenApiOperationObject>(options: {
  method: HttpMethod | readonly HttpMethod[];
  path: string;
  operation: T;
  setup: (box: Box) => ((event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse) | PrettyMerge<RouteOptions, {
    handler: (event: H3Event, ctx: RouterContext<T>) => EventHandlerResponse;
  }>;
}): Route<T>;
type Pretty<T> = { [K in keyof T]: T[K] } & {};
type Merge<T, U> = Omit<T, keyof U> & U;
type PrettyOmit<T, U extends keyof any> = Pretty<Omit<T, U>>;
type PrettyMerge<T, U> = Pretty<Merge<T, U>>;
/** Builder for OpenAPI metadata passed to `.meta()` on Zod schemas. */
declare const metadata: (meta: ZodOpenApiMetadata$1) => ZodOpenApiMetadata$1;
/**
 * Build a typed `requestBody` object with `application/json` content.
 *
 * Additional media type options (e.g. `example`) can be passed via `opts.content`.
 *
 * @example
 * ```ts
 * jsonRequest(inputSchema)
 * jsonRequest(inputSchema, { description: "Create a post", content: { example: { title: "Hello" } } })
 * ```
 */
declare function jsonRequest<S$1 extends {
  _zod: any;
}, O extends PrettyMerge<ZodOpenApiRequestBodyObject, {
  content?: PrettyOmit<ZodOpenApiMediaTypeObject, "schema">;
}>>(schema: S$1, opts?: O): PrettyMerge<ZodOpenApiRequestBodyObject, {
  content: {
    "application/json": PrettyMerge<{
      schema: S$1;
    }, O["content"]>;
  };
}>;
/**
 * Build a typed response object with `application/json` content.
 *
 * Additional media type options (e.g. `example`) can be passed via `opts.content`.
 *
 * @example
 * ```ts
 * jsonResponse(outputSchema, { description: "Success" })
 * jsonResponse(outputSchema, {
 *   description: "Success",
 *   headers: z.object({ "x-request-id": z.string() }),
 * })
 * ```
 */
declare function jsonResponse<S$1 extends {
  _zod: any;
}, H$1 extends {
  _zod: any;
} | undefined, O extends PrettyMerge<ZodOpenApiResponseObject, {
  content?: PrettyOmit<ZodOpenApiMediaTypeObject, "schema">;
  headers?: H$1;
}>>(schema: S$1, opts: O): PrettyMerge<ZodOpenApiResponseObject, {
  content: {
    "application/json": PrettyMerge<{
      schema: S$1;
    }, O["content"]>;
  };
  headers: O["headers"];
}>;
/**
 * Creates a typed schemas object for grouping route schemas together.
 *
 * The common keys are `params`, `query`, `headers`, `cookies`, `body`, and
 * `response`. Other schema properties can also be added.
 */
declare function schemas<T extends {
  params?: ZodType;
  query?: ZodType;
  headers?: ZodType;
  cookies?: ZodType;
  body?: ZodType;
  response?: ZodType;
  [k: string]: ZodType | undefined;
}>(s: T): T;
//#endregion
export { Controller, type CreateDocumentOptions, OpenApiPaths, OpenApiRouter, Route, RoutePlugin, RouterContext, RouterDocumentOptions, RouterReferenceOptions, type ZodOpenApiMetadata, type ZodOpenApiObject, createDocument, jsonRequest, jsonResponse, metadata, route, schemas, useRouter };