import { Context, FunctionRegion, DeployBuildingHandler, DeploySucceededHandler, DeployFailedHandler, DeployDeletedHandler, DeployLockedHandler, DeployUnlockedHandler, FormSubmittedHandler, UserLoginHandler, UserSignupHandler, UserValidateHandler, UserModifiedHandler, UserDeletedHandler, NetlifyGlobal } from '@netlify/types';
export { Context, Deploy, DeployBuildingEvent, DeployBuildingHandler, DeployDeletedEvent, DeployDeletedHandler, DeployFailedEvent, DeployFailedHandler, DeployLockedEvent, DeployLockedHandler, DeploySite, DeploySucceededEvent, DeploySucceededHandler, DeployUnlockedEvent, DeployUnlockedHandler, FormSubmittedEvent, FormSubmittedHandler, User, UserDeletedEvent, UserDeletedHandler, UserLoginEvent, UserLoginHandler, UserModifiedEvent, UserModifiedHandler, UserSignupEvent, UserSignupHandler, UserValidateEvent, UserValidateHandler } from '@netlify/types';
import { PipelineSource } from 'node:stream';

interface HandlerContext {
    callbackWaitsForEmptyEventLoop: boolean;
    functionName: string;
    functionVersion: string;
    invokedFunctionArn: string;
    memoryLimitInMB: string;
    awsRequestId: string;
    logGroupName: string;
    logStreamName: string;
    identity?: Record<string, any>;
    clientContext?: Record<string, any>;
    getRemainingTimeInMillis(): number;
    /** @deprecated Use handler callback or promise result */
    done(error?: Error, result?: any): void;
    /** @deprecated Use handler callback with first argument or reject a promise result */
    fail(error: Error | string): void;
    /** @deprecated Use handler callback with second argument or resolve a promise result */
    succeed(messageOrObject: any): void;
    /** @deprecated Use handler callback or promise result */
    succeed(message: string, object: any): void;
}

type EventHeaders = Record<string, string | undefined>;
type EventMultiValueHeaders = Record<string, string[] | undefined>;
type EventQueryStringParameters = Record<string, string | undefined>;
type EventMultiValueQueryStringParameters = Record<string, string[] | undefined>;
interface HandlerEvent {
    rawUrl: string;
    rawQuery: string;
    path: string;
    httpMethod: string;
    headers: EventHeaders;
    multiValueHeaders: EventMultiValueHeaders;
    queryStringParameters: EventQueryStringParameters | null;
    multiValueQueryStringParameters: EventMultiValueQueryStringParameters | null;
    body: string | null;
    isBase64Encoded: boolean;
    route?: string;
}

interface HandlerResponse {
    statusCode: number;
    headers?: Record<string, boolean | number | string>;
    multiValueHeaders?: Record<string, readonly (boolean | number | string)[]>;
    body?: string;
    isBase64Encoded?: boolean;
}
interface BuilderResponse extends HandlerResponse {
    ttl?: number;
}
interface StreamingResponse extends Omit<HandlerResponse, 'body'> {
    body?: string | PipelineSource<any>;
}

interface HandlerCallback<ResponseType extends HandlerResponse = HandlerResponse> {
    (error: any, response: ResponseType): void;
}
interface BaseHandler<ResponseType extends HandlerResponse = HandlerResponse, C extends HandlerContext = HandlerContext> {
    (event: HandlerEvent, context: C, callback?: HandlerCallback<ResponseType>): void | Promise<ResponseType>;
}
interface BackgroundHandler<C extends HandlerContext = HandlerContext> {
    (event: HandlerEvent, context: C): void | Promise<void>;
}
type Handler = BaseHandler;
type BuilderHandler = BaseHandler<BuilderResponse>;
interface StreamingHandler {
    (event: HandlerEvent, context: HandlerContext): Promise<StreamingResponse>;
}

declare const wrapHandler: (handler: BuilderHandler) => Handler;

declare const getContext: () => Context;

interface BasePurgeCacheOptions {
    apiURL?: string;
    deployAlias?: string;
    tags?: string[];
    token?: string;
    userAgent?: string;
}
interface PurgeCacheOptionsWithSiteID extends BasePurgeCacheOptions {
    siteID?: string;
}
interface PurgeCacheOptionsWithSiteSlug extends BasePurgeCacheOptions {
    siteSlug: string;
}
interface PurgeCacheOptionsWithDomain extends BasePurgeCacheOptions {
    domain: string;
}
type PurgeCacheOptions = PurgeCacheOptionsWithSiteID | PurgeCacheOptionsWithSiteSlug | PurgeCacheOptionsWithDomain;
declare const purgeCache: (options?: PurgeCacheOptions) => Promise<void>;

type Path = `/${string}`;
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
type CronSchedule = string;
type RateLimitAggregator = 'domain' | 'ip';
type RateLimitAction = 'rate_limit' | 'rewrite';
interface RateLimitConfig {
    action?: RateLimitAction;
    aggregateBy?: RateLimitAggregator | RateLimitAggregator[];
    to?: string;
    windowSize: number;
    windowLimit: number;
}
interface BaseConfig {
    /**
     * If `true`, the function runs in background (fire-and-forget) mode: the
     * platform returns an immediate response to the client and the function's
     * return value is discarded.
     */
    background?: boolean;
    /**
     * Defines metadata about the framework or extension that has generated the
     * function, if applicable. Typically contains the nane and the version.
     * Should not be used for functions authored by users.
     */
    generator?: string;
    /**
     * Limits the HTTP methods for which the function will run. If not set, the
     * function will run for all supported methods.
     */
    method?: HTTPMethod | HTTPMethod[];
    /**
     * Configures the function to serve any static files that match the request
     * URL and render the function only if no matching files exist.
     */
    preferStatic?: boolean;
    /**
     * Set rate-limiting rules for this function.
     *
     * {@link} https://ntl.fyi/rate-limiting-code
     */
    rateLimit?: RateLimitConfig;
    /**
     * Airport code for the region where the function should be deployed.
     *
     * @example
     * 'iad'
     */
    region?: FunctionRegion;
}
type MemoryOrVcpu = {
    /**
     * Maximum amount of memory (in MB) the function can use. Accepts either
     * a number (e.g. `2048`) or a human-friendly string (e.g. `"2gb"`,
     * `"1024mb"`).
     *
     * Mutually exclusive with `vcpu`.
     */
    memory?: number | string;
    vcpu?: never;
} | {
    memory?: never;
    /**
     * Number of vCPUs the function should be provisioned with. Allowed
     * range is 0.5–2.
     *
     * Mutually exclusive with `memory`.
     */
    vcpu?: number;
};
interface ConfigWithPath extends BaseConfig {
    /**
     * One or more URL paths for which the function will not run, even if they
     * match a path defined with the `path` property. Paths must begin with a
     * forward slash.
     *
     * {@link} https://ntl.fyi/func-routing
     */
    excludedPath?: Path | Path[];
    /**
     * One or more URL paths for which the function will run. Paths must begin
     * with a forward slash.
     *
     * {@link} https://ntl.fyi/func-routing
     */
    path?: Path | Path[];
    /**
     * The `schedule` property cannot be used when `path` is used.
     */
    schedule?: never;
}
interface ConfigWithSchedule extends BaseConfig {
    /**
     * The `excludedPath` property cannot be used when `schedule` is used.
     */
    excludedPath?: never;
    /**
     * The `path` property cannot be used when `schedule` is used.
     */
    path?: never;
    /**
     * Cron expression representing the schedule at which the function will be
     * automatically invoked.
     *
     * {@link} https://ntl.fyi/sched-func
     */
    schedule: CronSchedule;
}
type Config = (ConfigWithPath | ConfigWithSchedule) & MemoryOrVcpu;

type FetchHandler = (req: Request, context: Context) => Response | Promise<Response>;
type BackgroundFetchHandler = (req: Request, context: Context) => void | Promise<void>;
interface BaseNetlifyFunction {
    deployBuilding?: DeployBuildingHandler;
    deploySucceeded?: DeploySucceededHandler;
    deployFailed?: DeployFailedHandler;
    deployDeleted?: DeployDeletedHandler;
    deployLocked?: DeployLockedHandler;
    deployUnlocked?: DeployUnlockedHandler;
    formSubmitted?: FormSubmittedHandler;
    userLogin?: UserLoginHandler;
    userSignup?: UserSignupHandler;
    userValidate?: UserValidateHandler;
    userModified?: UserModifiedHandler;
    userDeleted?: UserDeletedHandler;
}
type NetlifyFunction = (BaseNetlifyFunction & {
    fetch?: FetchHandler;
    config?: Config & {
        background?: false;
    };
}) | (BaseNetlifyFunction & {
    fetch?: BackgroundFetchHandler;
    config: Config & {
        background: true;
    };
});

/**
 * Declares a function to run on a cron schedule.
 * Not reachable via HTTP.
 *
 * @example
 * ```
 * export const handler = cron("5 4 * * *", async () => {
 *   // ...
 * })
 * ```
 *
 * @param schedule expressed as cron string.
 * @param handler
 * @see https://ntl.fyi/sched-func
 */
declare const schedule: (cron: string, handler: Handler) => Handler;

/**
 * Enables streaming responses. `body` accepts a Node.js `Readable` stream or a WHATWG `ReadableStream`.
 *
 * @example
 * ```
 * const { Readable } = require('stream');
 *
 * export const handler = stream(async (event, context) => {
 *   const stream = Readable.from(Buffer.from(JSON.stringify(event)))
 *   return {
 *     statusCode: 200,
 *     body: stream,
 *   }
 * })
 * ```
 *
 * @example
 * ```
 * export const handler = stream(async (event, context) => {
 *   const response = await fetch('https://api.openai.com/', { ... })
 *   // ...
 *   return {
 *     statusCode: 200,
 *     body: response.body, // Web stream
 *   }
 * })
 * ```
 *
 * @param handler
 * @see https://ntl.fyi/streaming-func
 */
declare const stream: (handler: StreamingHandler) => Handler;

/**
 * Default timeout for synchronous functions in seconds
 */
declare const SYNCHRONOUS_FUNCTION_TIMEOUT = 30;
/**
 * Default timeout for background functions in seconds
 */
declare const BACKGROUND_FUNCTION_TIMEOUT = 900;

declare global {
    var Netlify: NetlifyGlobal;
}

export { BACKGROUND_FUNCTION_TIMEOUT, type BackgroundHandler, type BuilderHandler, type BuilderResponse, type Config, type Handler, type HandlerCallback, type HandlerContext, type HandlerEvent, type HandlerResponse, type NetlifyFunction, SYNCHRONOUS_FUNCTION_TIMEOUT, type StreamingHandler, type StreamingResponse, wrapHandler as builder, getContext, purgeCache, schedule, stream };
