using System.Threading;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;

namespace StellaOps.Vexer.Storage.Mongo;

public static class VexMongoMappingRegistry
{
    private static int _initialized;

    public static void Register()
    {
        if (Interlocked.Exchange(ref _initialized, 1) == 1)
        {
            return;
        }

        try
        {
            BsonSerializer.RegisterSerializer(typeof(byte[]), new ByteArraySerializer());
        }
        catch
        {
            // serializer already registered – safe to ignore
        }

        RegisterClassMaps();
    }

    private static void RegisterClassMaps()
    {
        RegisterClassMap<VexProviderRecord>();
        RegisterClassMap<VexProviderDiscoveryDocument>();
        RegisterClassMap<VexProviderTrustDocument>();
        RegisterClassMap<VexCosignTrustDocument>();
        RegisterClassMap<VexConsensusRecord>();
        RegisterClassMap<VexProductDocument>();
        RegisterClassMap<VexConsensusSourceDocument>();
        RegisterClassMap<VexConsensusConflictDocument>();
        RegisterClassMap<VexConfidenceDocument>();
        RegisterClassMap<VexCacheEntryRecord>();
    }

    private static void RegisterClassMap<TDocument>()
        where TDocument : class
    {
        if (BsonClassMap.IsClassMapRegistered(typeof(TDocument)))
        {
            return;
        }

        BsonClassMap.RegisterClassMap<TDocument>(classMap =>
        {
            classMap.AutoMap();
            classMap.SetIgnoreExtraElements(true);
        });
    }
}

public static class VexMongoCollectionNames
{
    public const string Migrations = "vex.migrations";
    public const string Providers = "vex.providers";
    public const string Raw = "vex.raw";
    public const string Claims = "vex.claims";
    public const string Consensus = "vex.consensus";
    public const string Exports = "vex.exports";
    public const string Cache = "vex.cache";
}
