using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
using MongoDB.Driver;
using StellaOps.Feedser.Storage.Mongo;
using StellaOps.Feedser.Storage.Mongo.Aliases;

namespace StellaOps.Feedser.Storage.Mongo.Tests;

[Collection("mongo-fixture")]
public sealed class AliasStoreTests : IClassFixture<MongoIntegrationFixture>
{
    private readonly MongoIntegrationFixture _fixture;

    public AliasStoreTests(MongoIntegrationFixture fixture)
    {
        _fixture = fixture;
    }

    [Fact]
    public async Task ReplaceAsync_UpsertsAliases_AndDetectsCollision()
    {
        await DropAliasCollectionAsync();
        var store = new AliasStore(_fixture.Database, NullLogger<AliasStore>.Instance);

        var timestamp = DateTimeOffset.UtcNow;
        await store.ReplaceAsync(
            "ADV-1",
            new[] { new AliasEntry("CVE", "CVE-2025-1234"), new AliasEntry(AliasStoreConstants.PrimaryScheme, "ADV-1") },
            timestamp,
            CancellationToken.None);

        var firstAliases = await store.GetByAdvisoryAsync("ADV-1", CancellationToken.None);
        Assert.Contains(firstAliases, record => record.Scheme == "CVE" && record.Value == "CVE-2025-1234");

        var result = await store.ReplaceAsync(
            "ADV-2",
            new[] { new AliasEntry("CVE", "CVE-2025-1234"), new AliasEntry(AliasStoreConstants.PrimaryScheme, "ADV-2") },
            timestamp.AddMinutes(1),
            CancellationToken.None);

        Assert.NotEmpty(result.Collisions);
        var collision = Assert.Single(result.Collisions);
        Assert.Equal("CVE", collision.Scheme);
        Assert.Contains("ADV-1", collision.AdvisoryKeys);
        Assert.Contains("ADV-2", collision.AdvisoryKeys);
    }

    private async Task DropAliasCollectionAsync()
    {
        try
        {
            await _fixture.Database.DropCollectionAsync(MongoStorageDefaults.Collections.Alias);
        }
        catch (MongoDB.Driver.MongoCommandException ex) when (ex.CodeName == "NamespaceNotFound" || ex.Message.Contains("ns not found", StringComparison.OrdinalIgnoreCase))
        {
        }
    }
}
