using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.IO;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Excititor.Core;
using StellaOps.Excititor.Formats.CSAF;

namespace StellaOps.Excititor.Formats.CSAF.Tests;

public sealed class CsafNormalizerTests
{
    [Fact]
    public async Task NormalizeAsync_ProducesClaimsPerProductStatus()
    {
        var json = """
        {
          "document": {
            "tracking": {
              "id": "RHSA-2025:0001",
              "version": "3",
              "revision": "3",
              "status": "final",
              "initial_release_date": "2025-10-01T00:00:00Z",
              "current_release_date": "2025-10-10T00:00:00Z"
            },
            "publisher": {
              "name": "Red Hat Product Security",
              "category": "vendor"
            }
          },
          "product_tree": {
            "full_product_names": [
              {
                "product_id": "CSAFPID-0001",
                "name": "Red Hat Enterprise Linux 9",
                "product_identification_helper": {
                  "cpe": "cpe:/o:redhat:enterprise_linux:9",
                  "purl": "pkg:rpm/redhat/enterprise-linux@9"
                }
              }
            ]
          },
          "vulnerabilities": [
            {
              "cve": "CVE-2025-0001",
              "title": "Kernel vulnerability",
              "product_status": {
                "known_affected": [ "CSAFPID-0001" ]
              }
            },
            {
              "id": "VEX-0002",
              "title": "Library issue",
              "product_status": {
                "known_not_affected": [ "CSAFPID-0001" ]
              }
            }
          ]
        }
        """;

        var rawDocument = new VexRawDocument(
            ProviderId: "excititor:redhat",
            VexDocumentFormat.Csaf,
            new Uri("https://example.com/csaf/rhsa-2025-0001.json"),
            new DateTimeOffset(2025, 10, 11, 0, 0, 0, TimeSpan.Zero),
            "sha256:dummydigest",
            Encoding.UTF8.GetBytes(json),
            ImmutableDictionary<string, string>.Empty);

        var provider = new VexProvider("excititor:redhat", "Red Hat CSAF", VexProviderKind.Distro);
        var normalizer = new CsafNormalizer(NullLogger<CsafNormalizer>.Instance);

        var batch = await normalizer.NormalizeAsync(rawDocument, provider, CancellationToken.None);

        batch.Claims.Should().HaveCount(2);

        var affectedClaim = batch.Claims.First(c => c.VulnerabilityId == "CVE-2025-0001");
        affectedClaim.Status.Should().Be(VexClaimStatus.Affected);
        affectedClaim.Product.Key.Should().Be("CSAFPID-0001");
        affectedClaim.Product.Purl.Should().Be("pkg:rpm/redhat/enterprise-linux@9");
        affectedClaim.Product.Cpe.Should().Be("cpe:/o:redhat:enterprise_linux:9");
        affectedClaim.Document.Revision.Should().Be("3");
        affectedClaim.FirstSeen.Should().Be(new DateTimeOffset(2025, 10, 1, 0, 0, 0, TimeSpan.Zero));
        affectedClaim.LastSeen.Should().Be(new DateTimeOffset(2025, 10, 10, 0, 0, 0, TimeSpan.Zero));
        affectedClaim.AdditionalMetadata.Should().ContainKey("csaf.tracking.id");
        affectedClaim.AdditionalMetadata["csaf.publisher.name"].Should().Be("Red Hat Product Security");

        var notAffectedClaim = batch.Claims.First(c => c.VulnerabilityId == "VEX-0002");
        notAffectedClaim.Status.Should().Be(VexClaimStatus.NotAffected);
    }

    [Fact]
    public async Task NormalizeAsync_PreservesRedHatSpecificMetadata()
    {
        var path = Path.Combine(AppContext.BaseDirectory, "Fixtures", "rhsa-sample.json");
        var json = await File.ReadAllTextAsync(path);

        var rawDocument = new VexRawDocument(
            ProviderId: "excititor:redhat",
            VexDocumentFormat.Csaf,
            new Uri("https://security.example.com/rhsa-2025-1001.json"),
            new DateTimeOffset(2025, 10, 6, 0, 0, 0, TimeSpan.Zero),
            "sha256:rhdadigest",
            Encoding.UTF8.GetBytes(json),
            ImmutableDictionary<string, string>.Empty);

        var provider = new VexProvider("excititor:redhat", "Red Hat CSAF", VexProviderKind.Distro);
        var normalizer = new CsafNormalizer(NullLogger<CsafNormalizer>.Instance);

        var batch = await normalizer.NormalizeAsync(rawDocument, provider, CancellationToken.None);
        batch.Claims.Should().ContainSingle();

        var claim = batch.Claims[0];
        claim.VulnerabilityId.Should().Be("CVE-2025-1234");
        claim.Status.Should().Be(VexClaimStatus.Affected);
        claim.Product.Key.Should().Be("rh-enterprise-linux-9");
        claim.Product.Name.Should().Be("Red Hat Enterprise Linux 9");
        claim.Product.Purl.Should().Be("pkg:rpm/redhat/enterprise-linux@9");
        claim.Product.Cpe.Should().Be("cpe:/o:redhat:enterprise_linux:9");
        claim.FirstSeen.Should().Be(new DateTimeOffset(2025, 10, 1, 12, 0, 0, TimeSpan.Zero));
        claim.LastSeen.Should().Be(new DateTimeOffset(2025, 10, 5, 10, 0, 0, TimeSpan.Zero));

        claim.AdditionalMetadata.Should().ContainKey("csaf.tracking.id");
        claim.AdditionalMetadata["csaf.tracking.id"].Should().Be("RHSA-2025:1001");
        claim.AdditionalMetadata["csaf.tracking.status"].Should().Be("final");
        claim.AdditionalMetadata["csaf.publisher.name"].Should().Be("Red Hat Product Security");
    }
}
