using System.Diagnostics.CodeAnalysis;

namespace StellaOps.Feedser.Source.Ghsa.Configuration;

public sealed class GhsaOptions
{
    public static string HttpClientName => "source.ghsa";

    public Uri BaseEndpoint { get; set; } = new("https://api.github.com/", UriKind.Absolute);

    public string ApiToken { get; set; } = string.Empty;

    public int PageSize { get; set; } = 50;

    public int MaxPagesPerFetch { get; set; } = 5;

    public TimeSpan InitialBackfill { get; set; } = TimeSpan.FromDays(30);

    public TimeSpan RequestDelay { get; set; } = TimeSpan.FromMilliseconds(200);

    public TimeSpan FailureBackoff { get; set; } = TimeSpan.FromMinutes(5);

    public int RateLimitWarningThreshold { get; set; } = 500;

    public TimeSpan SecondaryRateLimitBackoff { get; set; } = TimeSpan.FromMinutes(2);

    [MemberNotNull(nameof(BaseEndpoint), nameof(ApiToken))]
    public void Validate()
    {
        if (BaseEndpoint is null || !BaseEndpoint.IsAbsoluteUri)
        {
            throw new InvalidOperationException("BaseEndpoint must be an absolute URI.");
        }

        if (string.IsNullOrWhiteSpace(ApiToken))
        {
            throw new InvalidOperationException("ApiToken must be provided.");
        }

        if (PageSize is < 1 or > 100)
        {
            throw new InvalidOperationException("PageSize must be between 1 and 100.");
        }

        if (MaxPagesPerFetch <= 0)
        {
            throw new InvalidOperationException("MaxPagesPerFetch must be positive.");
        }

        if (InitialBackfill < TimeSpan.Zero)
        {
            throw new InvalidOperationException("InitialBackfill cannot be negative.");
        }

        if (RequestDelay < TimeSpan.Zero)
        {
            throw new InvalidOperationException("RequestDelay cannot be negative.");
        }

        if (FailureBackoff <= TimeSpan.Zero)
        {
            throw new InvalidOperationException("FailureBackoff must be greater than zero.");
        }

        if (RateLimitWarningThreshold < 0)
        {
            throw new InvalidOperationException("RateLimitWarningThreshold cannot be negative.");
        }

        if (SecondaryRateLimitBackoff <= TimeSpan.Zero)
        {
            throw new InvalidOperationException("SecondaryRateLimitBackoff must be greater than zero.");
        }
    }
}
