import { AnyPostgrestResponse } from '@supabase-cache-helpers/postgrest-core';
import { Redis } from 'ioredis';

type Value<Result> = AnyPostgrestResponse<Result>;
type Entry<Result> = {
    value: Value<Result>;
    freshUntil: number;
    /**
     * Unix timestamp in milliseconds.
     *
     * Do not use data after this point as it is considered no longer valid.
     *
     * You can use this field to configure automatic eviction in your store implementation.   *
     */
    staleUntil: number;
};

/**
 * A store is a common interface for storing, reading and deleting key-value pairs.
 *
 * The store implementation is responsible for cleaning up expired data on its own.
 */
interface Store {
    /**
     * A name for metrics/tracing.
     *
     * @example: memory | zone
     */
    name: string;
    /**
     * Return the cached value
     *
     * The response must be `undefined` for cache misses
     */
    get<Result>(key: string): Promise<Entry<Result> | undefined>;
    /**
     * Sets the value for the given key.
     *
     * You are responsible for evicting expired values in your store implementation.
     * Use the `entry.staleUntil` (unix milli timestamp) field to configure expiration
     */
    set<Result>(key: string, value: Entry<Result>): Promise<void>;
    /**
     * Removes the key from the store.
     */
    remove(key: string | string[]): Promise<void>;
    /**
     * Removes all keys with the given prefix.
     */
    removeByPrefix(prefix: string): Promise<void>;
}

type MemoryStoreConfig<TValue> = {
    persistentMap: Map<string, TValue>;
};
declare class MemoryStore implements Store {
    private readonly state;
    readonly name = "memory";
    constructor(config: MemoryStoreConfig<{
        expires: number;
        entry: Entry<any>;
    }>);
    get<Result>(key: string): Promise<Entry<Result> | undefined>;
    set<Result>(key: string, entry: Entry<Result>): Promise<void>;
    remove(keys: string | string[]): Promise<void>;
    removeByPrefix(prefix: string): Promise<void>;
}

type RedisStoreConfig = {
    redis: Redis;
    prefix?: string;
};
declare class RedisStore implements Store {
    private readonly redis;
    readonly name = "redis";
    private readonly prefix;
    constructor(config: RedisStoreConfig);
    private buildCacheKey;
    get<Result>(key: string): Promise<Entry<Result> | undefined>;
    set<Result>(key: string, entry: Entry<Result>): Promise<void>;
    remove(keys: string | string[]): Promise<void>;
    removeByPrefix(prefix: string): Promise<void>;
}

export { type Entry, MemoryStore, type MemoryStoreConfig, RedisStore, type RedisStoreConfig, type Store, type Value };
