using Polly;
using Polly.CircuitBreaker;
using Polly.Retry;

namespace Kbx.Shared.Integrations;

// Polly is intentionally limited to short-lived transient resilience.
// Persistent retries are scheduled by Hangfire from durable integration state.
public sealed class KbxPollyIntegrationPipeline
{
    public ResiliencePipeline<KbxIntegrationAttemptResult> Build(
        int maxRetryAttempts,
        TimeSpan baseDelay,
        TimeSpan timeout,
        double failureRatio,
        TimeSpan samplingDuration,
        int minimumThroughput,
        TimeSpan breakDuration)
    {
        return new ResiliencePipelineBuilder<KbxIntegrationAttemptResult>()
            .AddCircuitBreaker(new CircuitBreakerStrategyOptions<KbxIntegrationAttemptResult>
            {
                ShouldHandle = static args => args.Outcome switch
                {
                    { Exception: HttpRequestException } => PredicateResult.True(),
                    { Result.FailureKind: KbxIntegrationFailureKind.Transient } => PredicateResult.True(),
                    _ => PredicateResult.False(),
                },
                FailureRatio = failureRatio,
                SamplingDuration = samplingDuration,
                MinimumThroughput = minimumThroughput,
                BreakDuration = breakDuration,
            })
            .AddRetry(new RetryStrategyOptions<KbxIntegrationAttemptResult>
            {
                ShouldHandle = static args => args.Outcome switch
                {
                    { Exception: HttpRequestException } => PredicateResult.True(),
                    { Result.FailureKind: KbxIntegrationFailureKind.Transient } => PredicateResult.True(),
                    _ => PredicateResult.False(),
                },
                MaxRetryAttempts = maxRetryAttempts,
                Delay = baseDelay,
                BackoffType = DelayBackoffType.Exponential,
                UseJitter = true,
            })
            .AddTimeout(timeout)
            .Build();
    }
}
