using System.Reflection;
using adas_core.Domain.Enums;
using MongoDB.Bson;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;

namespace adas_core.Domain.Models.MongoModels;

public class HistoricalConfigChanges : JsonConverter
{
    public DateTime Time;

    public string Username = string.Empty;

    public ObjectId Id { get; set; }

    public DisplayConfigEnums.ConfigTypes? ConfigType { get; set; }

    public string? OldConfig { get; set; }

    public string NewConfig { get; set; } = string.Empty;

    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
    {
        if (value != null)
        {
            var jo = JObject.FromObject(value);

            AddStringEnumConverterAttribute(value, nameof(ConfigType));
            jo.WriteTo(writer);
        }
    }

    private static void AddStringEnumConverterAttribute(object value, string propertyName)
    {
        var prop = value.GetType().GetProperty(propertyName);
        var attr = new JsonConverterAttribute(typeof(StringEnumConverter));

        if (prop != null)
        {
            var attrs = prop.GetCustomAttributes(false);

            // Check if the attribute is not already applied
            if (Array.Find(attrs, a => a is JsonConverterAttribute) == null)
            {
                // Create a new array that includes the existing attributes and the new one
                var newAttrs = new object[attrs.Length + 1];
                Array.Copy(attrs, newAttrs, attrs.Length);
                newAttrs[attrs.Length] = attr;

                // Use reflection to set the new attributes array
                var field = typeof(PropertyInfo).GetField("m_customAttributes",
                    BindingFlags.Instance | BindingFlags.NonPublic);
                field?.SetValue(prop, newAttrs);
            }
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object? existingValue,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }
}