using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Fantasy.Assembly;
using Fantasy.Helper;
using Fantasy.Platform.Net;
using Fantasy.Serialize;
using Newtonsoft.Json.Linq;

// ReSharper disable SuspiciousTypeConversion.Global

namespace Fantasy.ConfigTable
{
    /// <summary>
    /// 配置表帮助类
    /// </summary>
    public static class ConfigTableHelper
    {
        private static readonly Dictionary<Type, IConfigContext> _dictionary = new Dictionary<Type, IConfigContext>();

        /// <summary>
        /// 初始化ConfigTableHelper
        /// </summary>
        public static void Initialize(string json, params System.Reflection.Assembly[] assemblies)
        {
            var jsonObj = JObject.Parse(json);
            Dictionary<string, JArray> tokens = new();
            foreach (var item in jsonObj)
            {
                try
                {
                    var name = item.Key;
                    var value = item.Value;
                    if (value is JArray jArray)
                    {
                        tokens[name] = jArray;
                    }
                }
                catch (Exception e)
                {
                    Log.Error($"读表异常，请检查，name={item.Key} ex={e}");
                }
            }

            foreach (var type in GetAllConfigTableTypes(assemblies))
            {
                var name = type.Name;
                if (tokens.TryGetValue(name, out var jArray))
                {
                    // 通过反射调用 ParseJson 方法
                    var parseMethod = type.GetMethod("ParseJson", BindingFlags.Public | BindingFlags.Static);
                    parseMethod?.Invoke(null, [jArray]);
                }
            }

            var d = _dictionary;
        }

        public static ConfigContext<T> Table<T>() where T : IConfigTable
        {
            var type = typeof(T);
            if (_dictionary.TryGetValue(type, out var context))
            {
                return context as ConfigContext<T>;
            }

            var jsonContext = new ConfigContext<T>();
            _dictionary[type] = jsonContext;
            return jsonContext;
        }

        public static List<T> ParseLine<T>(JArray arr) where T : IConfigTable, new()
        {
            List<T> list = new List<T>();
            foreach (var jToken in arr)
            {
                T instance = jToken.ToObject<T>();

                if (instance != null)
                {
                    list.Add(instance);
                }
            }

            var context = Table<T>();
            context.Association(list);

            return list;
        }

        /// <summary>
        /// 获取所有实现了 IConfigTable 接口的非抽象类
        /// </summary>
        /// <returns>所有非抽象的配置对象类</returns>
        private static List<Type> GetAllConfigTableTypes(params System.Reflection.Assembly[] assemblies)
        {
            var types = new List<Type>();
            var interfaceType = typeof(IConfigTable);

            // 遍历当前程序集中的所有类型
            foreach (var assembly in assemblies)
            {
                foreach (var type in assembly.GetTypes())
                {
                    // 检查是否实现了 IConfigTable 接口，并且不是抽象类
                    if (interfaceType.IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface)
                    {
                        types.Add(type);
                    }
                }
            }

            return types;
        }

        // private static string _configTableBinaryDirectory;
        // private static readonly object Lock = new object();
        // // 配置表数据缓存字典
        // private static readonly Dictionary<string, ASerialize> ConfigDic = new ();
        // /// <summary>
        // /// 初始化ConfigTableHelper
        // /// </summary>
        // /// <param name="configTableBinaryDirectory"></param>
        // public static void Initialize(string configTableBinaryDirectory)
        // {
        //     _configTableBinaryDirectory = configTableBinaryDirectory;
        // }
        // /// <summary>
        // /// 加载配置表数据
        // /// </summary>
        // /// <typeparam name="T">配置表类型</typeparam>
        // /// <returns>配置表数据</returns>
        // public static T Load<T>() where T : ASerialize
        // {
        //     lock (Lock)
        //     {
        //         try
        //         {
        //             var dataConfig = typeof(T).Name;
        //
        //             if (ConfigDic.TryGetValue(dataConfig, out var aProto))
        //             {
        //                 return (T)aProto;
        //             }
        //            
        //             var configFile = GetConfigPath(dataConfig);
        //             var bytes = File.ReadAllBytes(configFile);
        //             // Log.Debug($"dataConfig:{dataConfig} {bytes.Length}");
        //             var data = SerializerManager.GetSerializer(FantasySerializerType.ProtoBuf).Deserialize<T>(bytes);
        //             ConfigDic[dataConfig] = data;
        //             return data;
        //         }
        //         catch (Exception ex)
        //         {
        //             throw new Exception($"ConfigTableManage:{typeof(T).Name} 数据表加载之后反序列化时出错:{ex}");
        //         }
        //     }
        // }
        //
        // /// <summary>
        // /// 获取配置表文件路径
        // /// </summary>
        // /// <param name="name">配置表名称</param>
        // /// <returns>配置表文件路径</returns>
        // private static string GetConfigPath(string name)
        // {
        //     var configFile = Path.Combine(_configTableBinaryDirectory, $"{name}.bytes");
        //
        //     if (File.Exists(configFile))
        //     {
        //         return configFile;
        //     }
        //
        //     throw new FileNotFoundException($"{name}.byte not found: {configFile}");
        // }
        //
        // /// <summary>
        // /// 重新加载配置表数据
        // /// </summary>
        // public static void ReLoadConfigTable()
        // {
        //     lock (Lock)
        //     {
        //         foreach (var (_, aProto) in ConfigDic)
        //         {
        //             ((IDisposable) aProto).Dispose();
        //         }
        //
        //         ConfigDic.Clear();
        //     }
        // }
    }
}