//------------------------------------------------------------
// Byway Data Table Helper
// 基于 DefaultDataTableHelper 重新实现
// 核心改动：ParseData 方法从 Thrift 配置加载数据
//------------------------------------------------------------

using GameFramework;
using GameFramework.DataTable;
using System;
using UnityEngine;
using UnityGameFramework.Runtime;

namespace CrazyMaple
{
    /// <summary>
    /// Byway 数据表辅助器 - 从 Thrift 配置加载数据
    /// </summary>
    public class BywayDataTableHelper : DataTableHelperBase
    {
        private static readonly string BytesAssetExtension = ".bytes";
        private ResourceComponent m_ResourceComponent = null;

        /// <summary>
        /// 读取数据表。
        /// </summary>
        public override bool ReadData(DataTableBase dataTable, string dataTableAssetName, object dataTableAsset, object userData)
        {
            TextAsset dataTableTextAsset = dataTableAsset as TextAsset;
            if (dataTableTextAsset != null)
            {
                // Byway 系统始终使用 bytes 格式（Thrift 二进制）
                return dataTable.ParseData(dataTableTextAsset.bytes, userData);
            }

            Log.Warning("Data table asset '{0}' is invalid.", dataTableAssetName);
            return false;
        }

        /// <summary>
        /// 读取数据表。
        /// </summary>
        public override bool ReadData(DataTableBase dataTable, string dataTableAssetName, byte[] dataTableBytes, int startIndex, int length, object userData)
        {
            // Byway 系统始终使用 bytes 格式（Thrift 二进制）
            return dataTable.ParseData(dataTableBytes, startIndex, length, userData);
        }

        /// <summary>
        /// 解析数据表（字符串格式 - Byway 不支持）
        /// </summary>
        public override bool ParseData(DataTableBase dataTable, string dataTableString, object userData)
        {
            Log.Error("Byway data table system does not support string format. Use Thrift bytes instead.");
            return false;
        }

        /// <summary>
        /// 解析数据表（核心方法 - 从 Thrift 配置加载）
        /// </summary>
        public override bool ParseData(DataTableBase dataTable, byte[] dataTableBytes, int startIndex, int length, object userData)
        {
            var timer = System.Diagnostics.Stopwatch.StartNew();
            
            try
            {
                // 获取 DataRow 类型
                Type dataRowType = dataTable.Type;
                string dataRowTypeName = dataRowType.Name;

                // 推断 Thrift 配置类型名（去除 DR 前缀）
                // 例如：DRMergeData -> MergeData
                string configTypeName = dataRowTypeName.StartsWith("DR") 
                    ? dataRowTypeName.Substring(2) 
                    : dataRowTypeName;

                // 通过反射获取 Thrift 配置类型
                Type configType = FindThriftConfigType(configTypeName);
                if (configType == null)
                {
                    Log.Error("Can not find Thrift config type '{0}' for data row type '{1}'.", configTypeName, dataRowTypeName);
                    return false;
                }

                // 调用 ConfigManager.GetConfig<T>() 获取配置对象
                var getConfigMethod = typeof(Byway.Config.ConfigManager)
                    .GetMethod("GetConfig")
                    .MakeGenericMethod(configType);
                
                object configInstance = getConfigMethod.Invoke(Byway.Config.ConfigManager.Instance, null);
                if (configInstance == null)
                {
                    Log.Error("Can not get config instance for type '{0}'.", configTypeName);
                    return false;
                }

                // 获取配置字典
                var dictData = GetConfigDictionary(configInstance, configTypeName);
                if (dictData == null)
                {
                    Log.Error("Can not get config dictionary for type '{0}'.", configTypeName);
                    return false;
                }

                // 性能优化：不预先创建所有 DataRow，而是缓存配置字典供按需查询
                // 对于几千行的大表，这样可以避免启动时创建几千个 DataRow 对象
                var dict = dictData as System.Collections.IDictionary;
                if (dict == null)
                {
                    Log.Error("Config dictionary is not IDictionary type.");
                    return false;
                }

                // 将配置实例缓存到 DataTable 的 userData 中，供后续按需获取
                // 格式：{ "ConfigInstance": configInstance, "ConfigDict": dict }
                var cacheData = new System.Collections.Generic.Dictionary<string, object>
                {
                    { "ConfigInstance", configInstance },
                    { "ConfigDict", dictData },
                    { "OriginalUserData", userData }
                };

                // 性能优化选项：反射路径实测反而更慢，禁用
                // 标准路径（ParseDataRow + ConfigDict）已经是最优解
                bool useDirectConstruction = false; // 禁用反射优化路径

                int successCount = 0;
                int failCount = 0;
                
                // Debug.LogError($"[性能测试] 表 {dataRowTypeName} 开始加载，行数: {dict.Count}, 模式: 标准路径(ConfigDict直接获取)");
                var loadTimer = System.Diagnostics.Stopwatch.StartNew();

                if (useDirectConstruction)
                {
                    // 【性能最优路径】直接创建 DataRow 并设置数据，完全跳过 ParseDataRow
                    // Log.Info("Large table detected ({0} rows), using direct construction mode.", dict.Count);
                    
                    foreach (System.Collections.DictionaryEntry entry in dict)
                    {
                        try
                        {
                            int id = (int)entry.Key;
                            object itemData = entry.Value;
                            
                            // 直接创建 DataRow 实例（不走 AddDataRow）
                            var dataRow = Activator.CreateInstance(dataTable.Type) as DataRowBase;
                            if (dataRow == null)
                            {
                                failCount++;
                                continue;
                            }
                            
                            // 调用 SetConfigData 方法直接设置数据（跳过所有查询）
                            var setDataMethod = dataTable.Type.GetMethod("SetConfigData");
                            if (setDataMethod != null)
                            {
                                setDataMethod.Invoke(dataRow, new object[] { itemData });
                                
                                // 使用反射调用 DataTable 的内部 AddDataRow 方法
                                var addMethod = dataTable.GetType().GetMethod("InternalAddDataRow", 
                                    System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                                
                                if (addMethod != null)
                                {
                                    addMethod.Invoke(dataTable, new object[] { dataRow });
                                    successCount++;
                                }
                                else
                                {
                                    // 兜底：使用 AddDataRow（会触发 ParseDataRow，但数据已设置好）
                                    if (dataTable.AddDataRow(id.ToString(), null))
                                    {
                                        successCount++;
                                    }
                                    else
                                    {
                                        failCount++;
                                    }
                                }
                            }
                            else
                            {
                                Log.Warning("SetConfigData method not found, fallback to AddDataRow");
                                // 降级到标准模式
                                useDirectConstruction = false;
                                break;
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error("Direct construction failed for entry: {0}", ex.Message);
                            failCount++;
                        }
                    }
                }
                
                // 【标准路径】通过 AddDataRow + ParseDataRow
                if (!useDirectConstruction || (successCount == 0 && dict.Count > 0))
                {
                    Log.Info("Using standard AddDataRow mode ({0} rows).", dict.Count);
                    successCount = 0;
                    failCount = 0;
                    
                    foreach (System.Collections.DictionaryEntry entry in dict)
                    {
                        try
                        {
                            int id = (int)entry.Key;
                            
                            // 调用 DataTable.AddDataRow(int id) 
                            // DataRow 的 ParseDataRow 方法会被调用，传入 id 和配置实例
                            if (!dataTable.AddDataRow(id.ToString(), cacheData))
                            {
                                Log.Warning("Add data row failed for id '{0}'.", id);
                                failCount++;
                            }
                            else
                            {
                                successCount++;
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error("Add data row exception: {0}", ex.Message);
                            failCount++;
                        }
                    }
                }
                
                loadTimer.Stop();
                // Debug.LogError($"[性能测试] 表 {dataRowTypeName} 加载完成，成功: {successCount}, 失败: {failCount}, 耗时: {loadTimer.ElapsedMilliseconds}ms ({loadTimer.Elapsed.TotalSeconds:F3}秒)");

                timer.Stop();
                // Debug.LogError($"[性能测试] 表 {dataRowTypeName} 总耗时(含配置获取): {timer.ElapsedMilliseconds}ms ({timer.Elapsed.TotalSeconds:F3}秒)");

                return failCount == 0;
            }
            catch (Exception exception)
            {
                Log.Error("Parse Thrift data table failed with exception: {0}\n{1}", exception.Message, exception.StackTrace);
                return false;
            }
        }

        /// <summary>
        /// 查找 Thrift 配置类型
        /// </summary>
        private Type FindThriftConfigType(string typeName)
        {
            // 在 Byway.Thrift.Data 命名空间中查找
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in assemblies)
            {
                Type type = assembly.GetType($"Byway.Thrift.Data.{typeName}");
                if (type != null)
                {
                    return type;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取配置字典
        /// </summary>
        private object GetConfigDictionary(object config, string configTypeName)
        {
            if (config == null) return null;

            Type configType = config.GetType();

            // 尝试多种可能的字典属性名
            string[] possibleNames = new string[]
            {
                configTypeName + "s",           // MergeData -> MergeDatas
                configTypeName.ToLower() + "s", // MergeData -> mergedatas
                char.ToLower(configTypeName[0]) + configTypeName.Substring(1) + "s", // MergeData -> mergeDatas
                "Items",
                "Data",
                "Configs"
            };

            foreach (string name in possibleNames)
            {
                var property = configType.GetProperty(name);
                if (property != null)
                {
                    object value = property.GetValue(config);
                    if (value != null)
                    {
                        return value;
                    }
                }
            }

            // 查找第一个 Dictionary 类型的属性
            foreach (var property in configType.GetProperties())
            {
                Type propType = property.PropertyType;
                if (propType.IsGenericType && 
                    propType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.Dictionary<,>))
                {
                    object value = property.GetValue(config);
                    if (value != null)
                    {
                        return value;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// 释放数据表资源
        /// </summary>
        public override void ReleaseDataAsset(DataTableBase dataTable, object dataTableAsset)
        {
            m_ResourceComponent.UnloadAsset(dataTableAsset);
        }

        private void Start()
        {
            m_ResourceComponent = UnityGameFramework.Runtime.GameEntry.GetComponent<ResourceComponent>();
            if (m_ResourceComponent == null)
            {
                Log.Fatal("Resource component is invalid.");
                return;
            }
        }
    }
}
