using System;
using System.Collections.Concurrent;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using HuanMeng.DotNetCore.AttributeExtend;
using System.Linq.Expressions;
using Microsoft.IdentityModel.Tokens;


namespace HuanMeng.DotNetCore.Utility;


[Obsolete]
public static class ObjectExtensions11
{
    /// <summary>
    /// 缓存属性信息以提高反射访问的性能，使用 ConcurrentDictionary 确保线程安全
    /// </summary>
    private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropertyCache = new();

    /// <summary>
    /// 判断对象是否为基础类型。
    /// </summary>
    public static bool IsPrimitiveType(object obj) =>
        obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType);

    /// <summary>
    /// 判断对象是否为集合类型（排除字符串）。
    /// </summary>
    public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string;

    /// <summary>
    /// 判断对象是否为复杂类型。
    /// </summary>
    public static bool IsComplexType(object obj) =>
        obj is not null && !IsPrimitiveType(obj) && !IsCollectionType(obj);

    /// <summary>
    /// 转换对象为字典或列表
    /// </summary>
    public static object ToDictionaryOrList(object obj)
    {
        if (obj == null) return null;

        return obj switch
        {
            // 基础类型
            _ when IsPrimitiveType(obj) => obj,
            // 集合类型
            IEnumerable enumerable => TransformCollection(enumerable),
            // 复杂类型
            _ => TransformObject(obj)
        };
    }

    /// <summary>
    /// 转换集合为列表
    /// </summary>
    private static List<object> TransformCollection(IEnumerable enumerable)
    {
        var list = new List<object>();
        foreach (var item in enumerable)
        {
            list.Add(item.ToDictionaryOrList());
        }
        return list;
    }

    /// <summary>
    /// 转换对象为字典
    /// </summary>
    private static Dictionary<string, object> TransformObject(object obj)
    {
        var type = obj.GetType();
        var properties = PropertyCache.GetOrAdd(type, t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance));
        var keyValuePairs = new Dictionary<string, object>();

        foreach (var property in properties)
        {
            var propertyValue = property.GetValue(obj);
            keyValuePairs[property.Name] = IsCollectionType(propertyValue)
                ? propertyValue.ToDictionaryOrList()
                : propertyValue;
        }

        return keyValuePairs;
    }
}

[Obsolete]
public static class ObjectExtensions1
{
    private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropertyCache = new();
    private static readonly ConcurrentDictionary<PropertyInfo, bool> HasImagesAttributeCache = new();

    public static bool IsPrimitiveType(object obj) =>
        obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType);

    public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string;

    public static bool IsComplexType(object obj) =>
        obj is not null && !IsPrimitiveType(obj) && !IsCollectionType(obj);

    public static object ToDictionaryOrList(object obj)
    {
        if (obj == null) return null;

        return obj switch
        {
            _ when IsPrimitiveType(obj) => obj,
            IEnumerable enumerable => TransformCollection(enumerable),
            _ => TransformObject(obj)
        };
    }

    private static List<object> TransformCollection(IEnumerable enumerable)
    {
        var list = new List<object>(enumerable is ICollection collection ? collection.Count : 10);
        foreach (var item in enumerable)
        {
            list.Add(ToDictionaryOrList(item));
        }
        return list;
    }

    private static Dictionary<string, object> TransformObject(object obj)
    {
        var type = obj.GetType();
        var properties = PropertyCache.GetOrAdd(type, t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance));
        var keyValuePairs = new Dictionary<string, object>(properties.Length);

        foreach (var property in properties)
        {
            // 预先缓存 ImagesAttribute 判断结果
            if (!HasImagesAttributeCache.TryGetValue(property, out bool hasImagesAttribute))
            {
                hasImagesAttribute = property.GetCustomAttribute<ImagesAttribute>() != null;
                HasImagesAttributeCache.TryAdd(property, hasImagesAttribute);
            }
            var propertyValue = property.GetValue(obj);
            if (hasImagesAttribute)
            {
                keyValuePairs[property.Name] = $"image{propertyValue}";
                continue;
            }

            keyValuePairs[property.Name] = IsCollectionType(propertyValue)
                ? ToDictionaryOrList(propertyValue)
                : propertyValue;
            if (propertyValue is IEnumerable imagesEnumerable)
            {
                keyValuePairs[property.Name] = TransformCollection(imagesEnumerable);
            }
        }

        return keyValuePairs;
    }
}
[Obsolete]
public static class ObjectExtensions3
{
    private static readonly ConcurrentDictionary<Type, PropertyAccessor[]> PropertyAccessorsCache = new();
    private static readonly ConcurrentDictionary<PropertyInfo, bool> HasImagesAttributeCache = new();
    public static bool IsPrimitiveType(object obj) =>
        obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType);

    public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string;

    public static object ToDictionaryOrList(object obj)
    {
        if (obj == null) return null;

        return obj switch
        {
            _ when IsPrimitiveType(obj) => obj,
            IEnumerable enumerable => TransformCollection(enumerable),
            _ => TransformObject(obj)
        };
    }

    private static List<object> TransformCollection(IEnumerable enumerable)
    {
        var list = new List<object>();
        foreach (var item in enumerable)
        {
            list.Add(ToDictionaryOrList(item));
        }
        return list;
    }

    private static Dictionary<string, object> TransformObject(object obj)
    {
        var type = obj.GetType();
        var accessors = PropertyAccessorsCache.GetOrAdd(type, CreatePropertyAccessors);
        var keyValuePairs = new Dictionary<string, object>(accessors.Length);

        foreach (var accessor in accessors)
        {
            var propertyValue = accessor.Getter(obj);
            keyValuePairs[accessor.Name] = IsCollectionType(propertyValue)
                ? ToDictionaryOrList(propertyValue)
                : propertyValue;
        }

        return keyValuePairs;
    }

    private static PropertyAccessor[] CreatePropertyAccessors(Type type)
    {
        var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        var accessors = new PropertyAccessor[properties.Length];

        for (int i = 0; i < properties.Length; i++)
        {
            var property = properties[i];
            //var x = property.GetCustomAttribute<ImagesAttribute>() != null;

            var getter = CreateGetter(property);
            accessors[i] = new PropertyAccessor(property.Name, getter);
        }

        return accessors;
    }

    private static Func<object, object> CreateGetter(PropertyInfo property)
    {
        var parameter = Expression.Parameter(typeof(object), "instance");
        var castInstance = Expression.Convert(parameter, property.DeclaringType);
        var propertyAccess = Expression.Property(castInstance, property);
        var castResult = Expression.Convert(propertyAccess, typeof(object));
        var lambda = Expression.Lambda<Func<object, object>>(castResult, parameter);
        return lambda.Compile();
    }

    private record PropertyAccessor(string Name, Func<object, object> Getter);
}

[Obsolete]
public static class ObjectExtensions5
{
    // 用于缓存每个类型的属性访问器数组，以减少重复的反射操作
    private static readonly ConcurrentDictionary<Type, PropertyAccessor[]> PropertyCache = new();

    // 判断对象是否为原始类型、字符串或值类型
    public static bool IsPrimitiveType(object obj) =>
        obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType);

    // 判断对象是否为集合类型（非字符串的 IEnumerable）
    public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string;

    /// <summary>
    /// 将对象转换为字典或列表结构
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static object ToDictionaryOrList(object obj)
    {
        if (obj == null) return null;

        // 根据对象类型执行相应的转换操作
        return obj switch
        {
            _ when IsPrimitiveType(obj) => obj,           // 原始类型直接返回
            IEnumerable enumerable => TransformCollection(enumerable),  // 集合类型转换为列表
            _ => TransformObject(obj)                     // 复杂类型转换为字典
        };
    }

    /// <summary>
    ///  转换集合类型，将每个元素递归转换为字典或列表
    /// </summary>
    /// <param name="enumerable"></param>
    /// <returns></returns>
    private static List<object> TransformCollection(IEnumerable enumerable)
    {
        var list = new List<object>(enumerable is ICollection collection ? collection.Count : 10);
        foreach (var item in enumerable)
        {
            list.Add(ToDictionaryOrList(item));
        }
        return list;
    }

    // 转换复杂类型为字典结构，键为属性名，值为属性值
    private static Dictionary<string, object> TransformObject(object obj)
    {
        var type = obj.GetType();

        // 从缓存中获取或创建该类型的属性访问器数组
        var accessors = PropertyCache.GetOrAdd(type, t => CreatePropertyAccessors(t));
        var keyValuePairs = new Dictionary<string, object>(accessors.Length);

        // 遍历每个属性访问器
        foreach (var accessor in accessors)
        {
            // 使用表达式树生成的委托获取属性值
            var propertyValue = accessor.Getter(obj);

            // 如果属性具有 ImagesAttribute 特性，将其值转换为 "image{propertyValue}" 格式
            if (accessor.HasImagesAttribute)
            {
                keyValuePairs[accessor.PropertyName] = $"image{propertyValue}";
            }
            else
            {
                // 根据属性值的类型决定是否递归转换
                keyValuePairs[accessor.PropertyName] = IsCollectionType(propertyValue)
                    ? ToDictionaryOrList(propertyValue)
                    : propertyValue;
            }
        }

        return keyValuePairs;
    }

    // 创建指定类型的属性访问器数组
    private static PropertyAccessor[] CreatePropertyAccessors(Type type)
    {
        // 获取类型的公共实例属性
        var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        var accessors = new List<PropertyAccessor>(properties.Length);

        foreach (var property in properties)
        {
            // 使用表达式树生成委托来获取属性值，避免使用反射
            var parameter = Expression.Parameter(typeof(object), "obj");   // 输入参数 obj
            var castParameter = Expression.Convert(parameter, type);       // 将参数转换为目标类型
            var propertyAccess = Expression.Property(castParameter, property); // 获取属性值
            var convertPropertyAccess = Expression.Convert(propertyAccess, typeof(object)); // 转换为 object 类型
            var getter = Expression.Lambda<Func<object, object>>(convertPropertyAccess, parameter).Compile();

            // 检查属性是否具有 ImagesAttribute 特性
            bool hasImagesAttribute = property.GetCustomAttribute<ImagesAttribute>() != null;

            // 将属性名、Getter 委托和特性标识添加到 PropertyAccessor 对象中
            accessors.Add(new PropertyAccessor(property.Name, getter, hasImagesAttribute));
        }

        return accessors.ToArray();
    }

    // 表示属性访问器的类，包含属性名称、Getter 委托和特性标识
    private class PropertyAccessor
    {
        public string PropertyName { get; }          // 属性名称
        public Func<object, object> Getter { get; }  // 委托，用于获取属性值
        public bool HasImagesAttribute { get; }      // 是否包含 ImagesAttribute 特性

        public PropertyAccessor(string propertyName, Func<object, object> getter, bool hasImagesAttribute)
        {
            PropertyName = propertyName;
            Getter = getter;
            HasImagesAttribute = hasImagesAttribute;
        }
    }
}

[Obsolete]
public static class ObjectExtensions6
{
    /// <summary>
    /// 使用线程安全的字典缓存每个类型的属性访问器
    /// </summary>
    private static readonly ConcurrentDictionary<Type, PropertyAccessor[]> PropertyCache = new();
    /// <summary>
    /// 缓存每个属性是否具有 ImagesAttribute 特性
    /// </summary>
    private static readonly ConcurrentDictionary<PropertyInfo, bool> _PropertyCache = new ConcurrentDictionary<PropertyInfo, bool>();

    /// <summary>
    /// 判断对象是否为原始类型或字符串
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static bool IsPrimitiveType(object obj) =>
        obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType);

    /// <summary>
    /// 判断对象是否为集合类型（但不是字符串）
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string;

    /// <summary>
    /// 将对象转换为字典或列表
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static object ToDictionaryOrList(object obj)
    {
        if (obj == null) return null;

        return obj switch
        {
            _ when IsPrimitiveType(obj) => obj,
            IEnumerable enumerable => TransformCollection(enumerable),
            _ => TransformObject(obj)
        };
    }

    /// <summary>
    /// 将集合转换为列表
    /// </summary>
    /// <param name="enumerable"></param>
    /// <returns></returns>
    private static List<object> TransformCollection(IEnumerable enumerable)
    {
        // 如果集合实现了 ICollection 接口，则使用其 Count 属性初始化列表容量
        var list = new List<object>(enumerable is ICollection collection ? collection.Count : 10);
        foreach (var item in enumerable)
        {
            list.Add(ToDictionaryOrList(item));
        }
        return list;
    }

    // 将对象转换为字典
    private static Dictionary<string, object> TransformObject(object obj)
    {
        var type = obj.GetType();
        // 获取或创建该类型的属性访问器
        var accessors = PropertyCache.GetOrAdd(type, t => CreatePropertyAccessors(t));
        var keyValuePairs = new Dictionary<string, object>(accessors.Length);

        foreach (var accessor in accessors)
        {
            var propertyValue = accessor.Getter(obj);

            if (accessor.HasImagesAttribute)
            {
                // 如果属性具有 ImagesAttribute 特性，处理方式不同
                keyValuePairs[accessor.PropertyName] = $"image{propertyValue}";
            }
            else
            {
                // 如果属性是集合类型，递归转换
                keyValuePairs[accessor.PropertyName] = IsCollectionType(propertyValue)
                    ? ToDictionaryOrList(propertyValue)
                    : propertyValue;
            }
        }

        return keyValuePairs;
    }

    // 创建属性访问器数组
    private static PropertyAccessor[] CreatePropertyAccessors(Type type)
    {
        var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        var accessors = new List<PropertyAccessor>(properties.Length);

        foreach (var property in properties)
        {
            var parameter = Expression.Parameter(typeof(object), "obj");
            var castParameter = Expression.Convert(parameter, type);
            var propertyAccess = Expression.Property(castParameter, property);
            var convertPropertyAccess = Expression.Convert(propertyAccess, typeof(object));
            var getter = Expression.Lambda<Func<object, object>>(convertPropertyAccess, parameter).Compile();

            // 使用缓存检查属性是否具有 ImagesAttribute 特性
            bool hasImagesAttribute = GetHasImagesAttribute(property, _PropertyCache);

            accessors.Add(new PropertyAccessor(property.Name, getter, hasImagesAttribute));
        }

        return accessors.ToArray();
    }

    // 检查属性是否具有 ImagesAttribute 特性，并缓存结果
    private static bool GetHasImagesAttribute(PropertyInfo property, ConcurrentDictionary<PropertyInfo, bool> propertyCache)
    {
        if (propertyCache.TryGetValue(property, out bool hasImagesAttribute))
        {
            return hasImagesAttribute;
        }

        hasImagesAttribute = property.GetCustomAttribute<ImagesAttribute>() != null;
        propertyCache[property] = hasImagesAttribute;

        return hasImagesAttribute;
    }

    // 属性访问器类，包含属性名、获取器和特性标志
    private class PropertyAccessor
    {
        public string PropertyName { get; }
        public Func<object, object> Getter { get; }
        public bool HasImagesAttribute { get; }

        public PropertyAccessor(string propertyName, Func<object, object> getter, bool hasImagesAttribute)
        {
            PropertyName = propertyName;
            Getter = getter;
            HasImagesAttribute = hasImagesAttribute;
        }
    }
}

[Obsolete]
public static class ObjectExtensions7
{
    private static readonly ConcurrentDictionary<Type, PropertyAccessor[]> PropertyCache = new();
    private static readonly ConcurrentDictionary<PropertyInfo, bool> _PropertyCache = new();

    public static bool IsPrimitiveType(object obj) =>
        obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType);

    public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string;

    public static object ToDictionaryOrList(object obj)
    {
        if (obj == null) return null;

        return obj switch
        {
            _ when IsPrimitiveType(obj) => obj,
            IEnumerable enumerable => TransformCollection(enumerable),
            _ => TransformObject(obj)
        };
    }

    private static List<object> TransformCollection(IEnumerable enumerable)
    {
        var list = new List<object>(enumerable is ICollection collection ? collection.Count : 10);
        foreach (var item in enumerable)
        {
            list.Add(ToDictionaryOrList(item));
        }
        return list;
    }

    private static Dictionary<string, object> TransformObject(object obj)
    {
        var type = obj.GetType();
        var accessors = PropertyCache.GetOrAdd(type, CreatePropertyAccessors);
        var keyValuePairs = new Dictionary<string, object>(accessors.Length);

        foreach (var accessor in accessors)
        {
            var propertyValue = accessor.Getter(obj);
            keyValuePairs[accessor.PropertyName] = accessor.HasImagesAttribute
                ? $"image{propertyValue}"
                : IsCollectionType(propertyValue) ? ToDictionaryOrList(propertyValue) : propertyValue;
        }

        return keyValuePairs;
    }

    private static PropertyAccessor[] CreatePropertyAccessors(Type type)
    {
        var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        return properties.Select(property =>
        {
            var getter = CreatePropertyGetter(type, property);
            bool hasImagesAttribute = _PropertyCache.GetOrAdd(property, p => p.GetCustomAttribute<ImagesAttribute>() != null);
            return new PropertyAccessor(property.Name, getter, hasImagesAttribute);
        }).ToArray();
    }

    private static Func<object, object> CreatePropertyGetter(Type type, PropertyInfo property)
    {
        var parameter = Expression.Parameter(typeof(object), "obj");
        var castParameter = Expression.Convert(parameter, type);
        var propertyAccess = Expression.Property(castParameter, property);
        var convertPropertyAccess = Expression.Convert(propertyAccess, typeof(object));
        return Expression.Lambda<Func<object, object>>(convertPropertyAccess, parameter).Compile();
    }

    private class PropertyAccessor
    {
        public string PropertyName { get; }
        public Func<object, object> Getter { get; }
        public bool HasImagesAttribute { get; }

        public PropertyAccessor(string propertyName, Func<object, object> getter, bool hasImagesAttribute)
        {
            PropertyName = propertyName;
            Getter = getter;
            HasImagesAttribute = hasImagesAttribute;
        }
    }
}

