import { IMiddleware, HttpContext, IRequest, IResponse } from '@h3ravel/shared';
export { HttpContext } from '@h3ravel/shared';
import { H3Event, EventHandlerRequest } from 'h3';
import { DotNestedKeys, DotNestedValue } from '@h3ravel/support';
import { TypedHeaders, ResponseHeaderMap } from 'fetchdts';
import { Application, ServiceProvider } from '@h3ravel/core';

declare abstract class Middleware implements IMiddleware {
    abstract handle(context: HttpContext, next: () => Promise<unknown>): Promise<unknown>;
}

declare class Request implements IRequest {
    /**
     * The current app instance
     */
    app: Application;
    /**
     * Gets route parameters.
     * @returns An object containing route parameters.
     */
    readonly params: NonNullable<H3Event["context"]["params"]>;
    /**
     * Gets query parameters.
     * @returns An object containing query parameters.
     */
    readonly query: Record<string, string>;
    /**
     * Gets the request headers.
     * @returns An object containing request headers.
     */
    readonly headers: TypedHeaders<Record<keyof ResponseHeaderMap, string>>;
    /**
     * The current H3 H3Event instance
     */
    private readonly event;
    constructor(event: H3Event, 
    /**
     * The current app instance
     */
    app: Application);
    /**
     * Get all input data (query + body).
     */
    all<T = Record<string, unknown>>(): Promise<T>;
    /**
     * Get a single input field from query or body.
     */
    input<T = unknown>(key: string, defaultValue?: T): Promise<T>;
    /**
     * Get the base event
     */
    getEvent(): H3Event;
    getEvent<K extends DotNestedKeys<H3Event>>(key: K): DotNestedValue<H3Event, K>;
}

declare class Response implements IResponse {
    /**
     * The current app instance
     */
    app: Application;
    /**
     * The current H3 H3Event instance
     */
    private readonly event;
    private statusCode;
    private headers;
    constructor(event: H3Event, 
    /**
     * The current app instance
     */
    app: Application);
    /**
     * Set HTTP status code.
     */
    setStatusCode(code: number): this;
    /**
     * Set a header.
     */
    setHeader(name: string, value: string): this;
    html(content: string): string;
    /**
     * Send a JSON response.
     */
    json<T = unknown>(data: T): T;
    /**
     * Send plain text.
     */
    text(data: string): string;
    /**
     * Redirect to another URL.
     */
    redirect(url: string, status?: number): string;
    /**
     * Apply headers before sending response.
     */
    private applyHeaders;
    /**
     * Get the base event
     */
    getEvent(): H3Event;
    getEvent<K extends DotNestedKeys<H3Event>>(key: K): DotNestedValue<H3Event, K>;
}

declare class LogRequests extends Middleware {
    handle({ request }: HttpContext, next: () => Promise<unknown>): Promise<unknown>;
}

/**
 * Sets up HTTP kernel and request lifecycle.
 *
 * Register Request, Response, and Middleware classes.
 * Configure global middleware stack.
 * Boot HTTP kernel.
 *
 * Auto-Registered
 */
declare class HttpServiceProvider extends ServiceProvider {
    static priority: number;
    register(): void;
}

interface Resource {
    [key: string]: any;
    pagination?: {
        from?: number | undefined;
        to?: number | undefined;
        perPage?: number | undefined;
        total?: number | undefined;
    } | undefined;
}
type BodyResource = Resource & {
    data: Omit<Resource, 'pagination'>;
    meta?: {
        pagination?: Resource['pagination'];
    } | undefined;
};
/**
 * Class to render API resource
 */
declare class JsonResource<R extends Resource = any> {
    #private;
    protected event: H3Event;
    /**
     * The request instance
     */
    request: H3Event<EventHandlerRequest>['req'];
    /**
     * The response instance
     */
    response: H3Event['res'];
    /**
     * The data to send to the client
     */
    resource: R;
    /**
     * The final response data object
     */
    body: BodyResource;
    /**
     * Flag to track if response should be sent automatically
     */
    private shouldSend;
    /**
     * Flag to track if response has been sent
     */
    private responseSent;
    /**
     * Declare that this includes R's properties
     */
    [key: string]: any;
    /**
     * @param req The request instance
     * @param res The response instance
     * @param rsc The data to send to the client
     */
    constructor(event: H3Event, rsc: R);
    /**
     * Return the data in the expected format
     *
     * @returns
     */
    data(): Resource;
    /**
     * Build the response object
     * @returns this
     */
    json(): this;
    /**
     * Add context data to the response object
     * @param data Context data
     * @returns this
     */
    additional<X extends {
        [key: string]: any;
    }>(data: X): this;
    /**
     * Send the output to the client
     * @returns this
     */
    send(): this;
    /**
     * Set the status code for this response
     * @param code Status code
     * @returns this
     */
    status(code: number): this;
    /**
     * Check if send should be triggered automatically
     */
    private checkSend;
}

declare function ApiResource(instance: JsonResource): JsonResource<any>;

export { ApiResource, HttpServiceProvider, JsonResource, LogRequests, Middleware, Request, type Resource, Response };
