using adas_core.Domain.Enums;
using adas_core.Domain.Models.BsonConverters;
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 that participates in section-based entity mapping by implementing the <see cref="IEntityMapContributor"/> interface.
/// </summary>
public class SectionMapContributor : IEntityMapContributor
{
    /// <summary>
    /// Registers the BSON class maps for the <see cref="Section"/>, <see cref="Section.SectionItem"/>, <see cref="SectionConfig"/>, and <see cref="MinimalDisplaySection"/> types, configuring their MongoDB serialization behavior such as required fields, default values, null-ignoring members, and custom serializers. Each class map is registered only if it has not already been registered, preventing duplicate registrations.
    /// </summary>
    public void RegisterMaps()
        {
            if (!BsonClassMap.IsClassMapRegistered(typeof(Section)))
                BsonClassMap.RegisterClassMap<Section>(cm =>
                {
                    cm.AutoMap();
                    cm.MapIdMember(c => c._id);
                    cm.MapMember(c => c.Id)
                        .SetIsRequired(true)
                        .SetDefaultValue(string.Empty);
                    cm.MapMember(c => c.SectionTitle).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.PointOfCare).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.LastUpdate).SetIgnoreIfNull(true);
    
                    cm.MapMember(c => c.Configuration)
                        .SetSerializer(new DictionaryBsonConverter());
                    cm.MapMember(c => c.SectionConfig).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.DesignProperties).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.PointOfCareList)
                        .SetDefaultValue(new Dictionary<string, List<PointOfCare>>());
                    cm.MapMember(c => c.Items).SetDefaultValue(new List<Section.SectionItem>());
                    cm.MapMember(c => c.Status)
                        .SetIgnoreIfNull(true)
                        .SetSerializer(
                            new NullableSerializer<StatusEnum.Type>(new EnumSerializer<StatusEnum.Type>(BsonType.String)));
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(Section.SectionItem)))
                BsonClassMap.RegisterClassMap<Section.SectionItem>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Group).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Boxes).SetDefaultValue(new List<Box>());
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(SectionConfig)))
                BsonClassMap.RegisterClassMap<SectionConfig>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Columns).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Rows).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.RefreshValues).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.RefreshConfig).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Steps).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.DesignProperties).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(MinimalDisplaySection)))
                BsonClassMap.RegisterClassMap<MinimalDisplaySection>(cm =>
                {
                    cm.AutoMap();
                    cm.MapIdMember(c => c.Id).SetDefaultValue(ObjectId.GenerateNewId());
                    cm.MapMember(c => c.Name).SetDefaultValue(string.Empty);
                    cm.MapMember(c => c.IsSelected).SetDefaultValue(false);
                });
        }
}