import { Redis, Cluster } from 'ioredis';
import { storageTypeValues } from '../constants.mjs';
import { LogLevel, Prettify } from './utils.mjs';

type StorageType = (typeof storageTypeValues)[number];
interface IProxyCache {
    addDfspIdToProxyMapping: (dfspId: string, proxyId: string) => Promise<boolean>;
    lookupProxyByDfspId: (dfspId: string) => Promise<string | null>;
    removeDfspIdFromProxyMapping: (dfspId: string) => Promise<boolean>;
    removeProxyGetPartiesTimeout: (alsReq: AlsRequestDetails, proxyId: string) => Promise<boolean>;
    setProxyGetPartiesTimeout: (alsReq: AlsRequestDetails, proxyId: string, ttlSec?: number) => Promise<boolean>;
    /**
     *  Should be called if there's no party's DFSP from Oracle GET /participant/{ID} request,
     *   before sending discovery calls to all available proxies.
     */
    setSendToProxiesList: (alsRequest: AlsRequestDetails, proxyIds: string[], ttlSec: number) => Promise<boolean>;
    receivedSuccessResponse: (alsRequest: AlsRequestDetails) => Promise<boolean>;
    /**
     *  Returns `true` if the last failed response is detected. In that case Parties error callback should be sent.
     */
    receivedErrorResponse: (alsRequest: AlsRequestDetails, proxyId: string) => Promise<IsLastFailure>;
    isPendingCallback: (alsRequest: AlsRequestDetails) => Promise<boolean>;
    processExpiredAlsKeys: (callbackFn: ProcessExpiryKeyCallback, batchSize: number) => Promise<unknown>;
    processExpiredProxyGetPartiesKeys: (callbackFn: ProcessExpiryKeyCallback, batchSize: number) => Promise<unknown>;
    connect: () => Promise<RedisConnectionStatus>;
    disconnect: () => Promise<boolean>;
    healthCheck: () => Promise<boolean>;
    isConnected: boolean;
}
type ProcessNodeStreamSingleKeyCallback = (key: string) => Promise<unknown>;
type ProcessExpiryKeyCallback = (key: string) => Promise<void>;
type PartyIdType = string;
type AlsRequestDetails = {
    sourceId: string;
    type: PartyIdType;
    partyId: string;
};
type IsLastFailure = boolean;
type ProxyCacheFactory = (type: StorageType, proxyConfig: ProxyCacheConfig) => IProxyCache;
type ProxyCacheConfig = RedisProxyCacheConfig | RedisClusterProxyCacheConfig | MySqlProxyCacheConfig;
type RedisProxyCacheConfig = Prettify<BasicConnectionConfig & RedisOptions>;
type RedisClusterProxyCacheConfig = Prettify<RedisClusterConnectionConfig & RedisClusterOptions>;
type RedisClusterConnectionConfig = {
    cluster: BasicConnectionConfig[];
};
type RedisOptions = {
    username?: string;
    password?: string;
    /** @defaultValue `true` */
    lazyConnect?: boolean;
    db?: number;
};
type RedisClusterOptions = RedisOptions;
type RedisConnectionStatus = Redis['status'] | Cluster['status'];
/** **(!)**  _MySqlProxyCacheConfig_ is not supported yet */
type MySqlProxyCacheConfig = Prettify<BasicConnectionConfig & {
    database: string;
    user?: string;
    password?: string;
}>;
type BasicConnectionConfig = {
    host: string;
    port: number;
};
type LibConfig = {
    logLevel: LogLevel;
    /** @defaultValue `30sec` */
    defaultTtlSec: number;
};

export type { AlsRequestDetails, BasicConnectionConfig, IProxyCache, IsLastFailure, LibConfig, MySqlProxyCacheConfig, PartyIdType, ProcessExpiryKeyCallback, ProcessNodeStreamSingleKeyCallback, ProxyCacheConfig, ProxyCacheFactory, RedisClusterConnectionConfig, RedisClusterOptions, RedisClusterProxyCacheConfig, RedisConnectionStatus, RedisOptions, RedisProxyCacheConfig, StorageType };
