import { RawAxiosRequestHeaders, AxiosResponse, AxiosRequestConfig, AxiosInstance } from 'axios';
import { ILogger } from '../logging/logger.js';
import { Interceptor } from './interceptor.js';
import { Token } from './token.js';

type ClientOptions = {
    /**
     * The client name
     */
    readonly name?: string;
    /**
     * The authorization token to use
     */
    readonly token?: Token;
    /**
     *: ILogger instance to use
     */
    readonly logger?: ILogger;
    /**
     * The baseUrl to prefix all client requests with
     */
    readonly baseUrl?: string;
    /**
     * Default request timeout (ms)
     */
    readonly timeout?: number;
    /**
     * Default headers
     */
    readonly headers?: RawAxiosRequestHeaders;
    /**
     * Default interceptors to register
     */
    readonly interceptors?: Array<Interceptor>;
    /**
     * Default middleware to register. Middleware runs in insertion order around
     * token resolution, existing interceptors, and the terminal HTTP transport.
     */
    readonly middlewares?: Array<Middleware>;
};
/**
 * Context for a single HTTP middleware invocation.
 *
 * `config` is the single source of truth for the outbound request: it carries
 * the method, URL, body (`data`), query `params`, `headers`, and SDK-local
 * `extensions`. Middleware reads and mutates the request through `config`
 * (e.g. `context.config.headers`, `context.config.extensions`); `extensions`
 * is never copied into headers, query params, or the request body by the
 * common client. `log` is available for diagnostics.
 */
type MiddlewareContext<D = any> = {
    /**
     * Mutable request config for this outbound call.
     *
     * This is the authoritative request state. Read the method, URL, body, and
     * SDK-local `extensions` from here, and mutate it in place to change the
     * request seen by later middleware and the terminal HTTP transport.
     */
    config: RequestConfig<D>;
    /**
     * Client logger.
     */
    readonly log: ILogger;
};
/**
 * Calls the next middleware in the chain, or the terminal HTTP transport.
 */
type MiddlewareNext<R = AxiosResponse> = () => Promise<R>;
/**
 * HTTP middleware that wraps one outbound request.
 *
 * Middleware is registered with `client.use(...)` and runs in insertion order:
 * the first registered middleware is the outermost wrapper.
 */
type Middleware = {
    invoke<R = AxiosResponse, D = any>(context: MiddlewareContext<D>, next: MiddlewareNext<R>): Promise<R>;
};
type RequestConfig<D = any> = AxiosRequestConfig<D> & {
    /**
     * If provided, this token will be used instead of
     * the default token provided in the `ClientOptions`
     */
    token?: Token;
    /**
     * SDK-local request metadata for interceptors. This is not sent over the wire.
     */
    extensions?: Record<string, unknown>;
};
type InterceptorRegistry = {
    readonly requestId?: number;
    readonly responseId?: number;
    readonly interceptor: Interceptor;
};
declare class Client {
    token?: Token;
    readonly name: string;
    protected options: ClientOptions;
    protected log: ILogger;
    protected http: AxiosInstance;
    protected seq: number;
    protected _interceptors: Map<number, InterceptorRegistry>;
    protected _middlewares: Map<number, Middleware>;
    constructor(options?: ClientOptions);
    get interceptors(): readonly Interceptor[];
    /**
     * Registered HTTP middleware in execution order.
     */
    get middlewares(): readonly Middleware[];
    get<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: RequestConfig<D>): Promise<R>;
    post<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: RequestConfig<D>): Promise<R>;
    put<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: RequestConfig<D>): Promise<R>;
    patch<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: RequestConfig<D>): Promise<R>;
    delete<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: RequestConfig<D>): Promise<R>;
    request<T = any, R = AxiosResponse<T>, D = any>(config: RequestConfig<D>): Promise<R>;
    /**
     * Register HTTP middleware.
     */
    use(middleware: Middleware): number;
    /**
     * Register an interceptor for request/response/error compatibility.
     */
    use(interceptor: Interceptor): number;
    /**
     * Eject an interceptor
     */
    eject(id: number): void;
    /**
     * Clear (Eject) all interceptors
     */
    clear(): void;
    /**
     * Create a copy of the client
     */
    clone(options?: ClientOptions): Client;
    protected withConfig(config?: RequestConfig): Promise<RequestConfig>;
    private useMiddleware;
    private send;
    private useInterceptor;
    private invokeMiddleware;
}

export { Client, type ClientOptions, type Middleware, type MiddlewareContext, type MiddlewareNext, type RequestConfig };
