import { S3Client, S3ClientConfig } from '@aws-sdk/client-s3';
import { Readable } from 'node:stream';

/**
 * Converts a readable stream to a string
 */
declare function streamToString(stream: Readable | ReadableStream<Uint8Array> | Blob): Promise<string>;
interface S3MutexOptions {
    /**
     * AWS S3 client instance
     */
    s3Client?: S3Client;
    s3ClientConfig?: S3ClientConfig;
    /**
     * S3 bucket name where locks will be stored
     */
    bucketName: string;
    /**
     * Key prefix for lock files (optional)
     */
    keyPrefix?: string;
    /**
     * Max number of retries when acquiring a lock
     * @default 5
     */
    maxRetries?: number;
    /**
     * Base delay between retries in milliseconds (used for exponential backoff)
     * @default 200
     */
    retryDelayMs?: number;
    /**
     * Maximum delay between retries in milliseconds (caps the exponential backoff)
     * @default 5000 (5 seconds)
     */
    maxRetryDelayMs?: number;
    /**
     * Whether to add jitter to retry delays to prevent synchronized retries
     * @default true
     */
    useJitter?: boolean;
    /**
     * Lock timeout in milliseconds. After this time, the lock is considered stale
     * and can be forcefully acquired by another process.
     * @default 60000 (1 minute)
     */
    lockTimeoutMs?: number;
    /**
     * Clock skew tolerance in milliseconds. This value is added to expiration calculations
     * to account for differences in system clocks between distributed processes.
     * @default 1000 (1 second)
     */
    clockSkewToleranceMs?: number;
}
interface LockInfo {
    locked: boolean;
    owner?: string;
    acquiredAt?: number;
    expiresAt?: number;
    priority?: number;
}
declare class S3Mutex {
    private s3Client;
    private bucketName;
    private keyPrefix;
    private maxRetries;
    private retryDelayMs;
    private maxRetryDelayMs;
    private useJitter;
    private lockTimeoutMs;
    private clockSkewToleranceMs;
    private ownerId;
    private heldLocks;
    private lockRequests;
    private lockDependencies;
    constructor(options: S3MutexOptions);
    /**
     * Implements exponential backoff with optional jitter
     * @param attempt The current attempt number (0-based)
     * @returns A promise that resolves after the calculated delay
     */
    private exponentialBackoff;
    /**
     * Formats the full S3 key for a lock
     */
    private getLockKey;
    /**
     * Utility function to clean an ETag by removing quotes
     */
    private cleanETag;
    /**
     * Standard error handling for S3 operations
     */
    private handleS3Error;
    /**
     * Atomically initializes a lock if it doesn't exist
     * Uses a more atomic approach to initialize the lock file
     */
    private initializeLock;
    /**
     * Gets the current state of a lock
     */
    private getLockInfo;
    /**
     * Updates the lock info in S3 with improved error handling
     */
    private updateLockInfo;
    /**
     * Registers a lock dependency to help with deadlock detection
     * @param waitingOwner The owner waiting for the lock
     * @param targetLockName The lock being waited for
     * @param targetOwner The owner currently holding the lock
     */
    private registerLockDependency;
    /**
     * Checks if there's a potential deadlock scenario by detecting circular wait conditions
     * @param lockName The lock we're trying to acquire
     * @param currentOwner The current owner of the lock
     * @returns True if there's a potential deadlock
     */
    private isPotentialDeadlock;
    /**
     * Attempts to acquire a lock
     * @param lockName Name of the lock to acquire
     * @param timeoutMs Maximum time to wait for lock acquisition
     * @param priority Optional priority for this lock request (higher values have higher priority)
     * @returns A promise that resolves to true if the lock was acquired, false otherwise
     */
    acquireLock(lockName: string, timeoutMs?: number, priority?: number): Promise<boolean>;
    /**
     * Refreshes a lock's expiration time
     * @param lockName Name of the lock to refresh
     * @returns A promise that resolves to true if the lock was refreshed, false otherwise
     */
    refreshLock(lockName: string): Promise<boolean>;
    /**
     * Releases a lock
     * @param lockName Name of the lock to release
     * @param force If true, release the lock even if it's not owned by us
     * @returns A promise that resolves to true if the lock was released, false otherwise
     */
    releaseLock(lockName: string, force?: boolean): Promise<boolean>;
    /**
     * Executes a function while holding a lock
     * @param lockName Name of the lock to acquire
     * @param fn Function to execute while holding the lock
     * @param options Options for lock acquisition
     * @returns A promise that resolves to the result of the function or null if the lock couldn't be acquired
     */
    withLock<T>(lockName: string, fn: () => Promise<T>, options?: {
        timeoutMs?: number;
        retries?: number;
    }): Promise<T | null>;
    /**
     * Check if a lock exists and is currently locked
     * @param lockName Name of the lock to check
     * @returns A promise that resolves to true if the lock exists and is locked, false otherwise
     */
    isLocked(lockName: string): Promise<boolean>;
    /**
     * Check if we own a specific lock
     * @param lockName Name of the lock to check
     * @returns A promise that resolves to true if we own the lock, false otherwise
     */
    isOwnedByUs(lockName: string): Promise<boolean>;
    /**
     * Completely removes a lock file from S3
     * @param lockName Name of the lock to delete
     * @param force If true, delete the lock even if it's not owned by us
     * @returns A promise that resolves to true if the lock was deleted, false otherwise
     */
    deleteLock(lockName: string, force?: boolean): Promise<boolean>;
    /**
     * Finds and cleans up stale locks
     * @param options Optional configuration for cleanup
     * @returns A promise that resolves to the number of locks cleaned up
     */
    cleanupStaleLocks(options?: {
        prefix?: string;
        olderThan?: number;
        dryRun?: boolean;
    }): Promise<{
        cleaned: number;
        total: number;
        stale: number;
    }>;
}

export { type LockInfo, S3Mutex, type S3MutexOptions, streamToString };
