import Foundation

public struct ReconnectPolicy: Sendable {
    public let maxAttempts: Int
    public let baseDelaySeconds: Double
    public let maxDelaySeconds: Double
    public let jitterFraction: Double

    public init(
        maxAttempts: Int = 6,
        baseDelaySeconds: Double = 1.0,
        maxDelaySeconds: Double = 30.0,
        jitterFraction: Double = 0.25
    ) {
        self.maxAttempts = maxAttempts
        self.baseDelaySeconds = baseDelaySeconds
        self.maxDelaySeconds = maxDelaySeconds
        self.jitterFraction = jitterFraction
    }

    public static let `default` = ReconnectPolicy()
    public static let none = ReconnectPolicy(maxAttempts: 0)

    public func shouldReconnect(for reason: DisconnectReason) -> Bool {
        guard maxAttempts > 0 else { return false }
        switch reason {
        case .userRequested, .authenticationFailed:
            return false
        case .networkError, .protocolError, .remoteClosed:
            return true
        }
    }

    public func delay(for attempt: Int) -> Double? {
        guard attempt > 0, attempt <= maxAttempts else { return nil }
        let exponential = baseDelaySeconds * pow(2.0, Double(attempt - 1))
        let capped = min(exponential, maxDelaySeconds)
        let jitter = capped * jitterFraction
        let lower = max(0, capped - jitter)
        let upper = capped + jitter
        return Double.random(in: lower...upper)
    }
}
