using System.Collections;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.GroupedObservations;
using MongoDB.Bson;

namespace adas_core.Domain.Models.MongoModels;

/// <summary>
/// Represents a configuration class for display settings and options.
/// </summary>
/// <remarks>
/// This class encapsulates the configuration data used to manage display-related properties and behavior.
/// </remarks>
public class DisplayConfig
{
    public ObjectId Id { get; set; }
    public DisplayConfigEnums.DisplayType Type { get; set; }
    public ObjectId? CardConfigId { get; set; }
    public CardConfig? CardConfig { get; private set; }
    public HomeConfig? HomeConfig { get; set; }
    public HeaderConfig? HeaderConfig { get; set; }
    public ObjectId? DetailConfigId { get; set; }
    public CardDetailsConfig? DetailConfig { get; private set; }

    public List<ObjectId> DisplaySectionIdList { get; set; } = [];

    public string? Hospital { get; set; }
    public ColorConfig? ColorConfig { get; set; }
    public List<Field> FieldList { get; set; } = [];
    public string? MediaFolder { get; set; }
    public List<GroupedField>? GroupedFieldList { get; set; }
    public List<BannerItem>? HomeBanner { get; set; }
    public FormConfig? FormConfig { get; set; }
    public List<ObjectId>? ChartConfigIdList { get; set; }
    public List<ChartConfig>? ChartConfig { get; set; }
    public bool? HasCameras { get; set; }
    public bool? HasSound { get; set; }
    public bool? IsRotationEnabled { get; set; }
    public bool? CanChangeCameraMode { get; set; }
    public bool? CamerasAreActive { get; set; }
    public string? CameraStreamType { get; set; }
    public List<Sensor>? SensorList { get; set; }
    public string? ObservationForIndicator { get; set; }
    public List<Field>? AlarmFieldList { get; set; }
    public List<GroupedField>? RequestGroupedFieldList { get; set; }
    public bool? Pumps { get; set; }
    public GraphLayout? GraphLayout { get; set; }
    public List<CardRotatingLayout>? CardRotatingLayout { get; set; }

    #region NotMapped

    public List<MinimalDisplaySection> DisplaySectionList { get; set; } = [];

    #endregion

    /// <summary>
    /// Merges the current display configuration with the provided default configuration,
    /// using the current instance's values where they are not null or empty, and falling back
    /// to the default configuration values otherwise. Simple nullable properties are merged
    /// via null-coalescing assignment, while collection properties are replaced when they
    /// are null or empty.
    /// </summary>
    /// <param name="defaultConfig">The default configuration to use as a fallback when the current configuration properties are null or empty.</param>
    /// <returns>The current <see cref="DisplayConfig"/> instance with merged configuration values.</returns>
    public virtual DisplayConfig MergeConfig(DisplayConfig defaultConfig)
        {
            // CardConfig ??= defaultConfig.CardConfig; 
            CardConfigId ??= defaultConfig.CardConfigId;
            HomeConfig ??= defaultConfig.HomeConfig;
            HeaderConfig ??= defaultConfig.HeaderConfig;
            DetailConfigId ??= defaultConfig.DetailConfigId;
            Hospital ??= defaultConfig.Hospital;
            ColorConfig ??= defaultConfig.ColorConfig;
            MediaFolder ??= defaultConfig.MediaFolder;
            GroupedFieldList ??= defaultConfig.GroupedFieldList;
            if (SensorList?.Count == 0) SensorList = defaultConfig.SensorList;
            if (AlarmFieldList?.Count == 0) AlarmFieldList = defaultConfig.AlarmFieldList;
            if (FieldList.Count == 0) FieldList = defaultConfig.FieldList;
            if (GroupedFieldList?.Count == 0) GroupedFieldList = defaultConfig.GroupedFieldList;
            if (RequestGroupedFieldList?.Count == 0) RequestGroupedFieldList = defaultConfig.RequestGroupedFieldList;
            if (ChartConfig?.Count == 0) ChartConfig = defaultConfig.ChartConfig;
            return this;
        }
}
/// <summary>
/// Represents a standard display configuration, extending the base <see cref="DisplayConfig"/> class to provide default display settings.
/// </summary>
public class StandarDisplay : DisplayConfig
{
    public SectionConfig? SectionConfig { get; set; }

    /// <summary>
    /// Merges the provided default display configuration into the current instance when it is a <see cref="StandarDisplay"/>, applying the default home configuration if none is set and overriding color and rotation settings; otherwise returns the current instance unchanged.
    /// </summary>
    /// <param name="defaultConfig">The default display configuration to merge from. Only values from a <see cref="StandarDisplay"/> instance are applied.</param>
    /// <returns>The merged <see cref="DisplayConfig"/>, or the current instance if the provided configuration is not a <see cref="StandarDisplay"/>.</returns>
    public override DisplayConfig MergeConfig(DisplayConfig defaultConfig)
        {
            if (defaultConfig is not StandarDisplay defaultStandarConfig)
                return this; // Si no es de tipo DisplayNurse, no combinar.
    
            HomeConfig ??= defaultStandarConfig.HomeConfig;
            ColorConfig = defaultStandarConfig.ColorConfig;
            IsRotationEnabled = defaultStandarConfig.IsRotationEnabled;
            return base.MergeConfig(defaultConfig);
        }
}
/// <summary>
/// Represents a display configuration specific to nurses, inheriting common display behavior from the <see cref="DisplayConfig"/> base class.
/// </summary>
public class DisplayNurse : DisplayConfig
{
    /// <summary>
    /// Merges the current display configuration with the provided default configuration, populating HomeBanner, ColorConfig, and FormConfig with the default values when they are not already set. If the defaultConfig is not a DisplayNurse instance, the current configuration is returned unchanged before delegating to the base merge behavior.
    /// </summary>
    /// <param name="defaultConfig">The default DisplayConfig to merge values from. Only DisplayNurse instances contribute fallback values for nurse-specific settings.</param>
    /// <returns>A DisplayConfig containing the merged configuration.</returns>
    public override DisplayConfig MergeConfig(DisplayConfig defaultConfig)
        {
            if (defaultConfig is not DisplayNurse defaultNurseConfig) return this;
            HomeBanner ??= defaultNurseConfig.HomeBanner;
            ColorConfig ??= defaultNurseConfig.ColorConfig;
            FormConfig ??= defaultNurseConfig.FormConfig;
            return base.MergeConfig(defaultConfig);
        }
}

/// <summary>
/// Represents a display configuration tailored for a pump, providing settings that determine how pump-related information is rendered.
/// </summary>
/// <remarks>
/// Inherits from <see cref="DisplayConfig"/>, extending its general display configuration behavior with pump-specific context.
/// </remarks>
public class PumpDisplay : DisplayConfig
{
    /// <summary>
    /// Merges the specified display configuration into the current instance, applying default values from the provided <see cref="PumpDisplay"/> configuration when the current values are null or empty. Returns the current instance unchanged if the supplied configuration is not a <see cref="PumpDisplay"/>.
    /// </summary>
    /// <param name="config">The display configuration to merge from. Only <see cref="PumpDisplay"/> instances are processed; any other type results in the current instance being returned as-is.</param>
    /// <returns>The merged <see cref="DisplayConfig"/> result produced by chaining the base merge operation.</returns>
    public override DisplayConfig MergeConfig(DisplayConfig config)
        {
            if (config is not PumpDisplay defaultConfig) return this;
            CardConfigId ??= defaultConfig.CardConfigId;
            HomeConfig ??= defaultConfig.HomeConfig;
            ColorConfig = defaultConfig.ColorConfig;
            
            GraphLayout ??= defaultConfig.GraphLayout;
            Pumps ??= defaultConfig.Pumps;
            if (FieldList.Count == 0) FieldList = defaultConfig.FieldList;
            if (GroupedFieldList?.Count == 0) GroupedFieldList = defaultConfig.GroupedFieldList;
            if (RequestGroupedFieldList?.Count == 0) RequestGroupedFieldList = defaultConfig.RequestGroupedFieldList;
            if (ChartConfig?.Count == 0) ChartConfig = defaultConfig.ChartConfig;
            
            return base.MergeConfig(config);
        }
}

/// <summary>
/// Represents a smart display configuration that extends the base <see cref="DisplayConfig"/> behavior.
/// </summary>
public class SmartDisplay : DisplayConfig
{
    /// <summary>
    /// Merges the provided default configuration into this <see cref="SmartDisplay"/> instance, applying default values for any properties that are currently <see langword="null"/>. If the supplied configuration is not a <see cref="SmartDisplay"/>, the current instance is returned unchanged and the merge is delegated to the base implementation.
    /// </summary>
    /// <param name="defaultConfigToCast">The default <see cref="DisplayConfig"/> to merge; it is cast to <see cref="SmartDisplay"/> to access smart display-specific properties.</param>
    /// <returns>The merged <see cref="DisplayConfig"/> produced by the base merge operation.</returns>
    public override DisplayConfig MergeConfig(DisplayConfig defaultConfigToCast)
        {
            if (defaultConfigToCast is not SmartDisplay defaultConfig) return this;
            ColorConfig = defaultConfig.ColorConfig;
            HasCameras ??= defaultConfig.HasCameras;
            HasSound ??= defaultConfig.HasSound;
            IsRotationEnabled ??= defaultConfig.IsRotationEnabled;
            CanChangeCameraMode ??= defaultConfig.CanChangeCameraMode;
            CamerasAreActive ??= defaultConfig.CamerasAreActive;
            CameraStreamType ??= defaultConfig.CameraStreamType;
            GraphLayout ??= defaultConfig.GraphLayout;
            Pumps ??= defaultConfig.Pumps;
            ObservationForIndicator ??= defaultConfig.ObservationForIndicator;
            CardRotatingLayout ??= defaultConfig.CardRotatingLayout;
            return base.MergeConfig(defaultConfig);
        }

    // TO TEST
    public List<string> GetDifferentProperties(SmartDisplay? other)
    {
        // Obtiene las propiedades públicas de la clase SmartDisplay
        var properties = typeof(SmartDisplay).GetProperties();

        var differentProperties = (
            from property in properties
            let thisValue = property.GetValue(this)
            let otherValue = property.GetValue(other)
            where !AreEqual(thisValue, otherValue)
            select property.Name
        ).ToList();

        if (ColorConfig != null && !ColorConfig.Equals(other?.ColorConfig))
            differentProperties.Add("ColorConfig");

        return differentProperties;
    }

    // Método para comparar valores de diferentes tipos de propiedades
    /// <summary>
    /// Determines whether two values are considered equal, handling null cases, performing element-wise comparison for enumerables, and falling back to <see cref="object.Equals(object, object)"/> for same-type values or string comparison for different types.
    /// </summary>
    /// <param name="value1">The first value to compare.</param>
    /// <param name="value2">The second value to compare.</param>
    /// <returns><c>true</c> if both values are null, deeply equal as enumerables, equal via <see cref="object.Equals(object, object)"/> when their types match, or have matching string representations; otherwise, <c>false</c>.</returns>
    private static bool AreEqual(object? value1, object? value2)
        {
            if (value1 == null && value2 == null) return true;
    
            if (value1 == null || value2 == null) return false;
            if (value1 is IEnumerable enumerable1 && value2 is IEnumerable enumerable2)
            {
                var enumerator1 = enumerable1.GetEnumerator();
                var enumerator2 = enumerable2.GetEnumerator();
    
                try
                {
                    while (enumerator1.MoveNext() && enumerator2.MoveNext())
                        if (!AreEqual(enumerator1.Current, enumerator2.Current))
                            return false;
    
                    return !enumerator1.MoveNext() && !enumerator2.MoveNext();
                }
                finally
                {
                    if (enumerator1 is IDisposable disposable1) disposable1.Dispose();
                    if (enumerator2 is IDisposable disposable2) disposable2.Dispose();
                }
            }
    
            // Si ambos valores son del mismo tipo, usa Equals para comparar
            if (value1.GetType() == value2.GetType()) return value1.Equals(value2);
    
            // Si los tipos son diferentes, convierte a string y compara
            return value1.ToString() == value2.ToString();
        }
}
/// <summary>
/// Represents a configuration class for defining header-related settings.
/// </summary>
public class HeaderConfig
{
    public HeaderItem? PartnerLogo { get; set; }

    public HeaderItem? CompanyLogo { get; set; }

    public HeaderItem? MeddisLogo { get; set; }

    public HeaderItem? CenterLogo { get; set; }

    public HeaderItem? UnitName { get; set; }

    public HeaderItem? Cameras { get; set; }

    public HeaderItem? Sensors { get; set; }

    public HeaderItem? Fullscreen { get; set; }

    public HeaderItem? Sounds { get; set; }

    public HeaderItem? Sidebar { get; set; }

    public HeaderItem? CurrentDateTime { get; set; }

    public HeaderItem? SectionTitle { get; set; }

    /// <summary>
    /// Represents a single item contained within a header.
    /// </summary>
    public class HeaderItem
    {
        public string? LogoUrl { get; set; }
        public bool IsVisible { get; set; } = true;
    }
}

/// <summary>
/// Represents a display section that provides a minimal rendering configuration.
/// </summary>
public class MinimalDisplaySection
{
    public string? Name { get; set; }
    public ObjectId Id { get; set; }
    public bool IsSelected { get; set; }
}
/// <summary>
/// Represents the configuration settings for a section.
/// </summary>
public class SectionConfig
{
    public int? Columns { get; set; }
    public int? Rows { get; set; }
    public int? RefreshValues { get; set; }
    public int? RefreshConfig { get; set; }
    public UiFontData? DesignProperties { get; set; }
    public List<Step>? Steps { get; set; }
}
/// <summary>
/// Represents a banner item, typically used to encapsulate data related to a banner display element such as a notification, advertisement, or promotional content.
/// </summary>
public class BannerItem
{
    public DisplayConfigEnums.BannerType? Type { get; set; }
    public double GrowPriority { get; set; }
    public BannerItemConfig? Config { get; set; }
}

/// <summary>
/// Represents the configuration settings for a banner item, defining its properties and behavior.
/// </summary>
/// <remarks>
/// This class is used to store and manage configuration data related to individual banner items within the application.
/// </remarks>
public class BannerItemConfig
{
    public BannerItemTableConfig? BannerItemTableConfig { get; set; }
    public BannerItemTableConfig? BannerItemDialogTableConfig { get; set; }
    public MedicalStaffConfig? MedicalStaffConfig { get; set; }
}

/// <summary>
/// Represents the configuration settings for a banner item table.
/// </summary>
public class BannerItemTableConfig
{
    public List<HeaderBannerItemTableConfig>? Config { get; set; }
    public string? BgColor { get; set; }
    public string? TextColor { get; set; }
}

/// <summary>
/// Represents the configuration settings for medical staff.
/// </summary>
public class MedicalStaffConfig
{
    public bool? HasTeams { get; set; }
    public int? StaffAmount { get; set; }
}

/// <summary>
/// Represents an overview of form items, providing a consolidated view or summary of form-related data.
/// </summary>
public class FormItemOverview
{
    public bool Nhc { get; set; }
    public bool? Bed { get; set; }
    public bool? Name { get; set; }
    public bool? LastName { get; set; }
    public bool? SecondName { get; set; }
    public bool? Genre { get; set; }
    public bool? Birthday { get; set; }
    public bool? Origin { get; set; }
    public bool? OriginAux { get; set; }
    public bool? Diagnostic { get; set; }
    public bool? DiagnosticAux { get; set; }
    public bool? Allergy { get; set; }
    public bool? Language { get; set; }
    public bool? Insulation { get; set; }

    public bool? Service { get; set; }
    public bool? Destination { get; set; }
    public bool? DestinationAux { get; set; }
    public bool? AdmDischarge { get; set; }
    public bool? NurseDischarge { get; set; }
    public bool? MedicalDischarge { get; set; }
    public bool? IncomingDate { get; set; }
    public bool? UciDays { get; set; }
}

/// <summary>
/// Represents the configuration settings for a table that displays header banner items.
/// </summary>
public class HeaderBannerItemTableConfig
{
    public DisplayConfigEnums.CellType? Type { get; set; }
    public string? SubType { get; set; }
    public List<string>? Field { get; set; }
    public double? GrowPriority { get; set; }
    public bool? Icon { get; set; }
    public string? BgColor { get; set; }
    public string? TextColor { get; set; }
    public string? Title { get; set; }
}

/// <summary>
/// Represents a sensor, which is a device or component used to detect and measure physical phenomena such as temperature, pressure, or motion.
/// </summary>
public class Sensor
{
    public string? Name { get; set; }
    public string? Title { get; set; }
    public bool OnlyNumbers { get; set; }
    public bool IsGeneral { get; set; }
}

/// <summary>
/// Represents a configuration that defines color-related settings or values.
/// </summary>
public class ColorConfig
{
    public LevelColors? Level { get; set; }
    public TextColors? Text { get; set; }
    public ArrowColors? Arrow { get; set; }
    public IndicatorColors? Indicator { get; set; }
    public GraphColors? Graph { get; set; }
    public StatusBoxNumberColors? BoxNumber { get; set; }
    public StatusBoxNumberColors? BoxStatusColor { get; set; }
    public TherapyColors? Therapy { get; set; }
    public TestColors? Test { get; set; }
    public ProcedureColors? Procedure { get; set; }

    //public override bool Equals(object? obj)
    //{
    //    if (obj == null || GetType() != obj.GetType()) return false;

    //    var otherColorConfig = (ColorConfig)obj;
    //    return Level != null && Level.Equals(otherColorConfig.Level) &&
    //           Text != null && Text.Equals(otherColorConfig.Text) &&
    //           Arrow != null && Arrow.Equals(otherColorConfig.Arrow) &&
    //           Indicator != null && Indicator.Equals(otherColorConfig.Indicator) &&
    //           Graph != null && Graph.Equals(otherColorConfig.Graph) &&
    //           Therapy != null && Therapy.Equals(otherColorConfig.Therapy) &&
    //           Test != null && Test.Equals(otherColorConfig.Test) &&
    //           Procedure != null && Procedure.Equals(otherColorConfig.Procedure) &&
    //           BoxNumber != null && BoxNumber.Equals(otherColorConfig.BoxNumber) &&
    //           BoxStatusColor != null && BoxStatusColor.Equals(otherColorConfig.BoxStatusColor);
    //}

    //public override int GetHashCode()
    //{
    //    unchecked
    //    {
    //        var hash = 17;
    //        hash = hash * 23 + Level?.GetHashCode() ?? 0;
    //        hash = hash * 23 + Text?.GetHashCode() ?? 0;
    //        hash = hash * 23 + Arrow?.GetHashCode() ?? 0;
    //        hash = hash * 23 + Indicator?.GetHashCode() ?? 0;
    //        hash = hash * 23 + Graph?.GetHashCode() ?? 0;
    //        hash = hash * 23 + BoxNumber?.GetHashCode() ?? 0;
    //        hash = hash * 23 + Test?.GetHashCode() ?? 0;
    //        hash = hash * 23 + Procedure?.GetHashCode() ?? 0;
    //        hash = hash * 23 + Therapy?.GetHashCode() ?? 0;
    //        hash = hash * 23 + BoxStatusColor?.GetHashCode() ?? 0;
    //        return hash;
    //    }
    //}

    /// <summary>
    /// Represents configuration settings that define the visual appearance of an application or user interface element.
    /// </summary>
    public class AppearanceSettings
    {
        public string? TextColor { get; set; }
        public string? BackgroundColor { get; set; }
        public string? Icon { get; set; }
        public string? IconDefault { get; set; }
        public string? IconColor { get; set; }
        public string? IconCategory { get; set; }
        public double IconInvertColor { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherLevelColors = (AppearanceSettings)obj;
        //    return TextColor == otherLevelColors.TextColor &&
        //           BackgroundColor == otherLevelColors.BackgroundColor &&
        //           Icon == otherLevelColors.Icon &&
        //           Math.Abs(IconInvertColor - otherLevelColors.IconInvertColor) == 0 &&
        //           IconDefault == otherLevelColors.IconDefault
        //        ;
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + TextColor?.GetHashCode() ?? 0;
        //        hash = hash * 23 + BackgroundColor?.GetHashCode() ?? 0;
        //        hash = hash * 23 + IconInvertColor.GetHashCode();
        //        hash = hash * 23 + Icon?.GetHashCode() ?? 0;
        //        hash = hash * 23 + IconDefault?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Represents the set of colors used to display numbers within a status box.
    /// </summary>
    public class StatusBoxNumberColors
    {
        public AppearanceSettings? Reserved { get; set; }
        public AppearanceSettings? InUse { get; set; }
        public AppearanceSettings? Available { get; set; }
        public AppearanceSettings? Locked { get; set; }
        public AppearanceSettings? Transferable { get; set; }
        public AppearanceSettings? Exitus { get; set; }
        public AppearanceSettings? Altable { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherLevelColors = (StatusBoxNumberColors)obj;
        //    return Reserved != null && Reserved.Equals(otherLevelColors.Reserved) &&
        //           InUse != null && InUse.Equals(otherLevelColors.InUse) &&
        //           Transferable != null && Transferable.Equals(otherLevelColors.Transferable) &&
        //           Exitus != null && Exitus.Equals(otherLevelColors.Exitus) &&
        //           Altable != null && Altable.Equals(otherLevelColors.Altable) &&
        //           Available != null && Available.Equals(otherLevelColors.Available) &&
        //           Locked != null && Locked.Equals(otherLevelColors.Locked);
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + Reserved?.GetHashCode() ?? 0;
        //        hash = hash * 23 + InUse?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Available?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Locked?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Represents a collection of colors used for therapy-related visuals or themes.
    /// </summary>
    public class TherapyColors
    {
        public AppearanceSettings? Default { get; set; }
        public AppearanceSettings? Initialized { get; set; }
        public AppearanceSettings? Finished { get; set; }
        public AppearanceSettings? InProgress { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherLevelColors = (TherapyColors)obj;
        //    return InProgress != null && InProgress.Equals(otherLevelColors.InProgress) &&
        //           Initialized != null && Initialized.Equals(otherLevelColors.Initialized) &&
        //           Finished != null && Finished.Equals(otherLevelColors.Finished) &&
        //           Default != null && Default.Equals(otherLevelColors.Default);
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + InProgress?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Initialized?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Default?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Represents a test class for color-related operations or values.
    /// </summary>
    public class TestColors
    {
        public AppearanceSettings? Default { get; set; }
        public AppearanceSettings? Initialized { get; set; }
        public AppearanceSettings? Finished { get; set; }
        public AppearanceSettings? Expired { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherLevelColors = (TestColors)obj;
        //    return Expired != null && Expired.Equals(otherLevelColors.Expired) &&
        //           Initialized != null && Initialized.Equals(otherLevelColors.Initialized) &&
        //           Finished != null && Finished.Equals(otherLevelColors.Finished) &&
        //           Default != null && Default.Equals(otherLevelColors.Default);
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + Expired?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Initialized?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Finished?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Default?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Represents a set of colors used to define or customize the appearance of a procedure.
    /// </summary>
    public class ProcedureColors
    {
        public AppearanceSettings? Default { get; set; }
        public AppearanceSettings? Initialized { get; set; }
        public AppearanceSettings? Finished { get; set; }
        public AppearanceSettings? Expired { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherLevelColors = (ProcedureColors)obj;
        //    return Expired != null && Expired.Equals(otherLevelColors.Expired) &&
        //           Initialized != null && Initialized.Equals(otherLevelColors.Initialized) &&
        //           Finished != null && Finished.Equals(otherLevelColors.Finished) &&
        //           Default != null && Default.Equals(otherLevelColors.Default);
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + Expired?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Initialized?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Finished?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Default?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Represents a collection or definition of colors associated with different levels.
    /// </summary>
    public class LevelColors
    {
        public string? Level1 { get; set; }
        public string? Level2 { get; set; }
        public string? Level3 { get; set; }
        public string? Level4 { get; set; }
        public string? Level5 { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherLevelColors = (LevelColors)obj;
        //    return Level1 == otherLevelColors.Level1 &&
        //           Level2 == otherLevelColors.Level2 &&
        //           Level3 == otherLevelColors.Level3 &&
        //           Level4 == otherLevelColors.Level4 &&
        //           Level5 == otherLevelColors.Level5;
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + Level1?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Level2?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Level3?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Level4?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Level5?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Provides a collection of predefined color values used for styling or rendering text.
    /// </summary>
    public class TextColors
    {
        public string? Normal { get; set; }
        public string? Warning { get; set; }
        public string? Alert { get; set; }
        public string? Improve { get; set; }
        public string? Expired { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherTextColors = (TextColors)obj;
        //    return Normal == otherTextColors.Normal &&
        //           Warning == otherTextColors.Warning &&
        //           Alert == otherTextColors.Alert &&
        //           Improve == otherTextColors.Improve &&
        //           Expired == otherTextColors.Expired;
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + Normal?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Warning?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Alert?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Improve?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Expired?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Represents a collection or definition of colors used for rendering arrows.
    /// </summary>
    public class ArrowColors
    {
        public string? Normal { get; set; }
        public string? Warning { get; set; }
        public string? Alert { get; set; }
        public string? Improve { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherArrowColors = (ArrowColors)obj;
        //    return Normal == otherArrowColors.Normal &&
        //           Warning == otherArrowColors.Warning &&
        //           Alert == otherArrowColors.Alert &&
        //           Improve == otherArrowColors.Improve;
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + Normal?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Warning?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Alert?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Improve?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Represents a collection or definition of colors used for indicators.
    /// </summary>
    public class IndicatorColors
    {
        public string? Empty { get; set; }
        public string? Warning { get; set; }
        public string? Normal { get; set; }
        public string? Alert { get; set; }
        public string? Background { get; set; }
        public string? EmptyBackground { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherIndicatorColors = (IndicatorColors)obj;
        //    return Empty == otherIndicatorColors.Empty &&
        //           Warning == otherIndicatorColors.Warning &&
        //           Normal == otherIndicatorColors.Normal &&
        //           Alert == otherIndicatorColors.Alert &&
        //           Background == otherIndicatorColors.Background &&
        //           EmptyBackground == otherIndicatorColors.EmptyBackground;
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + Empty?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Warning?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Normal?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Alert?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Background?.GetHashCode() ?? 0;
        //        hash = hash * 23 + EmptyBackground?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }

    /// <summary>
    /// Represents a collection or definition of colors used for rendering graphs.
    /// </summary>
    public class GraphColors
    {
        public string? Normal { get; set; }
        public string? Warning { get; set; }
        public string? Alert { get; set; }

        //public override bool Equals(object? obj)
        //{
        //    if (obj == null || GetType() != obj.GetType()) return false;

        //    var otherGraphColors = (GraphColors)obj;
        //    return Normal == otherGraphColors.Normal &&
        //           Warning == otherGraphColors.Warning &&
        //           Alert == otherGraphColors.Alert;
        //}

        //public override int GetHashCode()
        //{
        //    unchecked
        //    {
        //        var hash = 17;
        //        hash = hash * 23 + Normal?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Warning?.GetHashCode() ?? 0;
        //        hash = hash * 23 + Alert?.GetHashCode() ?? 0;
        //        return hash;
        //    }
        //}
    }
}

/// <summary>
/// Represents configuration settings for a form.
/// </summary>
/// <remarks>
/// This class encapsulates the configuration data required to define or manage form-related properties.
/// </remarks>
public class FormConfig
{
    public FormItemOverview? Admission { get; set; }
    public FormItemOverview? Demographic { get; set; }
    public FormItemOverview? Discharge { get; set; }
    public FormItemOverview? IncomeInfo { get; set; }
}

// ======================
// Axis Components
// ======================
/// <summary>
/// Represents a label associated with an axis, typically used in charting or graphing scenarios to describe or identify the axis.
/// </summary>
public class AxisLabel
{
    public bool? Show { get; set; }
    public string? Color { get; set; }
    public decimal? FontSize { get; set; }
    public decimal? Margin { get; set; }
    public bool? Silent { get; set; }
}

/// <summary>
/// Represents the style configuration used to render an axis line.
/// </summary>
/// <summary>
/// Represents a line associated with an axis, typically used in charting or graphing scenarios to render or define axis-related visual elements.
/// </summary>
public class AxisLineStyle
{
    public string? Color { get; set; }
}

public class AxisLine
{
    public bool? Show { get; set; }
    public AxisLineStyle? LineStyle { get; set; }
}

/// <summary>
/// Represents a single tick mark on an axis, typically used in charting or graphing scenarios.
/// </summary>
public class AxisTick
{
    public bool? Show { get; set; }
    public short? Length { get; set; }

    public int? Interval { get; set; }
}

/// <summary>
/// Represents the configuration settings for a chart, defining its visual and behavioral properties.
/// </summary>
public class ChartConfig
{
    public ObjectId Id { get; set; }
    public ChartBaseConfig? BaseConfig { get; set; }
    public List<AxisConfig>? AxesConfig { get; set; }
    public List<SeriesConfigBase>? SeriesConfig { get; set; }

    // TODO: COMBINE ALL PROPERTIES IN SERIES CONFIG AND DELETE THE EXTENDS
}

// ======================
// Series Implementations
// ======================
/// <summary>
/// Serves as the base class for configuration types that define settings for a series.
/// Provides a common foundation for derived series configuration implementations.
/// </summary>
public class SeriesConfigBase
{
    public string? Key { get; set; }
    public string? Color { get; set; }
    public DisplayConfigEnums.SeriesType Type { get; set; }
    public DisplayConfigEnums.SourceType SourceType { get; set; }
    public List<string>? AxesNames { get; set; }
    public bool ShowSymbol { get; set; }
    public bool ShowColorOnLegend { get; set; }
    public bool ShowOnLegend { get; set; }
    public GroupedObservationEnum.Result Values { get; set; }
    public DisplayConfigEnums.MarkerIcon MarkerIcon { get; set; }
    public VisualMap? VisualMap { get; set; }
    public string? LineStyle { get; set; }
    public int LineWidth { get; set; }
    public string? LineType { get; set; }
    public DisplayConfigEnums.MarkerIcon Marker { get; set; }
    public string? AboveBaselineColor { get; set; }
    public string? BelowBaselineColor { get; set; }
    public List<Candle>? CandleKeyList { get; set; }

    //public override bool Equals(object? obj)
    //{
    //    return obj is SeriesConfigBase other &&
    //           Key == other.Key &&
    //           Color == other.Color &&
    //           Type == other.Type &&
    //           SourceType == other.SourceType &&
    //           AxesNames == other.AxesNames &&
    //           ShowSymbol == other.ShowSymbol &&
    //           ShowColorOnLegend == other.ShowColorOnLegend &&
    //           ShowOnLegend == other.ShowOnLegend &&
    //           Values == other.Values;
    //}

    //public override int GetHashCode()
    //{
    //    return HashCode.Combine(Key, Color, Type, SourceType, AxesNames, ShowSymbol, ShowColorOnLegend, Values);
    //}
}

/// <summary>
/// Represents a visual mapping that handles the rendering or display logic for map-related data.
/// </summary>
public class VisualMap
{
    public bool Show { get; set; } //Mostrar en la leyenda
    public int Dimension { get; set; } //Eje al que afecta (index)
    public string? SerieKey { get; set; } //Serie a la que afecta
    public List<Piece>? Pieces { get; set; } //Rangos de colores y configuraciones de tipos
}

/// <summary>
/// Represents a single piece, serving as a general-purpose entity within its containing system.
/// </summary>
public class Piece
{
    public double? Opacity { get; set; } //Valor de la opacidad
    public DisplayConfigEnums.LineType LineType { get; set; } //Enum tipo de línea
    public string? Color { get; set; } //Color del rango
    public string? Symbol { get; set; } //Icono del rango
    public int? SymbolSize { get; set; } //Tamaño del icono del rango

    //Comparaciones para evaluar rangos
    public object? Eq { get; set; }
    public object? Neq { get; set; }
    public double? Lt { get; set; }
    public double? Lte { get; set; }
    public double? Gt { get; set; }
    public double? Gte { get; set; }
}

// public class LineSeriesConfig : SeriesConfigBase
// {
//     public string? LineStyle { get; set; }
//     public int LineWidth { get; set; } 
//     public string? LineType { get; set; }
//
//     public override bool Equals(object? obj)
//     {
//         return base.Equals(obj) &&
//                obj is LineSeriesConfig other &&
//                LineStyle == other.LineStyle &&
//                LineWidth == other.LineWidth &&
//                ShowSymbol == other.ShowSymbol;
//     }
//
//     public override int GetHashCode()
//     {
//         return HashCode.Combine(base.GetHashCode(), LineStyle, LineWidth, ShowSymbol);
//     }
// }

// public class VerticalMarkerSeriesConfig : SeriesConfigBase
// {   
//     public DisplayConfigEnums.MarkerIcon Marker { get; set; }
//
//     public override bool Equals(object? obj)
//     {
//         return base.Equals(obj) &&
//                obj is VerticalMarkerSeriesConfig other &&
//                Marker == other.Marker;
//     }
//
//     public override int GetHashCode()
//     {
//         return HashCode.Combine(base.GetHashCode(), Marker);
//     }
// }

// public class AreaSeriesConfig : SeriesConfigBase
// {
//     public string? AboveBaselineColor { get; set; }
//     public string? BelowBaselineColor { get; set; }
//     public override bool Equals(object? obj)
//     {
//         return base.Equals(obj) &&
//             obj is AreaSeriesConfig other &&
//             AboveBaselineColor == other.AboveBaselineColor &&
//             BelowBaselineColor == other.BelowBaselineColor;
//     }
//
//     public override int GetHashCode()
//     {
//         return HashCode.Combine(AboveBaselineColor, BelowBaselineColor);
//     }
// }
// /// <summary>
// /// Represents a candle entity within the system.
// /// </summary>
// public class CandlestickSeriesConfig : SeriesConfigBase
// {
//     public List<Candle>? CandleKeyList { get; set; }
//     public override bool Equals(object? obj)
//     {
//         return base.Equals(obj) &&
//                obj is Candle other;
//     }
//
//     public override int GetHashCode()
//     {
//         return HashCode.Combine(CandleKeyList);
//     }
// }

public class Candle
{
    public string? Key { get; set; }
    public CandleValueType? CandleValueType { get; set; }
}

public enum CandleValueType
{
    Open,
    Close,
    UnSet
}

// ======================
// Chart Configurations
// ======================
/// <summary>
/// Serves as the base class for chart configuration objects, providing common configuration properties and behavior shared by all chart types.
/// </summary>
/// <remarks>
/// This class is intended to be inherited by specialized chart configuration types to ensure consistent configuration handling across the charting system.
/// </remarks>
public class ChartBaseConfig
{
    public string? Title { get; set; }
    public string? Top { get; set; }
    public string? Right { get; set; }
    public string? Bottom { get; set; }
    public string? Left { get; set; }
    public string? Group { get; set; }
    public string? Name { get; set; }
    public int BorderWidth { get; set; }
    public string? BorderColor { get; set; }
    public bool ShowLegend { get; set; }
    public bool ShowGrid { get; set; }
    public float NumValues { get; set; }
    public float BaselineOffset { get; set; }
}

/// <summary>
/// Represents the configuration settings for an axis.
/// </summary>
public class AxisConfig
{
    public DisplayConfigEnums.AxisType Type { get; set; }
    public string? KeyName { get; set; }
    public DisplayConfigEnums.AxisPosition Position { get; set; }
    public object? Min { get; set; }
    public object? Max { get; set; }
    public AxisLine? AxisLine { get; set; }
    public AxisTick? AxisTick { get; set; }
    public AxisLabel? AxisLabel { get; set; }
    public bool Silent { get; set; }
    public DisplayConfigEnums.LabelFormat LabelFormat { get; set; }
    public double Offset { get; set; }
    public List<string>? CustomLabels { get; set; }
    public bool SortLabels { get; set; }
    public bool Show { get; set; }
    public GroupedObservationEnum.Regularity Regularity { get; set; }
}

/// <summary>
/// Represents a layout configuration for arranging elements of a graph, such as positioning nodes and routing edges.
/// </summary>
/// <remarks>
/// This class serves as a base type for specific graph layout strategies and is intended to be used to control the visual or logical arrangement of graph components.
/// </remarks>
public class GraphLayout
{
    public string? Layout { get; set; }
    public List<List<string>>? ObservationTitle { get; set; }
    public List<string>? Name { get; set; }
    public string? GraphConf { get; set; }
    public List<string>? ObservationName { get; set; }
}

/// <summary>
/// Represents a layout configuration for arranging section boxes.
/// </summary>
public class SectionBoxLayout
{
    public DisplayConfigEnums.RowType Type { get; set; }
    public string? Name { get; set; }
    public string? Icon { get; set; }
    public int? GridColumn { get; set; }
    public string? PaddingTop { get; set; }
    public string? PaddingBottom { get; set; }
    public string? PaddingLeft { get; set; }
    public string? PaddingRight { get; set; }
    public string? BorderColor { get; set; }
    public string? BorderWidth { get; set; }
    public string? BorderStyle { get; set; }
    public string? BorderRadius { get; set; }
    public double? HProportion { get; set; }
    public string? BgColor { get; set; }
    public string? SectionUrl { get; set; }
    public string? MinHeight { get; set; }
    public bool? Subtitle { get; set; }
    public ConditionsConfig? Conditions { get; set; }
    public DisplayConfigEnums.DirectionEnum Direction { get; set; }
    public List<RowBoxLayout>? Rows { get; set; }
}

/// <summary>
/// Represents a configuration class that defines conditions.
/// </summary>
public class ConditionsConfig
{
    public string? Condition { get; set; }
    public string? FieldCondition { get; set; }
}

/// <summary>
/// Represents a layout manager that arranges child elements in a row-based box configuration.
/// </summary>
public class RowBoxLayout
{
    public double? GrowPriority { get; set; }
    public DisplayConfigEnums.CellType Type { get; set; } = DisplayConfigEnums.CellType.Default;
    public DisplayConfigEnums.WebDisplayCellSubtype SubType { get; set; }
    public string? BgColor { get; set; }
    public string? PaddingTop { get; set; }
    public string? PaddingBottom { get; set; }
    public string? PaddingLeft { get; set; }
    public string? PaddingRight { get; set; }
    public List<ObservationRowBoxLayout>? Observations { get; set; }
    public DisplayConfigEnums.DirectionEnum Direction { get; set; }
}

/// <summary>
/// Represents a box layout configuration for displaying observation rows.
/// </summary>
public class ObservationRowBoxLayout
{
    public List<ObservationTextRule>? TextRules { get; set; }
    public ChartSettings? ChartSettings { get; set; }
    public bool? ShowTitle { get; set; }

    public double? GrowPriority { get; set; }
    public DisplayConfigEnums.CellType Type { get; set; }
    public string? SubType { get; set; }
    public string? Name { get; set; }
    public string? Icon { get; set; }

    public string? Title { get; set; }
    public int GridColumn { get; set; }
    public bool? IsColumn { get; set; }
    public bool? IsStatic { get; set; }
    public string? GraphConf { get; set; }
    public List<string>? Names { get; set; }
    public List<string>? ObservationName { get; set; }
    public List<List<string>?>? ObservationTitle { get; set; }
    public List<ObservationRowBoxLayout>? Observations { get; set; }
    public string? BgColor { get; set; }
    public string? PaddingTop { get; set; }
    public string? PaddingBottom { get; set; }
    public string? PaddingLeft { get; set; }
    public string? PaddingRight { get; set; }
    public string? Border { get; set; }
    public string? BorderRadius { get; set; }
    public string? ValuePathNested { get; set; }
    public List<string>? ValuePathKey { get; set; }
    public double? Size { get; set; } = 15.0;
    public int? Format { get; set; }
    public int? Length { get; set; }
    public DisplayConfigEnums.DirectionEnum? Direction { get; set; }
}

/// <summary>
/// Represents a layout that arranges cards with a rotating behavior, likely managing the visual positioning and orientation of card elements within a container.
/// </summary>
public class CardRotatingLayout
{
    // In MS
    public int MillisecondsBeforeRotating { get; set; }
    public int? Order { get; set; }
    public string? Name { get; set; }
    public string? Title { get; set; }
    public DisplayConfigEnums.RotatingLayoutType Type { get; set; }
    public DisplayConfigEnums.RotatingLayoutMode Mode { get; set; }
    public ObjectId DataId { get; set; }
    public CardConfig Data { get; set; } = new();
}

/// <summary>
/// Represents a rule used to validate or process observation text.
/// </summary>
public class ObservationTextRule
{
    public ObservationEnum.ValueType ValueType { get; set; }
    public string? Value { get; set; }

    public string? MatchText { get; set; }
    public bool? MatchBoolean { get; set; }
    public decimal? MatchNumber { get; set; }
    public DateTime? MatchDate { get; set; }
    public string? Label { get; set; }
    public DateTime? MinDate { get; set; }
    public DateTime? MaxDate { get; set; }
    public decimal? MinNum { get; set; }
    public decimal? MaxNum { get; set; }
}

/// <summary>
/// Represents a configuration object that defines layout settings for a legend.
/// </summary>
public class LegendLayoutConfig
{
    public List<LegendLayoutRow>? Rows { get; set; }
}

/// <summary>
/// Represents a single row within a legend layout, typically used to organize and arrange legend items in a structured, row-based configuration.
/// </summary>
public class LegendLayoutRow
{
    public decimal? GrowPriority { get; set; }
    public List<LegendLayoutColumn>? Columns { get; set; }
}

/// <summary>
/// Represents a column within a legend layout, defining a vertical arrangement of legend entries or items.
/// </summary>
public class LegendLayoutColumn
{
    public string? Key { get; set; }
    public decimal? GrowPriority { get; set; }
    public LegendLabel? Label { get; set; }
}

/// <summary>
/// Represents a label associated with a legend, typically used to describe or identify an entry in a chart, graph, or similar visual component.
/// </summary>
public class LegendLabel
{
    public string? Name { get; set; }
    public string? ColorLabel { get; set; }
    public string? ColorIcon { get; set; }
    public bool? ShowSymbol { get; set; }
    public DisplayConfigEnums.ELegendIconType? IconType { get; set; }
}