using System;
using StellaOps.Feedser.Source.Common.Cursors;

namespace StellaOps.Feedser.Source.CertCc.Configuration;

/// <summary>
/// Connector options governing CERT/CC fetch cadence and API endpoints.
/// </summary>
public sealed class CertCcOptions
{
    public const string HttpClientName = "certcc";

    /// <summary>
    /// Root URI for the VINCE Vulnerability Notes API (must end with a slash).
    /// </summary>
    public Uri BaseApiUri { get; set; } = new("https://www.kb.cert.org/vuls/api/", UriKind.Absolute);

    /// <summary>
    /// Sliding window settings controlling which summary endpoints are requested.
    /// </summary>
    public TimeWindowCursorOptions SummaryWindow { get; set; } = new()
    {
        WindowSize = TimeSpan.FromDays(30),
        Overlap = TimeSpan.FromDays(3),
        InitialBackfill = TimeSpan.FromDays(365),
        MinimumWindowSize = TimeSpan.FromDays(1),
    };

    /// <summary>
    /// Maximum number of monthly summary endpoints to request in a single plan.
    /// </summary>
    public int MaxMonthlySummaries { get; set; } = 6;

    /// <summary>
    /// Maximum number of vulnerability notes (detail bundles) to process per fetch pass.
    /// </summary>
    public int MaxNotesPerFetch { get; set; } = 25;

    /// <summary>
    /// Optional delay inserted between successive detail requests to respect upstream throttling.
    /// </summary>
    public TimeSpan DetailRequestDelay { get; set; } = TimeSpan.FromMilliseconds(100);

    /// <summary>
    /// When disabled, parse/map stages skip detail mapping—useful for dry runs or migration staging.
    /// </summary>
    public bool EnableDetailMapping { get; set; } = true;

    public void Validate()
    {
        if (BaseApiUri is null || !BaseApiUri.IsAbsoluteUri)
        {
            throw new InvalidOperationException("CertCcOptions.BaseApiUri must be an absolute URI.");
        }

        if (!BaseApiUri.AbsoluteUri.EndsWith("/", StringComparison.Ordinal))
        {
            throw new InvalidOperationException("CertCcOptions.BaseApiUri must end with a trailing slash.");
        }

        SummaryWindow ??= new TimeWindowCursorOptions();
        SummaryWindow.EnsureValid();

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

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

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