using Knot.Contracts.Messaging.Domain;
using Knot.Shared.Kernel;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;

namespace Knot.Modules.Messaging.Infrastructure.Persistence.Mongo;

public static class MongoDbMapConfigurator
{
    private static bool _initialized;

    public static void Configure()
    {
        if (_initialized) return;

        try { BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard)); } catch { /* Already registered */ }

        BsonSerializer.RegisterSerializer(new EnumSerializer<MessageState>(BsonType.Int32));
        BsonSerializer.RegisterSerializer(new EnumSerializer<MediaType>(BsonType.String));

        BsonClassMap.RegisterClassMap<Entity<Guid>>(cm =>
        {
            cm.AutoMap();
            cm.MapIdProperty(e => e.Id);
        });

        BsonClassMap.RegisterClassMap<Message>(cm =>
        {
            cm.AutoMap();
            cm.MapField("_deletedFor").SetElementName("DeletedFor");
            cm.MapProperty(c => c.Content).SetSerializer(new EncryptedStringSerializer());
            cm.SetIgnoreExtraElements(true);
            cm.SetIsRootClass(true);
        });

        BsonClassMap.RegisterClassMap<TextMessage>(cm =>
        {
            cm.AutoMap();
            cm.MapProperty(c => c.Quote).SetSerializer(new EncryptedStringSerializer());
            cm.SetIgnoreExtraElements(true);
            cm.SetDiscriminator("TextMessage");
        });

        BsonClassMap.RegisterClassMap<MediaMessage>(cm =>
        {
            cm.AutoMap();
            cm.MapField("_media").SetElementName("Media");
            cm.SetIgnoreExtraElements(true);
            cm.SetDiscriminator("MediaMessage");
            cm.UnmapProperty(c => c.Caption);
        });

        BsonClassMap.RegisterClassMap<StoryMessage>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);
            cm.SetDiscriminator("StoryMessage");
            cm.MapProperty(c => c.StoryMediaUrl).SetSerializer(new EncryptedStringSerializer());
        });

        BsonClassMap.RegisterClassMap<DeletedMessage>(cm => cm.AutoMap());
        BsonClassMap.RegisterClassMap<MessageReaction>(cm => cm.AutoMap());

        BsonClassMap.RegisterClassMap<PollMessage>(cm =>
        {
            cm.AutoMap();
            cm.MapProperty(c => c.Options).SetElementName("_options");
            cm.MapProperty(c => c.Votes).SetElementName("_votes");
            cm.SetIgnoreExtraElements(true);
            cm.SetDiscriminator("PollMessage");
        });

        BsonClassMap.RegisterClassMap<CallMessage>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);
            cm.SetDiscriminator("CallMessage");
        });

        BsonClassMap.RegisterClassMap<PollOption>(cm => cm.AutoMap());
        BsonClassMap.RegisterClassMap<PollVote>(cm => cm.AutoMap());


        BsonClassMap.RegisterClassMap<Media>(cm =>
        {
            cm.AutoMap();
            cm.MapProperty(c => c.Url).SetSerializer(new EncryptedStringSerializer());
            cm.MapProperty(c => c.Filename).SetSerializer(new EncryptedStringSerializer());
        });

        _initialized = true;
    }
}



