using SatelliteProvider.Common.Exceptions;

namespace SatelliteProvider.Services.RegionProcessing;

internal enum RegionFailureCategory
{
    Timeout,
    ExternalCancellation,
    TaskCanceledOther,
    OperationCanceledOther,
    RateLimit,
    Network,
    Unexpected,
}

internal sealed record RegionFailureClassification(RegionFailureCategory Category, string ErrorMessage);

internal static class RegionFailureClassifier
{
    public const string TimeoutMessage =
        "Processing timed out after 5 minutes. Unable to download tiles within the time limit.";

    public const string ExternalCancellationMessage =
        "Processing was cancelled externally (likely application shutdown).";

    public static RegionFailureClassification Classify(
        Exception ex,
        CancellationTokenSource timeoutCts,
        CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(ex);
        ArgumentNullException.ThrowIfNull(timeoutCts);

        return ex switch
        {
            TaskCanceledException when timeoutCts.IsCancellationRequested
                => new RegionFailureClassification(RegionFailureCategory.Timeout, TimeoutMessage),

            TaskCanceledException when cancellationToken.IsCancellationRequested
                => new RegionFailureClassification(RegionFailureCategory.ExternalCancellation, ExternalCancellationMessage),

            TaskCanceledException
                => new RegionFailureClassification(
                    RegionFailureCategory.TaskCanceledOther,
                    $"Request cancelled or timed out: {ex.Message}. This may indicate HttpClient timeout or network issues."),

            OperationCanceledException when timeoutCts.IsCancellationRequested
                => new RegionFailureClassification(RegionFailureCategory.Timeout, TimeoutMessage),

            OperationCanceledException
                => new RegionFailureClassification(
                    RegionFailureCategory.OperationCanceledOther,
                    $"Operation cancelled: {ex.Message}"),

            RateLimitException
                => new RegionFailureClassification(
                    RegionFailureCategory.RateLimit,
                    $"Rate limit exceeded: {ex.Message}. Google Maps API rate limit was reached and retries were exhausted."),

            HttpRequestException httpEx
                => new RegionFailureClassification(
                    RegionFailureCategory.Network,
                    $"Network error (HTTP {httpEx.StatusCode}): {httpEx.Message}. Failed to download tiles from Google Maps."),

            _ => new RegionFailureClassification(
                RegionFailureCategory.Unexpected,
                $"Unexpected error ({ex.GetType().Name}): {ex.Message}"),
        };
    }
}
