using System;

namespace StellaOps.Feedser.Source.Kisa.Configuration;

public sealed class KisaOptions
{
    public const string HttpClientName = "feedser.source.kisa";

    /// <summary>
    /// Primary RSS feed for security advisories.
    /// </summary>
    public Uri FeedUri { get; set; } = new("https://knvd.krcert.or.kr/rss/securityInfo.do");

    /// <summary>
    /// Detail API endpoint template; `IDX` query parameter identifies the advisory.
    /// </summary>
    public Uri DetailApiUri { get; set; } = new("https://knvd.krcert.or.kr/rssDetailData.do");

    /// <summary>
    /// Optional HTML detail URI template for provenance.
    /// </summary>
    public Uri DetailPageUri { get; set; } = new("https://knvd.krcert.or.kr/detailDos.do");

    public TimeSpan RequestTimeout { get; set; } = TimeSpan.FromSeconds(30);

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

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

    public int MaxAdvisoriesPerFetch { get; set; } = 20;

    public int MaxKnownAdvisories { get; set; } = 256;

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

        if (DetailApiUri is null || !DetailApiUri.IsAbsoluteUri)
        {
            throw new InvalidOperationException("KISA detail API URI must be an absolute URI.");
        }

        if (DetailPageUri is null || !DetailPageUri.IsAbsoluteUri)
        {
            throw new InvalidOperationException("KISA detail page URI must be an absolute URI.");
        }

        if (RequestTimeout <= TimeSpan.Zero)
        {
            throw new InvalidOperationException("RequestTimeout must be positive.");
        }

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

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

        if (MaxAdvisoriesPerFetch <= 0)
        {
            throw new InvalidOperationException("MaxAdvisoriesPerFetch must be greater than zero.");
        }

        if (MaxKnownAdvisories <= 0)
        {
            throw new InvalidOperationException("MaxKnownAdvisories must be greater than zero.");
        }
    }

    public Uri BuildDetailApiUri(string idx)
    {
        if (string.IsNullOrWhiteSpace(idx))
        {
            throw new ArgumentException("IDX must not be empty", nameof(idx));
        }

        var builder = new UriBuilder(DetailApiUri);
        var queryPrefix = string.IsNullOrEmpty(builder.Query) ? string.Empty : builder.Query.TrimStart('?') + "&";
        builder.Query = $"{queryPrefix}IDX={Uri.EscapeDataString(idx)}";
        return builder.Uri;
    }

    public Uri BuildDetailPageUri(string idx)
    {
        var builder = new UriBuilder(DetailPageUri);
        var queryPrefix = string.IsNullOrEmpty(builder.Query) ? string.Empty : builder.Query.TrimStart('?') + "&";
        builder.Query = $"{queryPrefix}IDX={Uri.EscapeDataString(idx)}";
        return builder.Uri;
    }
}
