using adas_core.Domain.Enums;
using adas_core.Domain.Models;
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 the <see cref="PatientAppointment"/> type as part of the mapping framework.
/// </summary>
public class AppointmentMapContributor : IEntityMapContributor
{
    /// <summary>
    /// Registers BSON class maps for the <see cref="PatientAppointment"/>, <see cref="PatientAppointmentResourceGroup"/>, and <see cref="Allergies"/> types, customizing the MongoDB serialization for their members. Registration is performed only if a class map for the type has not already been registered, making the call safe to invoke multiple times. Optional members are configured to be ignored when null, enum members are serialized as nullable string enums, and certain computed/action members are unmapped or assigned default collection values.
    /// </summary>
    public void RegisterMaps()
        {
            if (!BsonClassMap.IsClassMapRegistered(typeof(PatientAppointment)))
                BsonClassMap.RegisterClassMap<PatientAppointment>(cm =>
                {
                    cm.AutoMap();
    
                    cm.MapIdMember(c => c.Id).SetElementName("_id");
                    cm.MapMember(c => c.PatientId).SetSerializer(new ObjectIdSerializer(BsonType.String));
                    cm.MapMember(c => c.Patient).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Timings).SetDefaultValue(new List<Timing>());
                    cm.MapMember(c => c.CreateTime).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.UpdateTime).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.PlacerOrder).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.FillerOrder).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.EventReason).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.AppointmentReason).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.AppointmentType).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.AppointmentOperationType)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(
                            new NullableSerializer<OperationType>(new EnumSerializer<OperationType>(BsonType.String)));
                    cm.MapMember(c => c.AppointmentStatus)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(
                            new NullableSerializer<OperationType>(new EnumSerializer<OperationType>(BsonType.String)));
                    cm.MapMember(c => c.Duration).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.VisitNumber).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.PatientClass).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.EpisodeActivation).SetDefaultValue(true);
                    cm.MapMember(c => c.PlacerContact).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.FillerContact).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ResourceGroups).SetDefaultValue(new List<PatientAppointmentResourceGroup>());
                    cm.MapMember(c => c.Allergies).SetDefaultValue(new List<Allergies>());
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(PatientAppointmentResourceGroup)))
                BsonClassMap.RegisterClassMap<PatientAppointmentResourceGroup>(cm =>
                {
                    cm.AutoMap();
    
                    cm.MapMember(c => c.Services).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Resources).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Locations).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Personnel).SetIgnoreIfNull(true);
    
                    cm.UnmapMember(c => c.ServicesActions);
                    cm.UnmapMember(c => c.ResourcesActions);
                    cm.UnmapMember(c => c.LocationsActions);
                    cm.UnmapMember(c => c.PersonnelActions);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(Allergies)))
                BsonClassMap.RegisterClassMap<Allergies>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.AllergenType).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Allergen).SetIgnoreIfNull(true);
                });
        }
}