/**
 * Redis-based cache manager for SAP API responses
 *
 * @module cache-manager
 */
import { CachedData, CacheOptions, CacheAdminStats, CacheKeyInfo } from '../types/cache';
/**
 * Manages caching operations with Redis
 */
export declare class CacheManager {
    private client;
    private isConnected;
    private isEnabled;
    private connectionString;
    private connectPromise;
    private encryptionKey;
    private encryptionEnabled;
    private connectedAt;
    private _memoryFallbackCache;
    private _memoryFallbackMaxSize;
    private _memoryFallbackEnabled;
    private maxReconnectAttempts;
    private reconnectDelay;
    private maxReconnectDelay;
    private currentReconnectAttempt;
    private isReconnecting;
    private _revalidationQueues;
    private _revalidationExecuting;
    private _revalidationProcessing;
    private _revalidationConcurrency;
    private _revalidationDelayMs;
    private _maxQueueLengthPerHost;
    private _queueDropStrategy;
    private _revalidationSessionCount;
    private _revalidationSessionStart;
    /**
     * Tracks ongoing revalidation operations to prevent duplicate SAP API calls
     *
     * Maps cache keys to their revalidation promises. When multiple requests
     * arrive for the same stale cache key, subsequent requests will be skipped
     * while the first revalidation is in progress.
     *
     * Memory Management:
     * - Keys are automatically removed after revalidation completes (success or failure)
     * - All entries are cleared when the cache manager is closed
     *
     * @private
     * @since 1.x.x (Queue Deduplication Feature)
     */
    private _revalidationInProgress;
    /**
     * Creates a new CacheManager instance
     *
     * @param connectionString - Redis connection string
     * @param enabled - Whether caching is enabled
     * @param encryptionSecret - Optional secret for encrypting cache values (recommended: use OAuth client secret)
     * @param maxQueueLength - Maximum revalidation queue length (default: 500, increased from 100 for P2-2 fix)
     * @param queueDropStrategy - Strategy for handling queue overflow: 'oldest' (drop oldest tasks), 'newest' (drop newest/incoming tasks), 'warn' (only warn, no limit)
     */
    constructor(connectionString: string, enabled?: boolean, encryptionSecret?: string, maxQueueLength?: number, queueDropStrategy?: 'oldest' | 'newest' | 'warn');
    /**
     * Initializes encryption key from the provided secret
     * Uses PBKDF2 to derive a secure encryption key
     *
     * FIX P3-1: Salt is now tenant-specific by including a hash of the secret
     * This ensures different tenants (with different secrets) get different encryption keys
     * even if the static salt prefix is the same.
     *
     * @param secret - The secret to derive the encryption key from
     */
    private initializeEncryption;
    /**
     * Encrypts data using AES-256-GCM
     *
     * @param data - The data to encrypt
     * @returns Encrypted data with IV prepended
     */
    private encrypt;
    /**
     * Decrypts data using AES-256-GCM
     *
     * @param encryptedData - The encrypted data with IV prepended
     * @returns Decrypted data
     */
    private decrypt;
    /**
     * Initializes and connects to Redis
     * Must be called before using the cache manager
     */
    connect(): Promise<void>;
    /**
     * Initializes the Redis client connection
     */
    private initialize;
    /**
     * Gets cached data by key
     * Falls back to in-memory cache if Redis is unavailable (P2-3 fix)
     *
     * @param key - The cache key
     * @returns Cached data or null if not found
     */
    get(key: string): Promise<CachedData | null>;
    /**
     * Stores data in the in-memory fallback cache
     * Implements simple LRU eviction when max size is reached
     *
     * @param key - The cache key
     * @param data - The cached data
     * @private
     */
    private _setMemoryFallback;
    /**
     * Sets cached data with options
     * Also stores in memory fallback for resilience (P2-3 fix)
     *
     * @param key - The cache key
     * @param data - The data to cache
     * @param options - Cache options (TTL and revalidation time)
     */
    set(key: string, data: any, options: CacheOptions): Promise<void>;
    /**
     * Determines if cached data should be revalidated
     *
     * @param cachedData - The cached data to check
     * @param forceRevalidate - Force revalidation regardless of time
     * @returns true if revalidation is needed
     */
    shouldRevalidate(cachedData: CachedData, forceRevalidate?: boolean): boolean;
    /**
     * Checks if cached data is expired
     *
     * @param cachedData - The cached data to check
     * @returns true if the data is expired
     */
    isExpired(cachedData: CachedData): boolean;
    private _getHostnameQueue;
    private _getHostnameExecuting;
    private _processHostnameQueue;
    private _getTotalQueueLength;
    /**
     * Cleans up revalidation tracking after completion
     *
     * This method is called in the `finally` block of each revalidation task
     * to ensure the cache key is removed from `_revalidationInProgress`,
     * regardless of whether the revalidation succeeded or failed.
     *
     * Memory Safety:
     * - Guaranteed cleanup through `finally` block
     * - Safe to call multiple times (idempotent)
     * - Handles non-existent keys gracefully
     *
     * Debug Logging:
     * When DEBUG=true, logs the cleanup operation and the current number
     * of revalidations still in progress.
     *
     * @param key - The cache key that completed revalidation
     * @private
     * @since 1.x.x (Queue Deduplication Feature)
     */
    private _cleanupRevalidation;
    /**
     * Revalidates cache in the background with timeout and rate limiting
     * Supports differential updates for collection endpoints
     *
     * Queue Deduplication:
     * Prevents multiple concurrent revalidations of the same cache key.
     * If a revalidation for a given key is already in progress, subsequent
     * requests will be skipped to avoid duplicate SAP API calls.
     *
     * Example scenario:
     * - 50 users request the same stale artifact data simultaneously
     * - Without deduplication: 50 SAP API calls
     * - With deduplication: 1 SAP API call
     *
     * @param key - The cache key to revalidate
     * @param fetchFn - Function that fetches fresh data
     * @param options - Cache options for the new data
     * @param enableDifferential - Enable differential updates (only for collections)
     * @param isCollectionEndpoint - Whether this is a collection endpoint
     */
    revalidateInBackground(key: string, fetchFn: () => Promise<any>, options: CacheOptions, enableDifferential?: boolean, isCollectionEndpoint?: boolean): Promise<void>;
    clearRevalidationQueue(): number;
    getQueueStatus(): {
        length: number;
        executing: number;
        processing: boolean;
        maxLength: number;
        perHost: Record<string, number>;
    };
    /**
     * Extracts artifacts array from various cache data formats
     * Supports: Direct array, OData v2/v4, IntegrationPackages, IntegrationRuntimeArtifacts
     *
     * @param data - The cache data to extract from
     * @returns Array of artifacts or null if format not recognized
     */
    private extractArtifactsArray;
    /**
     * Saves CachedData directly to Redis (internal helper for differential updates)
     *
     * @param key - The cache key
     * @param cachedData - The complete CachedData object to save
     */
    private saveCachedData;
    /**
     * Closes the Redis connection and removes all event listeners
     */
    close(): Promise<void>;
    /**
     * Checks if the cache manager is ready to use
     */
    isReady(): boolean;
    /**
     * Disables the cache manager
     * Useful when connection fails and cache should be disabled
     */
    disable(): void;
    /**
     * Finds cache keys matching a pattern using Redis SCAN
     * Uses SCAN instead of KEYS for better performance in production
     *
     * @param pattern - The pattern to match (supports wildcards like *)
     * @returns Array of matching cache keys
     *
     * @example
     * const keys = await cacheManager.findKeysByPattern('sap:hostname:GET:/IntegrationRuntimeArtifacts*');
     */
    findKeysByPattern(pattern: string): Promise<string[]>;
    /**
     * Updates a partial cache entry by applying an update function
     * Reads the cache entry, applies the update function, and writes it back
     *
     * @param key - The cache key to update
     * @param updateFn - Function that receives the cached data and returns updated data
     * @returns true if update was successful, false otherwise
     *
     * @example
     * await cacheManager.updatePartial('my-key', (cachedData) => {
     *   cachedData.data.status = 'updated';
     *   return cachedData;
     * });
     */
    updatePartial(key: string, updateFn: (cachedData: CachedData) => CachedData): Promise<boolean>;
    /**
     * Deletes a single cache entry by key
     *
     * @param key - The cache key to delete
     * @returns true if the key was deleted, false if the key doesn't exist or an error occurred
     *
     * @example
     * const deleted = await cacheManager.delete('sap:hostname:GET:/IntegrationRuntimeArtifacts(\'artifactId\')');
     */
    delete(key: string): Promise<boolean>;
    /**
     * Deletes all cache entries matching a pattern
     * Uses findKeysByPattern internally to find matching keys, then deletes them
     *
     * @param pattern - The pattern to match (supports wildcards like *)
     * @returns The number of keys deleted
     *
     * @example
     * const deletedCount = await cacheManager.deleteByPattern('sap:hostname:GET:/IntegrationRuntimeArtifacts*');
     */
    deleteByPattern(pattern: string): Promise<number>;
    /**
     * Updates a single field in a cache entry using a dot-notation path
     *
     * @param key - The cache key to update
     * @param fieldPath - The dot-notation path to the field (e.g. 'data.Status' or 'data.d.results[0].Status')
     * @param value - The value to set
     * @returns true if the update was successful, false otherwise
     *
     * @example
     * await cacheManager.updateField('my-key', 'data.Status', 'STARTED');
     */
    updateField(key: string, fieldPath: string, value: any): Promise<boolean>;
    /**
     * Updates multiple fields in a cache entry using dot-notation paths
     *
     * @param key - The cache key to update
     * @param updates - Object mapping field paths to values
     * @returns true if the update was successful, false otherwise
     *
     * @example
     * await cacheManager.updateFields('my-key', {
     *   'data.Status': 'STARTED',
     *   'data.DeployedBy': 'user@example.com',
     *   'data.DeployedOn': '2024-01-01T00:00:00Z'
     * });
     */
    updateFields(key: string, updates: Record<string, any>): Promise<boolean>;
    /**
     * Updates an item in an array within a cache entry
     * Finds the item by ID and updates its fields
     *
     * @param key - The cache key to update
     * @param arrayPath - The dot-notation path to the array (e.g. 'data.d.results' or 'data.IntegrationPackages')
     * @param itemId - The ID of the item to update (matches 'Id' or 'id' property)
     * @param updates - Object mapping field names to values to update
     * @returns true if the update was successful, false otherwise
     *
     * @example
     * await cacheManager.updateInArray('my-key', 'data.d.results', 'artifact1', {
     *   Status: 'STARTED',
     *   DeployedBy: 'user@example.com'
     * });
     */
    updateInArray(key: string, arrayPath: string, itemId: string, updates: Record<string, any>): Promise<boolean>;
    /**
     * Performs multiple cache updates in a single batch using Redis Pipeline
     *
     * **CRITICAL**: Uses Redis Pipeline for performance (50-100 updates = 1 roundtrip instead of 50-100)
     *
     * @param updates - Array of update operations, each containing a key and updates object
     * @returns Object with success and failed counts
     *
     * @example
     * const result = await cacheManager.batchUpdate([
     *   { key: 'key1', updates: { 'data.Status': 'STARTED' } },
     *   { key: 'key2', updates: { 'data.Status': 'STOPPED' } }
     * ]);
     * // result: { success: 2, failed: 0 }
     */
    batchUpdate(updates: Array<{
        key: string;
        updates: Record<string, any>;
    }>): Promise<{
        success: number;
        failed: number;
    }>;
    /**
     * Deletes multiple cache keys in a single batch using Redis Pipeline
     *
     * **CRITICAL**: Uses Redis Pipeline for performance (50-100 deletes = 1 roundtrip instead of 50-100)
     *
     * @param keys - Array of cache keys to delete
     * @returns The number of keys successfully deleted
     *
     * @example
     * const deleted = await cacheManager.batchDelete(['key1', 'key2', 'key3']);
     */
    batchDelete(keys: string[]): Promise<number>;
    /**
     * Gets cache statistics for admin/debug purposes
     *
     * **WARNING**: This API is expensive (uses MEMORY USAGE + SCAN) and should NOT be used in hot-path code.
     * Primarily intended for admin/debug/monitoring purposes.
     *
     * @returns Cache statistics including total keys, size, TTL information, etc.
     *
     * @example
     * const stats = await cacheManager.getStats();
     * console.log(`Total keys: ${stats.totalKeys}, Total size: ${stats.totalSize} bytes`);
     */
    getStats(): Promise<CacheAdminStats>;
    /**
     * Gets cache statistics for keys matching a specific pattern
     *
     * **WARNING**: This API is expensive (uses MEMORY USAGE + SCAN) and should not be used in hot-path code.
     * Primarily intended for admin/debug/monitoring purposes.
     *
     * @param pattern - The pattern to match cache keys (e.g., 'sap:*:GET:/IntegrationPackages*')
     * @returns Cache statistics for matching keys
     *
     * @example
     * const stats = await cacheManager.getStatsByPattern('sap:*:GET:/IntegrationRuntimeArtifacts*');
     * console.log(`Matching keys: ${stats.totalKeys}, Total size: ${stats.totalSize} bytes`);
     */
    getStatsByPattern(pattern: string): Promise<CacheAdminStats>;
    /**
     * Gets the health status of the cache
     *
     * @returns Health status including connection status, total keys, and uptime
     *
     * @example
     * const health = await cacheManager.getCacheHealth();
     * console.log(`Cache is ${health.isHealthy ? 'healthy' : 'unhealthy'}, Uptime: ${health.uptime}s`);
     */
    getCacheHealth(): Promise<{
        isHealthy: boolean;
        connectionStatus: 'connected' | 'disconnected' | 'error';
        totalKeys: number;
        errorRate?: number;
        lastError?: string;
        uptime: number;
    }>;
    /**
     * Gets cache statistics grouped by endpoint
     *
     * **WARNING**: This API is expensive (uses MEMORY USAGE + SCAN) and should not be used in hot-path code.
     * Primarily intended for admin/debug/monitoring purposes.
     *
     * @param endpoint - The endpoint path (e.g., '/IntegrationPackages' or '/IntegrationRuntimeArtifacts')
     * @returns Aggregated statistics for the endpoint
     *
     * @example
     * const stats = await cacheManager.getStatsByEndpoint('/IntegrationPackages');
     * console.log(`Endpoint: ${stats.endpoint}, Keys: ${stats.keys}, Size: ${stats.totalSize} bytes`);
     */
    getStatsByEndpoint(endpoint: string): Promise<{
        endpoint: string;
        keys: number;
        totalSize: number;
        averageTtl?: number;
    }>;
    /**
     * Gets information about a specific cache key
     *
     * **WARNING**: This API uses MEMORY USAGE which is expensive and should NOT be used in hot-path code.
     * Primarily intended for admin/debug purposes.
     *
     * @param key - The cache key to get information about
     * @returns Information about the cache key, or null if the key doesn't exist
     *
     * @example
     * const info = await cacheManager.getKeyInfo('sap:hostname:GET:/IntegrationRuntimeArtifacts');
     * if (info) {
     *   console.log(`Key exists: ${info.exists}, TTL: ${info.ttl}s, Size: ${info.size} bytes`);
     * }
     */
    getKeyInfo(key: string): Promise<CacheKeyInfo | null>;
    /**
     * Adds an artifact to a cache entry
     *
     * @param key - The cache key to update
     * @param artifact - The artifact to add
     * @param options - Optional configuration
     * @param options.arrayPath - Custom dot-notation path to the array (e.g. 'data.custom.path')
     * @param options.preventDuplicates - If true, prevents adding duplicate artifacts
     * @returns true if the artifact was added successfully, false otherwise
     *
     * @example
     * const success = await cacheManager.addToCache('my-key', newArtifact, {
     *   preventDuplicates: true
     * });
     */
    addToCache(key: string, artifact: any, options?: {
        arrayPath?: string;
        preventDuplicates?: boolean;
    }): Promise<boolean>;
    /**
     * Removes an artifact from a cache entry
     *
     * @param key - The cache key to update
     * @param artifactId - The ID of the artifact to remove
     * @param options - Optional configuration
     * @param options.arrayPath - Custom dot-notation path to the array (e.g. 'data.custom.path')
     * @returns true if the artifact was removed successfully, false otherwise
     *
     * @example
     * const success = await cacheManager.removeFromCache('my-key', 'MyArtifactId');
     */
    removeFromCache(key: string, artifactId: string, options?: {
        arrayPath?: string;
    }): Promise<boolean>;
    /**
     * Adds multiple artifacts to cache entries in a single batch using Redis Pipeline
     *
     * **CRITICAL**: Uses Redis Pipeline for performance (50-100 updates = 1 roundtrip instead of 50-100)
     *
     * @param updates - Array of artifact addition operations, each containing a key, artifact, and optional options
     * @returns Object with success and failed counts
     *
     * @example
     * const result = await cacheManager.batchAddToCache([
     *   { key: 'key1', artifact: { Id: 'Artifact1' }, options: { preventDuplicates: true } },
     *   { key: 'key2', artifact: { Id: 'Artifact2' } }
     * ]);
     * // result: { success: 2, failed: 0 }
     */
    batchAddToCache(updates: Array<{
        key: string;
        artifact: any;
        options?: {
            arrayPath?: string;
            preventDuplicates?: boolean;
        };
    }>): Promise<{
        success: number;
        failed: number;
    }>;
    /**
     * Updates the TTL (Time-To-Live) of a cache entry
     *
     * @param key - The cache key to update
     * @param newTTL - The new TTL in seconds
     * @returns true if the TTL was updated successfully, false otherwise
     *
     * @example
     * const success = await cacheManager.updateTTL('my-key', 3600); // Set TTL to 1 hour
     */
    updateTTL(key: string, newTTL: number): Promise<boolean>;
    /**
     * Extends the TTL (Time-To-Live) of a cache entry by adding additional seconds
     *
     * @param key - The cache key to update
     * @param additionalSeconds - The number of seconds to add to the current TTL
     * @returns true if the TTL was extended successfully, false otherwise
     *
     * @example
     * const success = await cacheManager.extendTTL('my-key', 1800); // Add 30 minutes
     */
    extendTTL(key: string, additionalSeconds: number): Promise<boolean>;
    /**
     * Updates TTL for multiple cache keys in a single batch using Redis Pipeline
     *
     * **CRITICAL**: Uses Redis Pipeline for performance (50-100 updates = 1 roundtrip instead of 50-100)
     *
     * @param updates - Array of TTL update operations, each containing a key and new TTL
     * @returns Object with success and failed counts
     *
     * @example
     * const result = await cacheManager.batchUpdateTTL([
     *   { key: 'key1', ttl: 3600 },
     *   { key: 'key2', ttl: 7200 }
     * ]);
     * // result: { success: 2, failed: 0 }
     */
    batchUpdateTTL(updates: Array<{
        key: string;
        ttl: number;
    }>): Promise<{
        success: number;
        failed: number;
    }>;
    /**
     * Warms the cache by pre-loading multiple endpoints
     *
     * @param endpoints - Array of endpoints to warm, each containing cache key, fetch function, and cache options
     * @param config - Optional configuration for warming behavior
     * @param config.timeout - Timeout per endpoint in milliseconds (default: 30000)
     * @param config.parallel - Whether to execute endpoints in parallel (default: true)
     * @returns Statistics about the warming operation (success count, failed count, duration, errors)
     *
     * @example
     * const result = await cacheManager.warmCache([
     *   {
     *     key: 'sap:hostname:GET:/IntegrationPackages',
     *     fetchFn: () => api.getIntegrationPackages(),
     *     options: { ttl: 3600, revalidateAfter: 1800 }
     *   }
     * ]);
     */
    warmCache(endpoints: Array<{
        key: string;
        fetchFn: () => Promise<any>;
        options?: CacheOptions;
    }>, config?: {
        timeout?: number;
        parallel?: boolean;
    }): Promise<{
        success: number;
        failed: number;
        duration: number;
        errors?: Array<{
            key: string;
            error: string;
        }>;
    }>;
    /**
     * Validates a single cache entry for consistency and validity
     *
     * @param key - The cache key to validate
     * @param options - Optional validation options
     * @param options.compareWithSap - Whether to compare cache data with SAP API (requires fetchFn)
     * @param options.fetchFn - Function to fetch fresh data from SAP API for comparison
     * @param options.autoRepair - Whether to automatically repair invalid entries
     * @returns Validation result with validity status, issues, and optional repair status
     *
     * @example
     * const result = await cacheManager.validateCacheEntry('my-key', {
     *   compareWithSap: true,
     *   fetchFn: () => api.getData(),
     *   autoRepair: true
     * });
     */
    validateCacheEntry(key: string, options?: {
        compareWithSap?: boolean;
        fetchFn?: () => Promise<any>;
        autoRepair?: boolean;
    }): Promise<{
        isValid: boolean;
        issues: string[];
        repaired?: boolean;
        comparisonResult?: {
            matches: boolean;
            differences?: string[];
        };
    }>;
    /**
     * Validates all cache entries matching a pattern
     *
     * @param pattern - The pattern to match cache keys (supports wildcards like *)
     * @param options - Optional validation options
     * @param options.autoRepair - Whether to automatically repair invalid entries
     * @param options.compareWithSap - Whether to compare cache data with SAP API (requires fetchFn)
     * @param options.fetchFn - Function to fetch fresh data from SAP API for comparison (receives key as parameter)
     * @returns Validation statistics and issues per key
     *
     * @example
     * const result = await cacheManager.validateCacheByPattern('sap:hostname:GET:/IntegrationPackages*', {
     *   autoRepair: true
     * });
     */
    validateCacheByPattern(pattern: string, options?: {
        autoRepair?: boolean;
        compareWithSap?: boolean;
        fetchFn?: (key: string) => Promise<any>;
    }): Promise<{
        total: number;
        valid: number;
        invalid: number;
        repaired: number;
        issues: Array<{
            key: string;
            issues: string[];
        }>;
    }>;
    /**
     * Gets data from cache or fetches it using the provided function
     * Implements Stale-While-Revalidate pattern:
     * - If data is in cache and fresh: return immediately
     * - If data is in cache but stale: return immediately, revalidate in background
     * - If data is expired or not in cache: fetch fresh data
     *
     * @param key - The cache key
     * @param fetchFn - Function to fetch fresh data
     * @param options - Cache options (TTL and revalidation time)
     * @param forceRefresh - Force fetching fresh data regardless of cache state
     * @returns Object containing data and cache info
     *
     * @example
     * const result = await cacheManager.getOrFetch(
     *   'sap:hostname:GET:/IntegrationPackages',
     *   async () => await api.getPackages(),
     *   { ttl: 2592000, revalidateAfter: 300 },
     *   false
     * );
     * console.log(result.data);     // The actual data
     * console.log(result.cacheInfo); // { hit: true, age: 120, status: 'HIT' }
     */
    getOrFetch<T>(key: string, fetchFn: () => Promise<T>, options: CacheOptions, forceRefresh?: boolean): Promise<{
        data: T;
        cacheInfo: {
            hit: boolean;
            age: number | null;
            status: 'HIT' | 'HIT-STALE' | 'MISS' | 'DISABLED';
        };
    }>;
    /**
     * Returns health status of the cache manager and Redis connection
     * Useful for monitoring and failover detection
     *
     * @returns Health status object
     */
    getHealthStatus(): {
        enabled: boolean;
        connected: boolean;
        reconnecting: boolean;
        reconnectAttempts: number;
        maxReconnectAttempts: number;
        uptime: number;
        connectedAt: string | null;
        encryptionEnabled: boolean;
        queueStatus: {
            length: number;
            executing: number;
            processing: boolean;
            maxLength: number;
            perHost: Record<string, number>;
        };
        status: "reconnecting" | "healthy" | "degraded" | "offline";
    };
    /**
     * Gets a human-readable connection status
     *
     * @private
     * @returns Connection status string
     */
    private _getConnectionStatus;
}
