using Microsoft.SharePoint.Client;
using SharepointToolbox.Core.Models;

namespace SharepointToolbox.Core.Helpers;

public static class ExecuteQueryRetryHelper
{
    private const int MaxRetries = 5;

    /// <summary>
    /// Executes a SharePoint query with automatic retry on throttle (429/503).
    /// Surfaces retry events via progress for user visibility ("Throttled — retrying in 30s…").
    /// </summary>
    public static async Task ExecuteQueryRetryAsync(
        ClientContext ctx,
        IProgress<OperationProgress>? progress = null,
        CancellationToken ct = default)
    {
        int attempt = 0;
        while (true)
        {
            ct.ThrowIfCancellationRequested();
            try
            {
                await ctx.ExecuteQueryAsync();
                return;
            }
            catch (Exception ex) when (IsThrottleException(ex) && attempt < MaxRetries)
            {
                attempt++;
                int delaySeconds = (int)Math.Pow(2, attempt) * 5; // 10, 20, 40, 80, 160s
                progress?.Report(OperationProgress.Indeterminate(
                    $"Throttled by SharePoint — retrying in {delaySeconds}s (attempt {attempt}/{MaxRetries})…"));
                await Task.Delay(TimeSpan.FromSeconds(delaySeconds), ct);
            }
        }
    }

    internal static bool IsThrottleException(Exception ex)
    {
        var msg = ex.Message;
        return msg.Contains("429") || msg.Contains("503") ||
               msg.Contains("throttl", StringComparison.OrdinalIgnoreCase);
    }
}
