import QueryString from "qs";
import { AnyObject } from "typescript-api-pro";

//#region src/error.d.ts
interface ResponseErrorOptions<E = unknown> {
  name?: string;
  message: string;
  status?: number;
  statusText?: string;
  response?: Response;
  config?: RequestConfig<unknown, BodyType, E>;
}
declare class ResponseError<E = unknown> extends Error {
  #private;
  constructor({
    message,
    status,
    statusText,
    response,
    config,
    name
  }: ResponseErrorOptions<E>);
  get message(): string;
  get status(): number | undefined;
  get statusText(): string | undefined;
  get response(): Response | undefined;
  get config(): RequestConfig<unknown, BodyType, E> | undefined;
  get name(): string;
}
//#endregion
//#region src/types.d.ts
type FetchResponseType = 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData' | 'bytes';
type RequestMethodWithParams = 'GET' | 'HEAD';
type RequestMethodWithBody = 'PUT' | 'PATCH' | 'POST' | 'DELETE' | 'OPTIONS';
type RequestMethod = RequestMethodWithParams | RequestMethodWithBody;
type BodyType = AnyObject | string | FormData | URLSearchParams | Blob | ArrayBuffer | ArrayBufferView | ReadableStream | null;
interface RequestConfig<P, D extends BodyType = BodyType, E = AnyObject> extends Omit<RequestInit, 'body' | 'signal' | 'credentials' | 'method'> {
  url: string;
  baseURL: string;
  params?: P;
  data?: D;
  withCredentials?: boolean;
  extra?: E;
  method: RequestMethod;
  resolve?: (() => any) | null;
  qsConfig?: QueryString.IStringifyOptions;
}
type BaseRequestOptions<P = AnyObject, D extends BodyType = BodyType, E = AnyObject> = Partial<{
  plugins: Array<HookFetchPlugin>;
  timeout: number;
  params: P;
  data: D;
  controller: AbortController;
  extra: E;
  qsConfig?: QueryString.IStringifyOptions;
  withCredentials: boolean;
  method: RequestMethod;
}> & Omit<RequestInit, 'body' | 'method'> & {
  url: string;
  baseURL: string;
};
interface FetchPluginContext<T = unknown, E = unknown, P = unknown, D extends BodyType = BodyType> {
  config: RequestConfig<P, D, E>;
  response: Response;
  responseType: FetchResponseType;
  result?: T;
  controller: AbortController;
}
interface StreamContext<T = unknown> {
  result: T;
  source: Uint8Array<ArrayBufferLike>;
  error: unknown | null;
}
type BeforeRequestHandler<E = unknown, P = unknown, D extends BodyType = BodyType> = (config: RequestConfig<P, D, E>) => RequestConfig<P, D, E> | PromiseLike<RequestConfig<P, D, E>>;
type AfterResponseHandler<T = unknown, E = unknown, P = unknown, D extends BodyType = BodyType> = (context: FetchPluginContext<T>, config: RequestConfig<P, D, E>) => FetchPluginContext<T> | PromiseLike<FetchPluginContext<T>>;
type BeforeStreamHandler<E = unknown, P = unknown, D extends BodyType = BodyType> = (body: ReadableStream<any>, config: RequestConfig<P, D, E>) => ReadableStream<any> | PromiseLike<ReadableStream<any>>;
type TransformStreamChunkHandler<E = unknown, P = unknown, D extends BodyType = BodyType> = (chunk: StreamContext<any>, config: RequestConfig<P, D, E>) => StreamContext | PromiseLike<StreamContext>;
type OnFinallyHandler<E = unknown, P = unknown, D extends BodyType = BodyType> = (res: Pick<FetchPluginContext<unknown, E, P, D>, 'config'>) => void | PromiseLike<void>;
type OnErrorHandler<E = unknown, P = unknown, D extends BodyType = BodyType> = (error: ResponseError<E>, config: RequestConfig<P, D, E>) => PromiseLike<Error | void | ResponseError<E>> | Error | void | ResponseError<E>;
interface HookFetchPlugin<T = unknown, E = unknown, P = unknown, D extends BodyType = BodyType> {
  name: string;
  priority?: number;
  beforeRequest?: BeforeRequestHandler<E, P, D>;
  afterResponse?: AfterResponseHandler<T, E, P, D>;
  beforeStream?: BeforeStreamHandler<E, P, D>;
  transformStreamChunk?: TransformStreamChunkHandler<E, P, D>;
  onError?: OnErrorHandler<E, P, D>;
  onFinally?: OnFinallyHandler<E, P, D>;
}
interface OptionProps {
  baseURL: string;
  timeout: number;
  headers: HeadersInit;
  plugins: Array<HookFetchPlugin<any, any, any, any>>;
  withCredentials: boolean;
  extra: AnyObject;
  qsConfig: QueryString.IStringifyOptions;
}
type BaseOptions = Partial<OptionProps>;
type RequestOptions<P = AnyObject, D extends BodyType = BodyType, E = AnyObject> = Omit<BaseRequestOptions<P, D, E>, 'url' | 'baseURL' | 'controller'>;
type RequestUseOptions<P = AnyObject, D extends BodyType = BodyType, E = AnyObject> = RequestOptions<P, D, E>;
type RequestWithBodyOptions<D extends BodyType = BodyType, P = AnyObject, E = AnyObject> = Omit<RequestOptions<P, D, E>, 'data'>;
type RequestWithParamsOptions<P = AnyObject, E = AnyObject> = Omit<RequestOptions<P, null, E>, 'params' | 'data'>;
type RequestWithBodyFnOptions<D extends BodyType = BodyType, P = AnyObject, E = AnyObject> = Omit<RequestOptions<P, D, E>, 'data' | 'method'>;
type RequestWithParamsFnOptions<P = AnyObject, E = AnyObject> = Omit<RequestOptions<P, null, E>, 'params' | 'data' | 'method'>;
type PostOptions<D extends BodyType = BodyType, P = AnyObject, E = AnyObject> = RequestWithBodyFnOptions<D, P, E>;
type PutOptions<D extends BodyType = BodyType, P = AnyObject, E = AnyObject> = RequestWithBodyFnOptions<D, P, E>;
type PatchOptions<D extends BodyType = BodyType, P = AnyObject, E = AnyObject> = RequestWithBodyFnOptions<D, P, E>;
type GetOptions<P = AnyObject, E = AnyObject> = RequestWithParamsFnOptions<P, E>;
type HeadOptions<P = AnyObject, E = AnyObject> = RequestWithParamsFnOptions<P, E>;
type OptionsOptions<P = AnyObject, D extends BodyType = BodyType, E = AnyObject> = RequestUseOptions<P, D, E>;
type DeleteOptions<P = AnyObject, D extends BodyType = BodyType, E = AnyObject> = RequestUseOptions<P, D, E>;
//#endregion
export { AfterResponseHandler, BaseOptions, BaseRequestOptions, BeforeRequestHandler, BeforeStreamHandler, BodyType, DeleteOptions, FetchPluginContext, FetchResponseType, GetOptions, HeadOptions, HookFetchPlugin, OnErrorHandler, OnFinallyHandler, OptionProps, OptionsOptions, PatchOptions, PostOptions, PutOptions, RequestConfig, RequestMethod, RequestMethodWithBody, RequestMethodWithParams, RequestOptions, RequestUseOptions, RequestWithBodyFnOptions, RequestWithBodyOptions, RequestWithParamsFnOptions, RequestWithParamsOptions, ResponseError, ResponseErrorOptions, StreamContext, TransformStreamChunkHandler };