using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;

namespace adas_core.Infrastructure.Utils.MongoMaps;

/// <summary>
/// Provides an entity map contributor that relays or forwards mapping contributions from an underlying source.
/// Implements the <see cref="IEntityMapContributor"/> contract to participate in entity mapping workflows.
/// </summary>
public class RelayContributor : IEntityMapContributor
{
    /// <summary>
    /// Registers the BSON class map for the <see cref="Relay"/> type, defining how its properties are serialized and stored in MongoDB. The registration is performed only when no class map is already registered for the type, and it configures default values, string-based enum serialization, and null-ignoring behavior for optional members.
    /// </summary>
    public void RegisterMaps()
        {
            if (!BsonClassMap.IsClassMapRegistered(typeof(Relay)))
                BsonClassMap.RegisterClassMap<Relay>(cm =>
                {
                    cm.AutoMap();
                    cm.MapIdMember(c => c.Id).SetElementName("_id");
                    cm.MapMember(c => c.Type)
                        .SetDefaultValue(RelayEnum.Type.Door)
                        .SetSerializer(new EnumSerializer<RelayEnum.Type>(BsonType.String));
                    cm.MapMember(c => c.Driver).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Ip).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Port).SetDefaultValue(0);
                    cm.MapMember(c => c.RelayNumber).SetDefaultValue(1);
                    cm.MapMember(c => c.RelayName).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Total).SetDefaultValue(1);
                    cm.MapMember(c => c.RefreshTime).SetDefaultValue(60);
                    cm.MapMember(c => c.Open).SetDefaultValue(false);
                    cm.MapMember(c => c.Status)
                        .SetDefaultValue(RelayEnum.Status.NotInitialized)
                        .SetSerializer(new EnumSerializer<RelayEnum.Status>(BsonType.String));
                    cm.MapMember(c => c.Username).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Password).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Mode)
                        .SetDefaultValue(RelayEnum.Mode.OpenedOnClosedOff)
                        .SetSerializer(new EnumSerializer<RelayEnum.Mode>(BsonType.String));
                    cm.MapMember(c => c.RebootDelay).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Cache).SetDefaultValue(true);
                    cm.MapMember(c => c.InUse).SetIgnoreIfNull(true).SetIsRequired(false);
                    cm.MapMember(c => c.ManualRelayStatus)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(
                            new NullableSerializer<RelayEnum.Status>(
                                new EnumSerializer<RelayEnum.Status>(BsonType.String)));
                });
        }
}