using System.Reflection;
using NBC.Network.Interface;
using NBC.Serialize;

namespace FantasyNetTest;

public static class CoderLoader
{
    private static List<Type> _types = new List<Type>();

    private static List<Type> _requestTypes = new List<Type>();

    public static List<Type> RequestTypes => _requestTypes.ToList();

    public static void Load()
    {
        var reqTpe = typeof(IRequest);
        var types = GetAllDerivedTypes(typeof(AMessage));
        _requestTypes.Clear();
        foreach (var type in types)
        {
            // 精确判断：直接实现的接口（不包括继承的接口）
            var interfaces = type.GetInterfaces();
            if (interfaces.Contains(reqTpe) && !type.IsAbstract)
            {
                if (interfaces.Contains(typeof(IRouteMessage)) && !interfaces.Contains(typeof(ICustomRouteRequest)))
                {
                    continue;
                }
                _requestTypes.Add(type);
            }
        }

        _types.AddRange(types);
    }

    public static List<Type> GetAllDerivedTypes(Type baseType)
    {
        var derivedTypes = new List<Type>();

        // 获取当前应用程序域中所有已加载的程序集
        var assemblies = AppDomain.CurrentDomain.GetAssemblies();

        foreach (var assembly in assemblies)
        {
            try
            {
                // 获取程序集中所有类型
                var types = assembly.GetTypes()
                    .Where(t => t != baseType && baseType.IsAssignableFrom(t) && !t.IsAbstract);

                derivedTypes.AddRange(types);
            }
            catch (ReflectionTypeLoadException ex)
            {
                // 处理部分类型加载失败的情况
                var loadedTypes = ex.Types.Where(t => t != null);
                var types = loadedTypes
                    .Where(t => t != baseType && baseType.IsAssignableFrom(t) && !t.IsAbstract);

                derivedTypes.AddRange(types);
            }
        }

        return derivedTypes;
    }

    public static Type? GetTypeByName(string name)
    {
        foreach (var type in _types)
        {
            if (type.Name == name)
            {
                return type;
            }
        }

        return null;
    }

    public static void SetPropertyValue(this object self, string name, object? value)
    {
        if (self == null || value == null) return;
        var propertyUsername = self.GetType()
            .GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        if (propertyUsername != null && propertyUsername.CanWrite)
        {
            propertyUsername.SetValue(self, value);
        }
    }

    public static object? GetFieldValue(this object obj, string fieldName)
    {
        Type type = obj.GetType();
        FieldInfo? field = type.GetField(fieldName); // 默认只查找公共实例字段

        if (field == null)
        {
            throw new ArgumentException($"字段 '{fieldName}' 未找到");
        }

        return field.GetValue(obj);
    }

    public static object? GetPropertyValue(this object obj, string fieldName)
    {
        Type type = obj.GetType();
        var ps = type.GetProperties();
        foreach (var propertyInfo in ps)
        {
            if (propertyInfo.Name == fieldName)
            {
            }
        }

        PropertyInfo? field = type.GetProperty(fieldName); // 默认只查找公共实例字段

        if (field == null)
        {
            throw new ArgumentException($"属性 '{fieldName}' 未找到");
        }

        return field.GetValue(obj);
    }
}