using System.Collections.Immutable;
using MongoDB.Bson;
using StellaOps.Feedser.Source.Common;
using StellaOps.Feedser.Models;
using StellaOps.Feedser.Source.Ru.Nkcki.Internal;
using StellaOps.Feedser.Storage.Mongo.Documents;
using Xunit;
using System.Reflection;

namespace StellaOps.Feedser.Source.Ru.Nkcki.Tests;

public sealed class RuNkckiMapperTests
{
    [Fact]
    public void Map_ConstructsCanonicalAdvisory()
    {
        var softwareEntries = ImmutableArray.Create(
            new RuNkckiSoftwareEntry(
                "SampleVendor SampleSCADA",
                "SampleVendor SampleSCADA <= 4.2",
                ImmutableArray.Create("<= 4.2")));

        var dto = new RuNkckiVulnerabilityDto(
            FstecId: "BDU:2025-00001",
            MitreId: "CVE-2025-0001",
            DatePublished: new DateTimeOffset(2025, 9, 1, 0, 0, 0, TimeSpan.Zero),
            DateUpdated: new DateTimeOffset(2025, 9, 2, 0, 0, 0, TimeSpan.Zero),
            CvssRating: "КРИТИЧЕСКИЙ",
            PatchAvailable: true,
            Description: "Test NKCKI vulnerability",
            Cwe: new RuNkckiCweDto(79, "Cross-site scripting"),
            ProductCategories: ImmutableArray.Create("ICS", "Automation"),
            Mitigation: "Apply update",
            VulnerableSoftwareText: null,
            VulnerableSoftwareHasCpe: false,
            VulnerableSoftwareEntries: softwareEntries,
            CvssScore: 8.8,
            CvssVector: "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
            CvssScoreV4: 6.4,
            CvssVectorV4: "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H",
            Impact: "ACE",
            MethodOfExploitation: "Special request",
            UserInteraction: false,
            Urls: ImmutableArray.Create("https://example.com/advisory", "https://cert.gov.ru/materialy/uyazvimosti/2025-00001"),
            Tags: ImmutableArray.Create("ics"));

        var document = new DocumentRecord(
            Guid.NewGuid(),
            RuNkckiConnectorPlugin.SourceName,
            "https://cert.gov.ru/materialy/uyazvimosti/2025-00001",
            DateTimeOffset.UtcNow,
            "abc",
            DocumentStatuses.PendingMap,
            "application/json",
            null,
            null,
            null,
            dto.DateUpdated,
            ObjectId.GenerateNewId());

        Assert.Equal("КРИТИЧЕСКИЙ", dto.CvssRating);
        var normalizeSeverity = typeof(RuNkckiMapper).GetMethod("NormalizeSeverity", BindingFlags.NonPublic | BindingFlags.Static)!;
        var ratingSeverity = (string?)normalizeSeverity.Invoke(null, new object?[] { dto.CvssRating });
        Assert.Equal("critical", ratingSeverity);

        var advisory = RuNkckiMapper.Map(dto, document, dto.DateUpdated!.Value);

        Assert.Contains("BDU:2025-00001", advisory.Aliases);
        Assert.Contains("CVE-2025-0001", advisory.Aliases);
        Assert.Equal("critical", advisory.Severity);
        Assert.True(advisory.ExploitKnown);
        Assert.Single(advisory.AffectedPackages);
        var package = advisory.AffectedPackages[0];
        Assert.Equal(AffectedPackageTypes.IcsVendor, package.Type);
        Assert.Single(package.NormalizedVersions);
        Assert.Equal(2, advisory.CvssMetrics.Length);
        Assert.Contains(advisory.CvssMetrics, metric => metric.Version == "4.0");
        Assert.Equal("critical", advisory.Severity);
        Assert.Contains(advisory.References, reference => reference.Url.Contains("example.com", StringComparison.OrdinalIgnoreCase));
    }
}
