import type { AuthenticatedContext, AuthRequestContext, AuthUser } from "../../types/authTypes.js";
/**
 * Token bucket state for a single user
 */
type TokenBucket = {
    /** Current number of tokens available */
    tokens: number;
    /** Last time tokens were added */
    lastRefill: number;
    /** User identifier */
    userId: string;
};
/**
 * Rate limit configuration per user or role
 */
export type RateLimitConfig = {
    /** Maximum requests allowed in the window */
    maxRequests: number;
    /** Time window in milliseconds */
    windowMs: number;
    /** Optional: Different limits per role (role -> maxRequests) */
    roleLimits?: Record<string, number>;
    /** Optional: Different limits per user ID (userId -> maxRequests) */
    userLimits?: Record<string, number>;
    /** Skip rate limiting for these roles */
    skipRoles?: string[];
    /** Error message when rate limited */
    message?: string;
};
/**
 * Rate limit result
 */
export type RateLimitResult = {
    /** Whether the request is allowed */
    allowed: boolean;
    /** Remaining requests in the current window */
    remaining: number;
    /** Time until the bucket resets (ms) */
    resetIn: number;
    /** Total limit for this user */
    limit: number;
    /** Error message if rate limited */
    error?: string;
};
/**
 * Result of an atomic consume operation
 */
export type AtomicConsumeResult = {
    /** Updated bucket after the operation */
    bucket: TokenBucket;
    /** Whether a token was successfully consumed */
    consumed: boolean;
};
/**
 * Interface for rate limit storage backends
 */
export interface RateLimitStorage {
    /** Get the current bucket for a user */
    getBucket(userId: string): Promise<TokenBucket | null>;
    /** Set the bucket for a user */
    setBucket(userId: string, bucket: TokenBucket): Promise<void>;
    /** Delete a bucket (for cleanup) */
    deleteBucket(userId: string): Promise<void>;
    /** Check storage health */
    healthCheck(): Promise<boolean>;
    /** Cleanup resources */
    cleanup(): Promise<void>;
    /**
     * Atomically refill and consume a token from the bucket.
     *
     * Implementations SHOULD perform the refill-and-consume in a single
     * atomic step (e.g. Lua script for Redis) to prevent race conditions
     * where parallel requests read the same token count and both succeed.
     *
     * The default in-memory implementation is inherently single-threaded,
     * so atomicity comes for free.
     *
     * @returns null when no bucket exists yet (caller should create one)
     */
    atomicConsume?(userId: string, limit: number, windowMs: number, nowMs: number): Promise<AtomicConsumeResult | null>;
}
/**
 * In-memory storage for rate limiting (single instance deployments)
 */
export declare class MemoryRateLimitStorage implements RateLimitStorage {
    private buckets;
    private cleanupInterval?;
    private expiryMs;
    constructor(cleanupIntervalMs?: number, expiryMs?: number);
    getBucket(userId: string): Promise<TokenBucket | null>;
    setBucket(userId: string, bucket: TokenBucket): Promise<void>;
    deleteBucket(userId: string): Promise<void>;
    healthCheck(): Promise<boolean>;
    cleanup(): Promise<void>;
    private cleanupExpiredBuckets;
}
/**
 * Redis-backed storage for rate limiting (distributed deployments)
 */
export declare class RedisRateLimitStorage implements RateLimitStorage {
    private redisUrl;
    private prefix;
    private ttlSeconds;
    private client;
    private initPromise;
    constructor(config: {
        url: string;
        prefix?: string;
        ttlSeconds?: number;
        /** When set, TTL will be at least ceil(windowMs/1000) so keys outlive the rate-limit window. */
        windowMs?: number;
    });
    private getClient;
    private createClient;
    getBucket(userId: string): Promise<TokenBucket | null>;
    setBucket(userId: string, bucket: TokenBucket): Promise<void>;
    deleteBucket(userId: string): Promise<void>;
    /**
     * Atomically refill and consume one token using a Redis Lua script.
     *
     * The entire read-modify-write cycle runs inside Redis as a single
     * atomic operation, so two parallel requests for the same user can
     * never read the same token count.
     */
    atomicConsume(userId: string, limit: number, windowMs: number, nowMs: number): Promise<AtomicConsumeResult | null>;
    healthCheck(): Promise<boolean>;
    cleanup(): Promise<void>;
}
/**
 * Token bucket rate limiter implementation
 *
 * Uses the token bucket algorithm which allows for burst traffic while
 * maintaining an average rate limit. Tokens are continuously added to
 * the bucket at a fixed rate, and each request consumes one token.
 */
export declare class UserRateLimiter {
    private storage;
    private config;
    constructor(config: RateLimitConfig, storage?: RateLimitStorage);
    /**
     * Get the rate limit for a specific user based on their roles
     */
    private getLimitForUser;
    /**
     * Check if a user should skip rate limiting (based on roles)
     */
    private shouldSkipRateLimit;
    /**
     * Consume a token from the user's bucket
     * Returns the rate limit result
     *
     * When the storage backend supports `atomicConsume` (e.g. Redis with Lua),
     * the entire refill-and-consume is executed as a single atomic operation,
     * preventing race conditions where parallel requests both read the same
     * token count and both succeed.
     */
    consume(user: AuthUser): Promise<RateLimitResult>;
    /**
     * Get current rate limit status for a user without consuming a token
     */
    getStatus(user: AuthUser): Promise<RateLimitResult>;
    /**
     * Reset rate limit for a user (admin action)
     */
    resetUser(userId: string): Promise<void>;
    /**
     * Check storage health
     */
    healthCheck(): Promise<boolean>;
    /**
     * Cleanup resources
     */
    cleanup(): Promise<void>;
}
/**
 * Middleware result type
 */
export type RateLimitMiddlewareResult = {
    /** Whether to proceed with the request */
    proceed: boolean;
    /** Rate limit result */
    rateLimitResult: RateLimitResult;
    /** Error response if rate limited */
    response?: Response;
};
/**
 * Create rate limiting middleware for authenticated requests
 *
 * @param config - Rate limit configuration
 * @param storage - Optional custom storage backend
 * @returns Middleware function
 *
 * @example
 * ```typescript
 * const rateLimitMiddleware = createRateLimitByUserMiddleware({
 *   maxRequests: 100,
 *   windowMs: 60000, // 1 minute
 *   roleLimits: {
 *     "premium": 500,
 *     "admin": 1000
 *   },
 *   skipRoles: ["super-admin"]
 * });
 *
 * // Use in server
 * app.use(async (request, context) => {
 *   const result = await rateLimitMiddleware(context);
 *   if (!result.proceed) {
 *     return result.response;
 *   }
 *   // Continue processing...
 * });
 * ```
 */
export declare function createRateLimitByUserMiddleware(config: RateLimitConfig, storage?: RateLimitStorage): (context: AuthenticatedContext) => Promise<RateLimitMiddlewareResult>;
/**
 * Create a combined auth and rate limit middleware
 *
 * @param authMiddleware - Authentication middleware function
 * @param rateLimitConfig - Rate limit configuration
 * @param storage - Optional custom storage backend
 * @returns Combined middleware function
 *
 * @example
 * ```typescript
 * const protectedRoute = createAuthenticatedRateLimitMiddleware(
 *   createAuthMiddleware({ provider: authProvider }),
 *   { maxRequests: 100, windowMs: 60000 }
 * );
 *
 * // Use in routes
 * app.post("/api/generate", async (request) => {
 *   const result = await protectedRoute(request);
 *   if (!result.proceed) {
 *     return result.response;
 *   }
 *   // Handle request with result.context
 * });
 * ```
 */
export declare function createAuthenticatedRateLimitMiddleware(authMiddleware: (context: AuthRequestContext) => Promise<{
    proceed: boolean;
    context?: AuthenticatedContext;
    response?: Response;
}>, rateLimitConfig: RateLimitConfig, storage?: RateLimitStorage): (context: AuthRequestContext) => Promise<{
    proceed: boolean;
    context?: AuthenticatedContext;
    rateLimitResult?: RateLimitResult;
    response?: Response;
}>;
/**
 * Create rate limit storage based on configuration
 *
 * @param config - Storage configuration
 * @returns Appropriate storage backend
 *
 * @example
 * ```typescript
 * // Memory storage (default)
 * const storage = createRateLimitStorage({ type: "memory" });
 *
 * // Redis storage
 * const storage = createRateLimitStorage({
 *   type: "redis",
 *   redis: {
 *     url: "redis://localhost:6379",
 *     prefix: "myapp:ratelimit:"
 *   }
 * });
 * ```
 */
export declare function createRateLimitStorage(config: {
    type: "memory" | "redis";
    redis?: {
        url: string;
        prefix?: string;
        ttlSeconds?: number;
        windowMs?: number;
    };
    cleanupIntervalMs?: number;
}): RateLimitStorage;
export {};
