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>
/// Represents a contributor that provides graph-based mapping logic for entities.
/// </summary>
/// <remarks>
/// Implements the <see cref="IEntityMapContributor"/> contract to participate in entity map configuration within a graph structure.
/// </remarks>
public class GraphMapContributor : IEntityMapContributor
{
    /// <summary>
    /// Registers BSON class maps for the application's chart, graph, and legend configuration types, configuring serialization behavior such as default values, null-ignoring, and enum string serialization. Each registration is guarded by an <see cref="BsonClassMap.IsClassMapRegistered"/> check so the method is idempotent and can be safely called multiple times.
    /// </summary>
    public void RegisterMaps()
        {
            if (!BsonClassMap.IsClassMapRegistered(typeof(GraphLayout)))
                BsonClassMap.RegisterClassMap<GraphLayout>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Layout).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ObservationTitle).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.GraphConf).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ObservationName).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(ChartSettings)))
                BsonClassMap.RegisterClassMap<ChartSettings>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.LegendLayoutConfig).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.LegendGrowPriority).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ChartGrowPriority).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(ChartConfig)))
            {
                BsonClassMap.RegisterClassMap<ChartConfig>(cm =>
                {
                    cm.AutoMap();
                    cm.MapIdMember(c => c.Id).SetElementName("_id");
                    cm.MapMember(c => c.BaseConfig).SetDefaultValue(new ChartBaseConfig());
                    cm.MapMember(c => c.AxesConfig).SetDefaultValue(new List<AxisConfig>());
                    cm.MapMember(c => c.SeriesConfig).SetDefaultValue(new List<SeriesConfigBase>());
                });
    
                BsonClassMap.RegisterClassMap<ChartBaseConfig>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Title).SetDefaultValue(string.Empty);
                    cm.MapMember(c => c.Top).SetDefaultValue("7%");
                    cm.MapMember(c => c.Right).SetDefaultValue("7%");
                    cm.MapMember(c => c.Bottom).SetDefaultValue("7%");
                    cm.MapMember(c => c.Left).SetDefaultValue("7%");
                    cm.MapMember(c => c.Group).SetDefaultValue(string.Empty);
                    cm.MapMember(c => c.Name).SetDefaultValue(string.Empty);
                    cm.MapMember(c => c.BorderWidth).SetDefaultValue(1);
                    cm.MapMember(c => c.BorderColor).SetDefaultValue(string.Empty);
                    cm.MapMember(c => c.ShowLegend).SetDefaultValue(false);
                    cm.MapMember(c => c.ShowGrid).SetDefaultValue(false);
                    cm.MapMember(c => c.NumValues).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.BaselineOffset).SetIgnoreIfNull(true);
                });
    
                BsonClassMap.RegisterClassMap<AxisConfig>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(a => a.Type)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.AxisType>(BsonType.String))
                        .SetDefaultValue(DisplayConfigEnums.AxisType.Value);
                    cm.MapMember(a => a.KeyName).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.Position)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.AxisPosition>(BsonType.String))
                        .SetDefaultValue(DisplayConfigEnums.AxisPosition.Left);
                    cm.MapMember(a => a.Min).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.Max).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.AxisLine).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.AxisTick).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.AxisLabel).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.Silent).SetDefaultValue(true);
                    cm.MapMember(a => a.LabelFormat)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.LabelFormat>(BsonType.String))
                        .SetDefaultValue(DisplayConfigEnums.LabelFormat.Hour);
                    cm.MapMember(a => a.Offset).SetDefaultValue(0.0);
                    cm.MapMember(a => a.CustomLabels).SetDefaultValue(new List<string>());
                    cm.MapMember(a => a.SortLabels).SetDefaultValue(false);
                    cm.MapMember(a => a.Show).SetDefaultValue(true);
                    cm.MapMember(a => a.Regularity)
                        .SetSerializer(new EnumSerializer<GroupedObservationEnum.Regularity>(BsonType.String))
                        .SetDefaultValue(GroupedObservationEnum.Regularity.Hour);
                });
    
    
                BsonClassMap.RegisterClassMap<AxisTick>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(a => a.Show).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.Interval).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.Length).SetIgnoreIfNull(true);
                });
    
                BsonClassMap.RegisterClassMap<AxisLabel>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(a => a.Show).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.Color).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.Margin).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.FontSize).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.Silent).SetIgnoreIfNull(true);
                });
    
                BsonClassMap.RegisterClassMap<AxisLineStyle>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(a => a.Color).SetIgnoreIfNull(true);
                });
                BsonClassMap.RegisterClassMap<AxisLine>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(a => a.Show).SetIgnoreIfNull(true);
                    cm.MapMember(a => a.LineStyle).SetIgnoreIfNull(true);
                });
                BsonClassMap.RegisterClassMap<SeriesConfigBase>(cm =>
                {
                    cm.AutoMap();
                    // cm.SetIsRootClass(true);
                    // cm.AddKnownType(typeof(CandlestickSeriesConfig));
                    cm.MapMember(s => s.Key).SetElementName("key");
                    cm.MapMember(s => s.Color).SetElementName("color");
                    cm.MapMember(s => s.Type)
                        .SetDefaultValue(DisplayConfigEnums.SeriesType.Line)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.SeriesType>(BsonType.String));
                    cm.MapMember(s => s.SourceType)
                        .SetDefaultValue(DisplayConfigEnums.SourceType.Obs)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.SourceType>(BsonType.String));
                    cm.MapMember(s => s.AxesNames)
                        .SetDefaultValue(new List<string>());
                    cm.MapMember(s => s.ShowSymbol).SetDefaultValue(false);
                    cm.MapMember(s => s.ShowColorOnLegend).SetDefaultValue(false);
                    cm.MapMember(s => s.ShowOnLegend).SetDefaultValue(true);
                    cm.MapMember(s => s.Values)
                        .SetDefaultValue(GroupedObservationEnum.Result.Last)
                        .SetSerializer(new EnumSerializer<GroupedObservationEnum.Result>(BsonType.String));
                    cm.MapMember(s => s.MarkerIcon)
                        .SetDefaultValue(DisplayConfigEnums.MarkerIcon.None)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.MarkerIcon>(BsonType.String));
                    cm.MapMember(s => s.VisualMap).SetIgnoreIfNull(true);
                    cm.MapMember(l => l.LineWidth).SetDefaultValue(2);
                    cm.MapMember(l => l.LineStyle).SetDefaultValue("solid");
                    cm.MapMember(v => v.Marker)
                        .SetDefaultValue(DisplayConfigEnums.MarkerIcon.Kangaroo)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.MarkerIcon>(BsonType.String));
                    cm.MapMember(a => a.AboveBaselineColor).SetIgnoreIfDefault(true);
                    cm.MapMember(a => a.BelowBaselineColor).SetIgnoreIfDefault(true);
                    cm.MapMember(a => a.CandleKeyList).SetIgnoreIfDefault(true);
                    cm.MapMember(p => p.LineType).SetIgnoreIfNull(true);
                });
                // BsonClassMap.RegisterClassMap<LineSeriesConfig>(cm =>
                // {
                //     cm.AutoMap();
                //     cm.MapMember(l => l.LineWidth).SetDefaultValue(2);
                //     cm.MapMember(l => l.LineStyle).SetDefaultValue("solid");
                // });
                // BsonClassMap.RegisterClassMap<VerticalMarkerSeriesConfig>(cm =>
                // {
                //     cm.AutoMap();
                //     cm.MapMember(v => v.Marker)
                //         .SetDefaultValue(DisplayConfigEnums.MarkerIcon.Kangaroo)
                //         .SetSerializer(new EnumSerializer<DisplayConfigEnums.MarkerIcon>(BsonType.String));
                // });
                // BsonClassMap.RegisterClassMap<AreaSeriesConfig>(cm =>
                // {
                //     cm.AutoMap();
                //     cm.MapMember(a => a.AboveBaselineColor).SetIgnoreIfDefault(true);
                //     cm.MapMember(a => a.BelowBaselineColor).SetIgnoreIfDefault(true);
                // });
                // BsonClassMap.RegisterClassMap<CandlestickSeriesConfig>(cm =>
                // {
                //     cm.AutoMap();
                //     cm.MapMember(a => a.CandleKeyList).SetIgnoreIfDefault(true); 
                // });
                // if (!BsonClassMap.IsClassMapRegistered(typeof(LineSeriesConfig)))
                // {
                //     BsonClassMap.RegisterClassMap<LineSeriesConfig>(cm =>
                //     {
                //         cm.AutoMap();
                //         cm.MapMember(p => p.LineStyle).SetDefaultValue("solid");
                //         cm.MapMember(p => p.LineWidth).SetDefaultValue(2);
                //         cm.MapMember(p => p.LineType).SetIgnoreIfNull(true);
                //     });
                // }
                BsonClassMap.RegisterClassMap<Candle>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(a => a.Key).SetIgnoreIfDefault(true);
                    cm.MapMember(a => a.CandleValueType)
                        .SetSerializer(
                            new NullableSerializer<CandleValueType>(new EnumSerializer<CandleValueType>(BsonType.String)));
                });
    
                BsonClassMap.RegisterClassMap<VisualMap>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(v => v.Show).SetDefaultValue(false);
                    cm.MapMember(v => v.Dimension).SetDefaultValue(0);
                    cm.MapMember(v => v.SerieKey).SetIgnoreIfNull(true);
                    cm.MapMember(v => v.Pieces).SetDefaultValue(new List<Piece>());
                });
            }
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(LegendLayoutConfig)))
                BsonClassMap.RegisterClassMap<LegendLayoutConfig>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Rows).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(LegendLayoutRow)))
                BsonClassMap.RegisterClassMap<LegendLayoutRow>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.GrowPriority).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Columns).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(LegendLayoutColumn)))
                BsonClassMap.RegisterClassMap<LegendLayoutColumn>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Key).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.GrowPriority).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.Label).SetIgnoreIfNull(true);
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(LegendLabel)))
                BsonClassMap.RegisterClassMap<LegendLabel>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ColorLabel).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ColorIcon).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.ShowSymbol).SetIgnoreIfNull(true);
                    cm.MapMember(c => c.IconType).SetIgnoreIfNull(true)
                        .SetSerializer(new NullableSerializer<DisplayConfigEnums.ELegendIconType>(
                            new EnumSerializer<DisplayConfigEnums.ELegendIconType>(BsonType.String)));
                });
    
            if (!BsonClassMap.IsClassMapRegistered(typeof(Piece)))
                BsonClassMap.RegisterClassMap<Piece>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(p => p.Opacity).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.LineType)
                        .SetDefaultValue(DisplayConfigEnums.LineType.Solid)
                        .SetSerializer(new EnumSerializer<DisplayConfigEnums.LineType>(BsonType.String));
                    cm.MapMember(p => p.Color).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.Symbol).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.SymbolSize).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.Eq).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.Neq).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.Gt).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.Lt).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.Gte).SetIgnoreIfNull(true);
                    cm.MapMember(p => p.Lte).SetIgnoreIfNull(true);
                });
        }
}