using System;
using System.Linq;

namespace StellaOps.Feedser.Source.Vndr.Msrc.Internal;

public sealed class MsrcDetailParser
{
    public MsrcAdvisoryDto Parse(MsrcVulnerabilityDetailDto detail)
    {
        ArgumentNullException.ThrowIfNull(detail);

        var advisoryId = string.IsNullOrWhiteSpace(detail.VulnerabilityId) ? detail.Id : detail.VulnerabilityId;
        var cveIds = detail.CveNumbers?.Where(static c => !string.IsNullOrWhiteSpace(c)).Select(static c => c.Trim()).ToArray()
            ?? (string.IsNullOrWhiteSpace(detail.CveNumber) ? Array.Empty<string>() : new[] { detail.CveNumber! });

        var kbIds = detail.Remediations?
            .Where(static remediation => !string.IsNullOrWhiteSpace(remediation.KbNumber))
            .Select(static remediation => remediation.KbNumber!.Trim())
            .Distinct(StringComparer.OrdinalIgnoreCase)
            .ToArray() ?? Array.Empty<string>();

        return new MsrcAdvisoryDto
        {
            AdvisoryId = advisoryId,
            Title = string.IsNullOrWhiteSpace(detail.Title) ? advisoryId : detail.Title.Trim(),
            Description = detail.Description,
            Severity = detail.Severity,
            ReleaseDate = detail.ReleaseDate,
            LastModifiedDate = detail.LastModifiedDate,
            CveIds = cveIds,
            KbIds = kbIds,
            Threats = detail.Threats?.Select(static threat => new MsrcAdvisoryThreat(
                threat.Type ?? "unspecified",
                threat.Description,
                threat.Severity)).ToArray() ?? Array.Empty<MsrcAdvisoryThreat>(),
            Remediations = detail.Remediations?.Select(static remediation => new MsrcAdvisoryRemediation(
                remediation.Type ?? "unspecified",
                remediation.Description,
                remediation.Url,
                remediation.KbNumber)).ToArray() ?? Array.Empty<MsrcAdvisoryRemediation>(),
            Products = detail.AffectedProducts?.Select(product =>
                new MsrcAdvisoryProduct(
                    BuildProductIdentifier(product),
                    product.ProductName,
                    product.Platform,
                    product.Architecture,
                    product.BuildNumber,
                    product.Cpe)).ToArray() ?? Array.Empty<MsrcAdvisoryProduct>(),
            CvssBaseScore = detail.Cvss?.BaseScore,
            CvssVector = detail.Cvss?.VectorString,
            ReleaseNoteUrl = detail.ReleaseNoteUrl,
            CvrfUrl = detail.CvrfUrl,
        };
    }

    private static string BuildProductIdentifier(MsrcAffectedProductDto product)
    {
        var name = string.IsNullOrWhiteSpace(product.ProductName) ? product.ProductId : product.ProductName;
        if (string.IsNullOrWhiteSpace(name))
        {
            name = "Unknown Product";
        }

        if (!string.IsNullOrWhiteSpace(product.BuildNumber))
        {
            return $"{name} build {product.BuildNumber}";
        }

        return name;
    }
}
