import { AnyRecord } from 'store-vert';
import { EnhancedStore } from 'store-vert';
import { Key as Key_2 } from 'store-vert';
import { Store } from 'store-vert';
import { StoreFactory } from 'store-vert';
import { StoreKey } from 'store-vert';
import { TaskQueue } from 'id-queue';

export declare type BaseRequestor = (config: RequestConfig<any>) => any;

/**
 * 缓存中间件
 * 支持：
 * - 自定义缓存 key 生成
 * - 自定义缓存有效期（固定时长或动态计算）
 * - 自定义缓存有效性校验
 * - 自定义存储介质
 */
export declare const cache: <D = any, R = any>(options?: Partial<CacheOptions<D, R>>) => CacheMiddleware<D, R>;

/** 请求前上下文：检查缓存是否有效 */
declare interface CacheCheckContext<D = any, R = any> {
    key: CacheKey;
    config: RequestConfig<D>;
    cachedData?: R;
}

/**
 * 缓存 + 幂等组合配置（扁平化）
 */
export declare type CachedIdempotentConfig<D = any, R = any> = FlattenWithInstanceKey<[
CacheOptions<D, R>,
IdempotencyOptions<D>
]>;

/** 缓存 key 类型 */
export declare type CacheKey = string | number | symbol;

/** 请求前上下文：生成缓存 key */
declare interface CacheKeyContext<D = any> {
    config: RequestConfig<D>;
}

/** 缓存中间件类型（带 storage 实例）*/
declare type CacheMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.CACHE, D, R> & {
    storage: CacheStorageInstance<R>;
};

/** 缓存模块配置 */
declare interface CacheOptions<D = any, R = any> {
    /**
     * 缓存 key 生成函数
     * 默认使用 method + url 哈希
     */
    key: (ctx: CacheKeyContext<D>) => CacheKey;
    /**
     * 缓存有效期
     * - number: 固定毫秒数
     * - function: 可根据请求或响应动态计算
     */
    duration: number | ((ctx: CacheUpdateContext<D, R>) => number);
    /**
     * 判断缓存是否有效（请求前）
     * - 可以根据现有缓存数据或其他条件动态判断
     * - 返回 boolean 或 Promise<boolean>
     */
    isValid: (ctx: CacheCheckContext<D, R>) => boolean | Promise<boolean>;
    /** 缓存介质 */
    store: StoreDescriptor;
}

declare type CacheSchema<R> = Record<CacheKey, R>;

declare type CacheStorageInstance<R = any> = ExpirableCacheStorage<R> & EnhancedStore<ExpirableSchema<CacheSchema<R>>>;

/** 请求后上下文：更新缓存 */
declare interface CacheUpdateContext<D = any, R = any> {
    key: CacheKey;
    config: RequestConfig<D>;
    cachedData?: R;
    response: R;
}

export declare const concurrent: <D = any, R = any>(options?: Partial<ConcurrentOptions<D>>) => ConcurrentMiddleware<D, R>;

declare type ConcurrentContext<D = any> = {
    config: RequestConfig<D>;
};

declare type ConcurrentMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.CONCURRENT, D, R> & {
    pool: ConcurrentPool;
};

declare type ConcurrentOptions<D = any> = {
    parallelCount: number;
    createId: (params: ConcurrentContext<D>) => Id;
};

declare class ConcurrentPool<T extends any = any> {
    parallelCount: number;
    tasks: TaskItemList<T>;
    runningCount: number;
    constructor(parallelCount?: number);
    add(id: Id, task: Task<T>): Promise<T>;
    remove(id: Id): void;
    execute(currentTask: TaskItem<T>): Promise<void>;
    _run(): void;
}

/**
 * 并发 + 重试组合配置（扁平化）
 */
export declare type ConcurrentRetryConfig<D = any> = FlattenWithInstanceKey<[
ConcurrentOptions<D>,
RetryOptions<D>
]>;

/**
 * 创建带缓存和幂等的请求器
 * 适用场景：数据查询接口，既需要缓存提升性能，又要避免重复请求
 * @param config 组合配置对象
 */
export declare function createCachedIdempotentRequestor<D = any, R = any>(config: CachedIdempotentConfig<D, R>): Requestor;

/**
 * 创建带并发控制和重试的请求器
 * 适用场景：批量请求场景，需要控制并发数量，失败后自动重试
 * @param config 组合配置对象
 */
export declare function createConcurrentRetryRequestor<D = any>(config: ConcurrentRetryConfig<D>): Requestor;

declare const createPromiseCache: () => {
    getPromise: <T = unknown>(key: SafeKey) => Promise<T> | undefined;
    setPromise: <T = unknown>(key: SafeKey, promise: Promise<T>) => void;
    delPromise: (key: SafeKey) => boolean;
    clearCache: () => void;
};

/**
 * 创建请求器
 * @param config 配置对象（可选）
 * @returns 返回 Requestor 实例（所有方法都返回 Promise）
 */
export declare function createRequestor<const Extensions extends readonly Middleware[] = []>(config?: CreateRequestorConfig<Extensions>): Requestor;

export declare interface CreateRequestorConfig<Extensions extends readonly Middleware[] = readonly Middleware[]> {
    extensions?: Extensions;
    instanceKey?: Key;
}

declare class ExpirableCacheStorage<R = any> {
    store: EnhancedStore<ExpirableSchema<CacheSchema<R>>>;
    constructor(store: StoreDescriptor);
    /**
     * 设置缓存（自动包装成 ExpirableValue）
     * @param key 缓存 key
     * @param value 要缓存的值
     * @param duration 过期时长（毫秒），默认 24 小时
     */
    setCache(key: CacheKey, value: R, duration?: number): void;
    /**
     * 获取缓存值（检查过期，如果过期返回 undefined）
     * @param key 缓存 key
     * @returns 未过期返回值，已过期返回 undefined
     */
    getCache(key: CacheKey): Promise<R | undefined>;
    /**
     * 检查是否有有效的缓存（未过期）
     * @param key 缓存 key
     * @returns true 表示有有效缓存，false 表示无缓存或已过期
     */
    hasValidCache(key: CacheKey): Promise<boolean>;
}

/**
 * 将 Schema 的所有值类型映射为 ExpirableValue 包装的版本
 * 用于缓存存储的类型转换
 */
export declare type ExpirableSchema<Schema extends AnyRecord> = {
    [K in keyof Schema]: ExpirableValue<Schema[K]>;
};

/**
 * 带过期时间的值类型（通用型）
 * 可用于缓存、幂等、同步等需要时间控制的场景
 */
export declare type ExpirableValue<T = any> = {
    value: T;
    expireAt: number;
};

/**
 * 扁平化多个对象类型
 * @template Types - 需要扁平化的对象类型元组
 * @example
 * ```ts
 * type Result = Flatten<[{ a: string }, { b: number }, { c: boolean }]>
 * // Result = { a: string } & { b: number } & { c: boolean }
 * ```
 */
export declare type Flatten<Types extends readonly any[]> = UnionToIntersection<Types[number]>;

/**
 * 组合工具：扁平化多个对象类型并添加 instanceKey
 * @template Types - 需要扁平化的对象类型元组
 * @example
 * ```ts
 * type Result = FlattenWithInstanceKey<[TypeA, TypeB, TypeC]>
 * // Result = TypeA & TypeB & TypeC & { instanceKey?: Key }
 * ```
 */
export declare type FlattenWithInstanceKey<Types extends readonly any[]> = WithInstanceKey<Flatten<Types>>;

export declare type HandlerParams<T extends keyof Requestor> = Parameters<Requestor[T]>;

declare type Id = string | number;

declare type IdempotencyContext<D = any> = {
    config: RequestConfig<D>;
};

declare type IdempotencyOptions<D = any> = {
    key: (params: IdempotencyContext<D>) => string;
};

export declare const idempotent: <D = any, R = any>(options?: Partial<IdempotencyOptions<D>>) => IdempotentMiddleware<D, R>;

declare type IdempotentMiddleware<D = any, R = any> = TypedMiddleware<MIDDLEWARE_TYPE.IDEMPOTENT, D, R> & {
    promiseCache: PromiseCache;
};

export declare const inject: (requestor: BaseRequestor, instanceKey?: string) => void;

export declare type Key = string | symbol | number;

export declare type Middleware<D = any, R = any> = (context: {
    config: RequestConfig<D>;
    next: () => Promise<R>;
    ctx: MiddlewareContext;
}) => Promise<R>;

declare enum MIDDLEWARE_TYPE {
    CACHE = "cache",
    RETRY = "retry",
    IDEMPOTENT = "idempotent",
    CONCURRENT = "concurrent",
    THROTTLE = "throttle"
}

export declare interface MiddlewareContext extends Record<string, any> {
}

declare type MiddlewareType = MIDDLEWARE_TYPE;

declare type PromiseCache = ReturnType<typeof createPromiseCache>;

declare enum REQUEST_METHOD {
    GET = "get",
    POST = "post",
    PUT = "put",
    DELETE = "delete"
}

export declare interface RequestConfig<D = any> extends Record<string, any> {
    url: string;
    method: RequestMethod;
    data?: D;
}

declare type RequestMethod = REQUEST_METHOD;

export declare interface Requestor {
    request: <R = any, D = any>(config: RequestConfig<D>) => Promise<R>;
    get: <R = any, D = any>(url: string, config?: WithoutMethod<D>) => Promise<R>;
    post: <R = any, D = any>(url: string, data?: D, config?: WithoutMethod<D>) => Promise<R>;
    put: <R = any, D = any>(url: string, data?: D, config?: WithoutMethod<D>) => Promise<R>;
    delete: <R = any, D = any>(url: string, config?: WithoutMethod<D>) => Promise<R>;
}

export declare const retry: <D = any, R = any>(options?: Partial<RetryOptions<D>>) => TypedMiddleware<MIDDLEWARE_TYPE.RETRY, D, R>;

declare type RetryContext<D = any> = {
    config: RequestConfig<D>;
    lastResponse: any;
    attempt: number;
};

declare type RetryOptions<D = any> = {
    retries: number;
    delay: number | ((params: RetryContext<D>) => number);
    retryCondition: (params: RetryContext<D>) => boolean;
};

declare type SafeKey = string | number | symbol;

export declare type StoreDescriptor = StoreKey | {
    key: Key_2;
    factory: StoreFactory<Store<AnyRecord>, any[]>;
};

declare type Task<T> = () => Promise<T>;

declare type TaskItem<T> = {
    task: Task<T>;
    resolve: (value: T) => void;
    reject: (reason: any) => void;
};

declare type TaskItemList<T> = TaskQueue<TaskItem<T>>;

/**
 * 节流中间件
 *
 * 确保所有请求按照最小间隔时间排队执行
 *
 * @example
 * ```typescript
 * // 创建节流中间件，每次请求最少间隔 1 秒
 * const throttleMiddleware = throttle({ interval: 1000 })
 *
 * // 带超时控制，超过 5 秒丢弃请求
 * const throttleMiddleware = throttle({
 *   interval: 1000,
 *   timeout: 5000
 * })
 *
 * // 所有使用该中间件的请求共享同一个节流器
 * const api1 = createRequest(config1, [throttleMiddleware])
 * const api2 = createRequest(config2, [throttleMiddleware])
 *
 * // 组合使用
 * const api3 = createRequest(config3, [
 *   cache({ duration: 5000 }),     // 优先走缓存
 *   idempotent(),                  // 去重相同请求
 *   throttle({ interval: 1000 }),  // 限制请求速率
 *   retry({ retries: 3 })          // 失败重试
 * ])
 *
 * // 查看节流器状态
 * throttleMiddleware.throttler.getStatus()
 * ```
 */
export declare const throttle: <D = any, R = any>(options?: Partial<ThrottleOptions>) => ThrottleMiddleware<D, R>;

/**
 * 节流中间件类型
 */
declare type ThrottleMiddleware<D = any, R = any> = Middleware<D, R> & {
    __middlewareType: MIDDLEWARE_TYPE.THROTTLE;
    throttler: Throttler;
};

/**
 * 节流中间件配置
 */
declare interface ThrottleOptions {
    /**
     * 最小请求间隔（毫秒）
     * @default 1000
     */
    interval: number;
    /**
     * 队列超时时间（毫秒）
     * 如果请求在队列中等待超过此时间，将被拒绝并抛出 ThrottleTimeoutError
     * - 不设置（undefined）：永不超时，所有请求都会执行
     * - 设为 0：立即超时，直接拒绝排队的请求
     * - 设为正数：等待指定时间后超时
     * @default undefined
     */
    timeout?: number;
}

/**
 * 节流器接口
 */
declare interface Throttler {
    /** 添加任务到队列 */
    add: <T>(task: () => Promise<T>) => Promise<T>;
    /** 获取节流器状态 */
    getStatus: () => ThrottlerStatus;
    /** 清空队列（慎用） */
    clear: () => void;
}

/**
 * 节流器状态
 */
declare interface ThrottlerStatus {
    /** 当前队列长度 */
    queueLength: number;
    /** 上次执行时间戳 */
    lastExecutionTime: number;
    /** 是否正在处理队列 */
    isProcessing: boolean;
    /** 预计下次执行时间 */
    nextExecutionTime: number | null;
}

export declare type TypedMiddleware<Type extends MiddlewareType, D = any, R = any> = Middleware<D, R> & {
    __middlewareType: Type;
};

/* Excluded from this release type: UnionToIntersection */

export declare const useRequestor: (instanceKey?: Key) => BaseRequestor;

/**
 * 给类型添加可选的 instanceKey 字段
 * @template T - 源对象类型
 * @example
 * ```ts
 * type Config = { timeout: number }
 * type Result = WithInstanceKey<Config>
 * // Result = { timeout: number; instanceKey?: Key }
 * ```
 */
export declare type WithInstanceKey<T> = T & {
    /** 请求器实例 key（可选） */
    instanceKey?: Key;
};

export declare type WithoutMethod<D = any> = Omit<RequestConfig<D>, 'method' | 'url'>;

export { }
