using adas_core.Domain.Enums;
using adas_core.Domain.Models.GroupedObservations;
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>
/// Represents a contributor responsible for providing display-related mapping logic for entities.
/// </summary>
/// <remarks>
/// Implements the <see cref="IEntityMapContributor"/> interface to participate in the entity mapping pipeline for display scenarios.
/// </remarks>
public class DisplayMapContributor : IEntityMapContributor
{
    /// <summary>
    /// Registers BSON class maps for display-related types (Display, DisplayNurse, StandarDisplay, SmartDisplay, PumpDisplay, DisplayConfig, and GroupedField) used for MongoDB serialization.
    /// </summary>
    /// <remarks>Configures polymorphic deserialization for DisplayConfig by declaring its known subtypes, sets custom element names for identifiers, applies default values for enum and collection members, omits null or unmapped properties, and uses string-based enum serialization where applicable. Each registration is guarded so it only occurs when the corresponding class map has not already been registered.</remarks>
    public void RegisterMaps()
        {
            if (!BsonClassMap.IsClassMapRegistered(typeof(Display)))
                BsonClassMap.RegisterClassMap<Display>(cm =>
                {
                    cm.AutoMap();
                    cm.MapIdMember(c => c.Id).SetElementName("_id");
                    cm.UnmapProperty(c => c.Unit);
                    cm.UnmapProperty(c => c.PointOfCares);
                    cm.UnmapProperty(c => c.DisplayConfig);
                    cm.MapMember(c => c.Type)
                        .SetDefaultValue(DisplayConfigEnums.DisplayType.Unknown)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.DisplayType>(BsonType.String));
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(DisplayNurse)))
                BsonClassMap.RegisterClassMap<DisplayNurse>(cm =>
                {
                    cm.AutoMap();
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(StandarDisplay)))
                BsonClassMap.RegisterClassMap<StandarDisplay>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.SectionConfig).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(SmartDisplay)))
                BsonClassMap.RegisterClassMap<SmartDisplay>(cm =>
                {
                    cm.AutoMap();
                    
                });
            
            if (!BsonClassMap.IsClassMapRegistered(typeof(PumpDisplay)))
                BsonClassMap.RegisterClassMap<PumpDisplay>(cm =>
                {
                    cm.AutoMap();
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(DisplayConfig)))
            {
                BsonClassMap.RegisterClassMap<DisplayConfig>(cm =>
                {
                    cm.AutoMap();
                    cm.AddKnownType(typeof(DisplayNurse));
                    cm.AddKnownType(typeof(StandarDisplay));
                    cm.AddKnownType(typeof(SmartDisplay));
                    cm.AddKnownType(typeof(PumpDisplay));
                    cm.MapIdMember(c => c.Id).SetElementName("_id");
                    cm.MapMember(c => c.Type)
                        .SetDefaultValue(DisplayConfigEnums.DisplayType.Unknown)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.DisplayType>(BsonType.String));
                    cm.MapMember(c => c.MediaFolder).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.CardConfigId).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.CardConfig)
                        .SetIgnoreIfNull(true)
                        .SetIsRequired(false);
                    cm.MapMember(c => c.DetailConfigId).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.DetailConfig)
                        .SetIgnoreIfNull(true)
                        .SetIsRequired(false);
                    cm.MapMember(c => c.HomeBanner).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.FormConfig)
                        .SetDefaultValue(new FormConfig
                        {
                            Admission = new FormItemOverview { Nhc = true },
                            Demographic = new FormItemOverview { Nhc = true },
                            Discharge = new FormItemOverview { Nhc = true },
                            IncomeInfo = new FormItemOverview { Nhc = true }
                        });
                    cm.MapMember(c => c.HasCameras).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.HasSound).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.IsRotationEnabled).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.CanChangeCameraMode).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.CamerasAreActive).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.CameraStreamType).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.SensorList).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ObservationForIndicator).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.AlarmFieldList).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.RequestGroupedFieldList).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Pumps).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ChartConfig).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.GraphLayout).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.CardRotatingLayout).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ChartConfigIdList).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.HomeConfig).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.HeaderConfig).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.DisplaySectionIdList).SetDefaultValue(new List<ObjectId>());
                    cm.MapMember(c => c.Hospital).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ColorConfig).SetDefaultValue(new ColorConfig());
                    cm.MapMember(c => c.FieldList).SetDefaultValue(new List<Field>());
                    cm.MapMember(c => c.GroupedFieldList).SetDefaultValue(new List<GroupedField>());
    
                    cm.UnmapProperty(c => c.DisplaySectionList);
                    // cm.UnmapProperty(c => c.CardConfig);
                });
    
                BsonClassMap.RegisterClassMap<GroupedField>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Names).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Group).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.StartTimeShift).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Max);
                    cm.MapMember(c => c.Regularity)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(new NullableSerializer<GroupedObservationEnum.Regularity>(
                            new EnumSerializer<GroupedObservationEnum.Regularity>(BsonType.String)));
                    cm.MapMember(c => c.Since)
                        .SetDefaultValue(GroupedObservationEnum.Since.Last)
                        .SetSerializer(new EnumSerializer<GroupedObservationEnum.Since>(BsonType.String));
                    cm.MapMember(c => c.Result)
                        .SetIgnoreIfNull(true);
                    //.SetSerializer(new EnumSerializer<GroupedObservationEnum.Result>(BsonType.Array));
                    cm.MapMember(c => c.LabelList).SetIgnoreIfNull(true);
                });
            }
        }
}