import { Mongoose } from 'mongoose';
import { RedisOptions } from 'ioredis';
import { StringValue } from 'ms';

type CacheTTL = number | StringValue;
type CacheData = Record<string, unknown> | Record<string, unknown>[] | unknown[] | number | undefined;
type CacheOptions = {
    engine: 'memory' | 'redis';
    engineOptions?: RedisOptions;
    defaultTTL?: CacheTTL;
    debug?: boolean;
};
interface CacheEngine {
    get: (key: string) => Promise<CacheData> | CacheData;
    set: (key: string, value: CacheData, ttl?: CacheTTL) => Promise<void> | void;
    del: (key: string) => Promise<void> | void;
    clear: () => Promise<void> | void;
    close: () => Promise<void> | void;
}

declare module 'mongoose' {
    interface Query<ResultType, DocType, THelpers, RawDocType> {
        cache: (this: Query<ResultType, DocType, THelpers, RawDocType>, ttl?: CacheTTL, customKey?: string) => this;
        _key: string | null;
        getCacheKey: (this: Query<ResultType, DocType, THelpers, RawDocType>) => string;
        _ttl: CacheTTL | null;
        getCacheTTL: (this: Query<ResultType, DocType, THelpers, RawDocType>) => CacheTTL | null;
        op?: string;
        _path?: unknown;
        _fields?: unknown;
        _distinct?: unknown;
        _conditions?: unknown;
    }
    interface Aggregate<ResultType> {
        cache: (this: Aggregate<ResultType>, ttl?: CacheTTL, customKey?: string) => this;
        _key: string | null;
        getCacheKey: (this: Aggregate<ResultType>) => string;
        _ttl: CacheTTL | null;
        getCacheTTL: (this: Aggregate<ResultType>) => CacheTTL | null;
    }
}
declare class CacheMongoose {
    #private;
    private cache;
    private constructor();
    static init(mongoose: Mongoose, cacheOptions: CacheOptions): CacheMongoose;
    clear(customKey?: string): Promise<void>;
    close(): Promise<void>;
}

export { type CacheData, type CacheEngine, type CacheOptions, type CacheTTL, CacheMongoose as default };
