using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.SystemAlerts;
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>
/// Represents a contributor that provides entity mapping configuration for Alarm entities.
/// </summary>
/// <remarks>Implements the <see cref="IEntityMapContributor"/> interface to participate in the entity mapping process.</remarks>
public class AlarmMapContributor : IEntityMapContributor
{
    /// <summary>
    /// Registers BSON class maps for alarm-related domain types (including alarm configuration, audio, alarm items, patient observation alarms, inactivation states, sources, recording alerts, and performance), configuring enum serialization as strings, null-ignore behavior for optional members, default values where applicable, and unmapping members that should not be persisted. Registration is performed only when a class map for the type is not already registered, ensuring idempotent behavior.
    /// </summary>
    public void RegisterMaps()
        {
            if (!BsonClassMap.IsClassMapRegistered(typeof(AlarmConfig)))
                BsonClassMap.RegisterClassMap<AlarmConfig>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Enabled).SetDefaultValue(false);
                    cm.MapMember(c => c.EndAfter).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Recording).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Beacon).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.OpenDoor).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Priority).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Color).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.AudioConfig).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(AudioConfig)))
                BsonClassMap.RegisterClassMap<AudioConfig>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Type)
                        .SetDefaultValue(AlarmEnum.AudioAlarmType.Off)
                        .SetSerializer(new EnumSerializer<AlarmEnum.AudioAlarmType>(BsonType.String));
                    cm.MapMember(c => c.Path).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.EndAfter).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(AlarmItem)))
                BsonClassMap.RegisterClassMap<AlarmItem>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Enabled).SetDefaultValue(false);
                    cm.MapMember(c => c.StartBefore).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.EndAfter).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Color).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Severity)
                        .SetDefaultValue(AlarmEnum.Severity.None)
                        .SetSerializer(new EnumSerializer<AlarmEnum.Severity>(BsonType.String));
                    cm.MapMember(c => c.BeaconColor)
                        .SetDefaultValue(AlarmEnum.BeaconColor.None)
                        .SetSerializer(new EnumSerializer<AlarmEnum.BeaconColor>(BsonType.String));
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(PatientObservationAlarm)))
            {
                BsonClassMap.RegisterClassMap<PatientObservationAlarm>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.InactivationState).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.EventPhase)
                        .SetDefaultValue(AlarmEnum.EventPhase.Continue)
                        .SetSerializer(new EnumSerializer<AlarmEnum.EventPhase>(BsonType.String));
                    cm.MapMember(c => c.Event).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.EventId).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.State)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(new NullableSerializer<AlarmEnum.ObservationAlarmState>(
                            new EnumSerializer<AlarmEnum.ObservationAlarmState>(BsonType.String)));
                    cm.MapMember(c => c.Priority)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(new NullableSerializer<AlarmEnum.ObservationAlarmPriority>(
                            new EnumSerializer<AlarmEnum.ObservationAlarmPriority>(BsonType.String)));
                    cm.MapMember(c => c.PriorityLevel)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(new NullableSerializer<int>(new Int32Serializer()));
                    cm.UnmapMember(c => c.AlarmConfig);
                    cm.MapMember(c => c.Type)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(
                            new NullableSerializer<AlarmEnum.ObservationAlarmType>(
                                new EnumSerializer<AlarmEnum.ObservationAlarmType>(BsonType.String)));
                    cm.MapMember(c => c.AlertColor).SetIgnoreIfNull(true)
                        .SetSerializer(new StringSerializer(BsonType.String));
                    cm.UnmapMember(c => c.MessageTime);
                    cm.MapMember(c => c.Persist).SetIgnoreIfNull(true);
                    cm.UnmapMember(c => c.Expired);
                    cm.MapMember(c => c.Expires).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Sources).SetIgnoreIfNull(true);
                });
    
                BsonClassMap.RegisterClassMap<InactivationState>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Audio)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(
                            new NullableSerializer<AlarmEnum.AudioVideoState>(
                                new EnumSerializer<AlarmEnum.AudioVideoState>(BsonType.String)));
                    cm.MapMember(c => c.Visual)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(
                            new NullableSerializer<AlarmEnum.AudioVideoState>(
                                new EnumSerializer<AlarmEnum.AudioVideoState>(BsonType.String)));
                    cm.MapMember(c => c.Acknowledge).SetIgnoreIfNull(true);
                });
    
                BsonClassMap.RegisterClassMap<Source>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Code).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.OriginalName).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.CodeSystem).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Units).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Value).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Result).SetIgnoreIfNull(true);
                });
            }
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(PatientRecordingAlert)))
                BsonClassMap.RegisterClassMap<PatientRecordingAlert>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.IsRecording);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(Performance)))
                BsonClassMap.RegisterClassMap<Performance>(cm => { cm.AutoMap(); });
        }
}