export interface RedisConfig {
  host: string;
  port: number;
  password?: string;
  username?: string;
  db?: number;
  keyPrefix?: string;
  maxRetriesPerRequest?: number;
  retryDelayOnFailover?: number;
  connectTimeout?: number;
  commandTimeout?: number;
  keepAlive?: number;
  tls?: {
    cert?: string;
    key?: string;
    ca?: string;
    rejectUnauthorized?: boolean;
  };
}

export interface CacheProvider {
  get<T>(key: string): Promise<T | null>;
  set<T>(
    key: string,
    value: T,
    options?:
      | number
      | {
          ttl?: number;
          preserveTTL?: boolean;
          onlyIfExists?: boolean;
          onlyIfNotExists?: boolean;
          getOldValue?: boolean;
        }
  ): Promise<T | null>;
  del(key: string): Promise<void>;
  exists(key: string): Promise<boolean>;
  clear(): Promise<void>;
  keys(pattern: string): Promise<string[]>;
  getStats(): CacheStats;
  health(): Promise<boolean>;

  /**
   * Wait for the cache to be ready and connected
   * @param timeout Maximum time to wait in milliseconds (default: 5000)
   * @returns Promise that resolves when cache is ready
   */
  waitForReady(timeout?: number): Promise<void>;

  /**
   * Check if the cache is currently ready
   */
  isReady(): boolean;

  // Enhanced cache methods
  /**
   * Update value preserving existing TTL
   */
  update?<T>(key: string, value: T): Promise<T | null>;

  /**
   * Set value only if key exists
   */
  setIfExists?<T>(key: string, value: T, ttl?: number): Promise<boolean>;

  /**
   * Set value only if key doesn't exist
   */
  setIfNotExists?<T>(key: string, value: T, ttl?: number): Promise<boolean>;

  /**
   * Replace existing key's value and TTL
   */
  replace?<T>(key: string, value: T, ttl?: number): Promise<T | null>;
  /**
   * Atomically update field with transformation function
   */
  updateField?<T>(key: string, updater: (current: T | null) => T, ttl?: number): Promise<T | null>;
}

export interface CacheOptions {
  ttl?: number;
  keyPrefix?: string;
  enableMetrics?: boolean;
  name?: string; // Name for connection identification
  shared?: boolean; // Whether to use shared connection
  redisConfig: RedisConfig;
  logger?: any; // Optional logger instance
}

export interface CacheStats {
  hits: number;
  misses: number;
  errors: number;
  hitRate: number;
  total: number;
  uptime: number;
}

export interface CacheConfig {
  type: 'redis';
  keyPrefix?: string;
  defaultTTL?: number;
  enableMetrics?: boolean;
  compression?: boolean;
}

export type CacheKey = string | (() => string);

export interface SerializationOptions {
  compress?: boolean;
  binary?: boolean;
}
