using UnityEngine;
using UnityGameFramework.Runtime;
using System.Collections.Generic;
using System.Linq;
using ArtResource;
using GameFramework.Resource;
using Spine.Unity;
using System;

namespace CrazyMaple
{
    /// <summary>
    /// 美术资源运行时管理器（单例MonoBehaviour）- 优化版
    /// 三级缓存：SO缓存 -> Sprite缓存 -> Spine缓存
    /// 
    /// 改进点：
    /// 1. 增加初始化完成回调，支持外部等待
    /// 2. 正确实现AssetBundle资源加载（运行时）
    /// 3. 优化初始化时序，避免竞态条件
    /// 4. 支持预加载配置（从manifest读取）
    /// </summary>
    public class ArtResourceManager : MonoBehaviour
    {
        private static ArtResourceManager instance;
        public static ArtResourceManager Instance
        {
            get
            {
                if (instance == null)
                {
                    GameObject go = new GameObject("ArtResourceManager");
                    instance = go.AddComponent<ArtResourceManager>();
                    DontDestroyOnLoad(go);
                }
                return instance;
            }
        }

        #region 缓存结构

        /// <summary>
        /// 常量：SO文件夹路径
        /// </summary>
        private const string SO_ROOT_PATH = "Assets/Art_SubModule/Art_SO";

        /// <summary>
        /// SO文件缓存（启动时一次性加载所有SO，速度快~几十毫秒）
        /// Key: TableId
        /// </summary>
        private Dictionary<int, ArtTableSO> allTables = new Dictionary<int, ArtTableSO>();

        /// <summary>
        /// SO名称索引（支持按Name查询）
        /// Key: TableName
        /// </summary>
        private Dictionary<string, ArtTableSO> tablesByName = new Dictionary<string, ArtTableSO>();

        /// <summary>
        /// Sprite资源缓存（重量级，按需加载）
        /// Key: "tableId_itemId"
        /// </summary>
        private Dictionary<string, Sprite> loadedSprites = new Dictionary<string, Sprite>();

        /// <summary>
        /// Spine资源缓存（重量级，按需加载）
        /// Key: "tableId_itemId"
        /// </summary>
        private Dictionary<string, SkeletonDataAsset> loadedSpines = new Dictionary<string, SkeletonDataAsset>();

        /// <summary>
        /// 正在加载的表资源（防止重复加载）
        /// Key: TableId, Value: 回调列表
        /// </summary>
        private Dictionary<int, List<Action<bool>>> loadingTables = new Dictionary<int, List<Action<bool>>>();

        /// <summary>
        /// 正在加载的Sprite（防止重复加载）
        /// Key: "tableId_itemId", Value: 回调列表
        /// </summary>
        private Dictionary<string, List<Action<Sprite>>> loadingSprites = new Dictionary<string, List<Action<Sprite>>>();

        /// <summary>
        /// 正在加载的Spine（防止重复加载）
        /// Key: "tableId_itemId", Value: 回调列表
        /// </summary>
        private Dictionary<string, List<Action<SkeletonDataAsset>>> loadingSpines = new Dictionary<string, List<Action<SkeletonDataAsset>>>();

        /// <summary>
        /// SO是否已初始化完成
        /// </summary>
        private bool isInitialized = false;

        /// <summary>
        /// 初始化完成时的回调列表
        /// </summary>
        private List<Action<bool>> initializeCallbacks = new List<Action<bool>>();

        /// <summary>
        /// Manifest数据（包含预加载配置）
        /// </summary>
        private ArtTableManifest manifest;

        #endregion

        private void Awake()
        {
            if (instance != null && instance != this)
            {
                Destroy(gameObject);
                return;
            }

            instance = this;
            DontDestroyOnLoad(gameObject);

            // 不在Awake中自动初始化，等待外部调用
            // 这样可以让ProcedurePreload控制初始化时机
        }

        #region 初始化

        /// <summary>
        /// 初始化：加载所有ArtTableSO（异步回调方式）
        /// 建议在ProcedurePreload中调用，并等待回调完成
        /// </summary>
        /// <param name="onComplete">初始化完成回调（true=成功，false=失败）</param>
        public void Initialize(Action<bool> onComplete = null)
        {
            if (isInitialized)
            {
                Debug.LogWarning("[ArtResourceManager] 已初始化，直接执行回调");
                onComplete?.Invoke(true);
                return;
            }

            // 加入回调队列
            if (onComplete != null)
            {
                initializeCallbacks.Add(onComplete);
            }

            // 如果已经在加载中，直接返回
            if (initializeCallbacks.Count > 1)
            {
                Debug.Log("[ArtResourceManager] 正在初始化中，已加入回调队列");
                return;
            }

            var startTime = Time.realtimeSinceStartup;
            Debug.Log("[ArtResourceManager] 开始加载所有ArtTableSO...");

            // Editor和Runtime统一使用GameEntry.Resource.LoadAsset
            LoadAllTables(success =>
            {
                var duration = (Time.realtimeSinceStartup - startTime) * 1000f;
                
                if (success)
                {
                    isInitialized = true;
                    Debug.Log($"[ArtResourceManager] SO初始化完成: {allTables.Count} 个表，耗时 {duration:F2}ms");
                    
                    // 自动预加载配置的表
                    AutoPreloadTables();
                }
                else
                {
                    Debug.LogError("[ArtResourceManager] SO初始化失败");
                }

                // 通知所有等待的回调
                var callbacks = new List<Action<bool>>(initializeCallbacks);
                initializeCallbacks.Clear();
                foreach (var callback in callbacks)
                {
                    callback?.Invoke(success);
                }
            });
        }

        /// <summary>
        /// 加载所有SO文件（只加载SO本身，不加载引用的资源）
        /// 需要先加载索引文件 art_table_manifest.json，获取所有SO的AssetName列表
        /// </summary>
        private void LoadAllTables(Action<bool> onComplete)
        {
            const string manifestPath = "Assets/Art_SubModule/Art_SO/art_table_manifest.json";

            // 创建加载回调
            var loadCallbacks = new LoadAssetCallbacks(
                // 成功回调
                (assetName, asset, duration, userData) =>
                {
                    var manifestAsset = asset as TextAsset;
                    if (manifestAsset == null)
                    {
                        Debug.LogError($"[ArtResourceManager] 索引文件格式错误: {manifestPath}");
                        onComplete?.Invoke(false);
                        return;
                    }

                    // 解析JSON获取所有SO路径
                    manifest = JsonUtility.FromJson<ArtTableManifest>(manifestAsset.text);

                    if (manifest == null || manifest.tablePaths == null || manifest.tablePaths.Length == 0)
                    {
                        Debug.LogError("[ArtResourceManager] 索引文件为空，没有找到任何SO");
                        onComplete?.Invoke(false);
                        return;
                    }

                    // 遍历加载所有SO
                    int totalCount = manifest.tablePaths.Length;
                    int loadedCount = 0;
                    int failedCount = 0;
                    var soLoadStartTime = Time.realtimeSinceStartup;
                    var soLoadTimes = new List<(string path, float ms)>();

                    Debug.Log($"[ArtResourceManager] 开始加载 {totalCount} 个SO文件...");

                    foreach (var assetPath in manifest.tablePaths)
                    {
                        LoadSingleTable(assetPath, (success, loadTime) =>
                        {
                            if (success)
                            {
                                loadedCount++;
                                soLoadTimes.Add((assetPath, loadTime));
                            }
                            else
                                failedCount++;

                            // 检查是否全部加载完成
                            if (loadedCount + failedCount >= totalCount)
                            {
                                var totalDuration = (Time.realtimeSinceStartup - soLoadStartTime) * 1000f;
                                bool allSuccess = failedCount == 0;
                                
                                Debug.Log($"[ArtResourceManager] SO加载完成: 成功={loadedCount}, 失败={failedCount}, 总计={totalCount}, 总耗时={totalDuration:F2}ms");
                                
                                // 显示最慢的前5个SO
                                if (soLoadTimes.Count > 0)
                                {
                                    var slowest = soLoadTimes.OrderByDescending(x => x.ms).Take(5).ToList();
                                    Debug.Log($"[ArtResourceManager] 最慢的{slowest.Count}个SO:");
                                    foreach (var item in slowest)
                                    {
                                        Debug.Log($"  - {item.path}: {item.ms:F2}ms");
                                    }
                                }
                                
                                onComplete?.Invoke(allSuccess);
                            }
                        });
                    }
                },
                // 失败回调
                (assetName, status, errorMessage, userData) =>
                {
                    Debug.LogError($"[ArtResourceManager] 加载索引文件失败: {manifestPath}, {errorMessage}");
                    Debug.LogError("[ArtResourceManager] 请在Editor下运行工具生成art_table_manifest.json");
                    onComplete?.Invoke(false);
                }
            );

            // 使用GameEntry.Resource.LoadAsset加载索引文件
            GameEntry.Resource.LoadAsset(manifestPath, typeof(TextAsset), loadCallbacks);
        }

        /// <summary>
        /// 加载单个SO文件
        /// </summary>
        private void LoadSingleTable(string assetPath, Action<bool, float> onComplete)
        {
            var startTime = Time.realtimeSinceStartup;
            var loadCallbacks = new LoadAssetCallbacks(
                // 成功回调
                (assetName, asset, duration, userData) =>
                {
                    var loadTime = (Time.realtimeSinceStartup - startTime) * 1000f;
                    var table = asset as ArtTableSO;
                    if (table != null)
                    {
                        RegisterTable(table, assetPath);
                        onComplete?.Invoke(true, loadTime);
                    }
                    else
                    {
                        Debug.LogError($"[ArtResourceManager] 加载SO失败: {assetPath}");
                        onComplete?.Invoke(false, loadTime);
                    }
                },
                // 失败回调
                (assetName, status, errorMessage, userData) =>
                {
                    var loadTime = (Time.realtimeSinceStartup - startTime) * 1000f;
                    Debug.LogError($"[ArtResourceManager] 加载SO异常 [{assetPath}]: {errorMessage}");
                    onComplete?.Invoke(false, loadTime);
                }
            );

            // 使用GameEntry.Resource.LoadAsset加载SO
            GameEntry.Resource.LoadAsset(assetPath, typeof(ArtTableSO), loadCallbacks);
        }

        /// <summary>
        /// 注册SO到缓存
        /// 注意：路径已经在ArtItemData中存储，无需额外缓存
        /// </summary>
        private void RegisterTable(ArtTableSO table, string tablePath)
        {
            if (allTables.ContainsKey(table.TableId))
            {
                Debug.LogWarning($"[ArtResourceManager] 表ID重复: {table.TableId} ({table.TableName})");
                return;
            }

            allTables[table.TableId] = table;
            
            if (!string.IsNullOrEmpty(table.TableName))
            {
                if (tablesByName.ContainsKey(table.TableName))
                {
                    Debug.LogWarning($"[ArtResourceManager] 表名称重复: {table.TableName}");
                }
                else
                {
                    tablesByName[table.TableName] = table;
                }
            }

            Debug.Log($"[ArtResourceManager] 注册表: {table.TableId} - {table.TableName} ({table.Items.Count} 项)");
        }

        /// <summary>
        /// 自动预加载manifest中配置的表
        /// </summary>
        private void AutoPreloadTables()
        {
            if (manifest == null || manifest.preloadTableIds == null || manifest.preloadTableIds.Length == 0)
            {
                Debug.Log("[ArtResourceManager] 没有配置自动预加载的表");
                return;
            }

            Debug.Log($"[ArtResourceManager] 开始自动预加载 {manifest.preloadTableIds.Length} 个表...");
            
            foreach (var tableId in manifest.preloadTableIds)
            {
                LoadTable(tableId, success =>
                {
                    if (success)
                    {
                        Debug.Log($"[ArtResourceManager] 自动预加载表 {tableId} 成功");
                    }
                    else
                    {
                        Debug.LogWarning($"[ArtResourceManager] 自动预加载表 {tableId} 失败");
                    }
                });
            }
        }

        /// <summary>
        /// 索引文件的数据结构（包含预加载配置）
        /// </summary>
        [Serializable]
        private class ArtTableManifest
        {
            public string[] tablePaths;
            public int[] preloadTableIds;
        }

        #endregion

        #region 表级资源加载

        /// <summary>
        /// 异步加载资源表的所有引用资源（Sprite + Spine）
        /// 适用场景：预加载关键表、界面预加载
        /// </summary>
        /// <param name="tableId">表ID</param>
        /// <param name="onComplete">加载完成回调（true=成功，false=失败）</param>
        public void LoadTable(int tableId, Action<bool> onComplete = null)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                onComplete?.Invoke(false);
                return;
            }

            // 检查表是否存在
            if (!allTables.TryGetValue(tableId, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] LoadTable失败: 找不到表ID {tableId}");
                onComplete?.Invoke(false);
                return;
            }

            // 检查是否正在加载
            if (loadingTables.ContainsKey(tableId))
            {
                Debug.Log($"[ArtResourceManager] 资源表 {tableId} 正在加载中，加入回调队列");
                loadingTables[tableId].Add(onComplete);
                return;
            }

            // 开始加载
            loadingTables[tableId] = new List<Action<bool>> { onComplete };
            Debug.Log($"[ArtResourceManager] 开始预加载资源表 {tableId} ({table.TableName}) 的所有资源（共 {table.Items.Count} 项）");

            int totalCount = 0;
            int loadedCount = 0;
            int failedCount = 0;

            // 统计需要加载的资源数量
            foreach (var item in table.Items)
            {
                // 检查Sprite是否需要加载（有引用或有路径）
                if (item.Sprite != null || !string.IsNullOrEmpty(item.SpritePath))
                {
                    totalCount++;
                }
                
                // 检查Spine是否需要加载（有引用或有路径）
                if (item.SpineAsset != null || !string.IsNullOrEmpty(item.SpineAssetPath))
                {
                    totalCount++;
                }
            }

            if (totalCount == 0)
            {
                Debug.LogWarning($"[ArtResourceManager] 资源表 {tableId} 没有任何Sprite或Spine资源");
                NotifyLoadTableComplete(tableId, true);
                return;
            }

            // 加载所有资源
            foreach (var item in table.Items)
            {
                // 加载Sprite
                if (item.Sprite != null || !string.IsNullOrEmpty(item.SpritePath))
                {
                    PreloadSprite(tableId, item.Id, item, success =>
                    {
                        if (success) loadedCount++;
                        else failedCount++;

                        CheckComplete();
                    });
                }

                // 加载Spine
                if (item.SpineAsset != null || !string.IsNullOrEmpty(item.SpineAssetPath))
                {
                    PreloadSpine(tableId, item.Id, item, success =>
                    {
                        if (success) loadedCount++;
                        else failedCount++;

                        CheckComplete();
                    });
                }
            }

            void CheckComplete()
            {
                if (loadedCount + failedCount >= totalCount)
                {
                    bool allSuccess = failedCount == 0;
                    Debug.Log($"[ArtResourceManager] 资源表 {tableId} 预加载完成: 成功={loadedCount}, 失败={failedCount}, 总计={totalCount}");
                    NotifyLoadTableComplete(tableId, allSuccess);
                }
            }
        }

        /// <summary>
        /// 按Name加载资源表
        /// </summary>
        public void LoadTableByName(string tableName, Action<bool> onComplete = null)
        {
            if (tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                LoadTable(table.TableId, onComplete);
            }
            else
            {
                Debug.LogError($"[ArtResourceManager] LoadTableByName失败: 找不到表名称 '{tableName}'");
                onComplete?.Invoke(false);
            }
        }

        /// <summary>
        /// 通知加载表完成
        /// </summary>
        private void NotifyLoadTableComplete(int tableId, bool success)
        {
            if (loadingTables.ContainsKey(tableId))
            {
                var callbacks = loadingTables[tableId];
                loadingTables.Remove(tableId);
                foreach (var callback in callbacks)
                {
                    callback?.Invoke(success);
                }
            }
        }

        #endregion

        #region 资源加载（运行时按需加载）

        /// <summary>
        /// 加载Sprite资源（表ID + 资源项ID）
        /// </summary>
        public void LoadSprite(int tableId, int itemId, Action<Sprite> onComplete)
        {
            LoadSpriteInternal(tableId, itemId, null, onComplete);
        }

        /// <summary>
        /// 加载Sprite资源（表ID + 资源项Name）
        /// </summary>
        public void LoadSprite(int tableId, string itemName, Action<Sprite> onComplete)
        {
            LoadSpriteInternal(tableId, null, itemName, onComplete);
        }

        /// <summary>
        /// 加载Sprite资源（表Name + 资源项ID）
        /// </summary>
        public void LoadSprite(string tableName, int itemId, Action<Sprite> onComplete)
        {
            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] LoadSprite失败: 找不到表名称 '{tableName}'");
                onComplete?.Invoke(null);
                return;
            }
            LoadSpriteInternal(table.TableId, itemId, null, onComplete);
        }

        /// <summary>
        /// 加载Sprite资源（表Name + 资源项Name）
        /// </summary>
        public void LoadSprite(string tableName, string itemName, Action<Sprite> onComplete)
        {
            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] LoadSprite失败: 找不到表名称 '{tableName}'");
                onComplete?.Invoke(null);
                return;
            }
            LoadSpriteInternal(table.TableId, null, itemName, onComplete);
        }

        /// <summary>
        /// 内部加载Sprite实现
        /// </summary>
        private void LoadSpriteInternal(int tableId, int? itemId, string itemName, Action<Sprite> onComplete)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                onComplete?.Invoke(null);
                return;
            }

            // 从SO中查找Item
            if (!allTables.TryGetValue(tableId, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] LoadSprite失败: 找不到表ID {tableId}");
                onComplete?.Invoke(null);
                return;
            }

            ArtItemData item;
            if (itemId.HasValue)
            {
                item = table.Items.FirstOrDefault(x => x.Id == itemId.Value);
                if (item == null)
                {
                    Debug.LogError($"[ArtResourceManager] LoadSprite失败: 资源表{tableId} ({table.TableName}) 中找不到ID为{itemId.Value} 的资源项");
                    onComplete?.Invoke(null);
                    return;
                }
            }
            else
            {
                item = table.Items.FirstOrDefault(x => x.Name == itemName);
                if (item == null)
                {
                    Debug.LogError($"[ArtResourceManager] LoadSprite失败: 资源表{tableId} ({table.TableName}) 中找不到Name为'{itemName}' 的资源项");
                    onComplete?.Invoke(null);
                    return;
                }
            }

            string cacheKey = $"{tableId}_{item.Id}";

            // 检查Sprite缓存
            if (loadedSprites.TryGetValue(cacheKey, out Sprite cachedSprite))
            {
                onComplete?.Invoke(cachedSprite);
                return;
            }

            // 检查是否正在加载
            if (loadingSprites.ContainsKey(cacheKey))
            {
                loadingSprites[cacheKey].Add(onComplete);
                return;
            }

            // 开始加载Sprite
            loadingSprites[cacheKey] = new List<Action<Sprite>> { onComplete };
            LoadSpriteAsset(item, sprite =>
            {
                // 缓存结果
                if (sprite != null)
                {
                    loadedSprites[cacheKey] = sprite;
                }

                // 通知所有等待的回调
                var callbacks = loadingSprites[cacheKey];
                loadingSprites.Remove(cacheKey);
                foreach (var callback in callbacks)
                {
                    callback?.Invoke(sprite);
                }
            });
        }

        /// <summary>
        /// 加载Spine资源（表ID + 资源项ID）
        /// </summary>
        public void LoadSpine(int tableId, int itemId, Action<SkeletonDataAsset, string> onComplete)
        {
            LoadSpineInternal(tableId, itemId, null, onComplete);
        }

        /// <summary>
        /// 加载Spine资源（表ID + 资源项Name）
        /// </summary>
        public void LoadSpine(int tableId, string itemName, Action<SkeletonDataAsset, string> onComplete)
        {
            LoadSpineInternal(tableId, null, itemName, onComplete);
        }

        /// <summary>
        /// 加载Spine资源（表Name + 资源项ID）
        /// </summary>
        public void LoadSpine(string tableName, int itemId, Action<SkeletonDataAsset, string> onComplete)
        {
            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] LoadSpine失败: 找不到表名称 '{tableName}'");
                onComplete?.Invoke(null, "");
                return;
            }
            LoadSpineInternal(table.TableId, itemId, null, onComplete);
        }

        /// <summary>
        /// 加载Spine资源（表Name + 资源项Name）
        /// </summary>
        public void LoadSpine(string tableName, string itemName, Action<SkeletonDataAsset, string> onComplete)
        {
            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] LoadSpine失败: 找不到表名称 '{tableName}'");
                onComplete?.Invoke(null, "");
                return;
            }
            LoadSpineInternal(table.TableId, null, itemName, onComplete);
        }

        /// <summary>
        /// 内部加载Spine实现
        /// </summary>
        private void LoadSpineInternal(int tableId, int? itemId, string itemName, Action<SkeletonDataAsset, string> onComplete)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                onComplete?.Invoke(null, "");
                return;
            }

            // 从SO中查找Item
            if (!allTables.TryGetValue(tableId, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] LoadSpine失败: 找不到表ID {tableId}");
                onComplete?.Invoke(null, "");
                return;
            }

            ArtItemData item;
            if (itemId.HasValue)
            {
                item = table.Items.FirstOrDefault(x => x.Id == itemId.Value);
                if (item == null)
                {
                    Debug.LogError($"[ArtResourceManager] LoadSpine失败: 资源表{tableId} ({table.TableName}) 中找不到ID为{itemId.Value} 的资源项");
                    onComplete?.Invoke(null, "");
                    return;
                }
            }
            else
            {
                item = table.Items.FirstOrDefault(x => x.Name == itemName);
                if (item == null)
                {
                    Debug.LogError($"[ArtResourceManager] LoadSpine失败: 资源表{tableId} ({table.TableName}) 中找不到Name为'{itemName}' 的资源项");
                    onComplete?.Invoke(null, "");
                    return;
                }
            }

            string cacheKey = $"{tableId}_{item.Id}";

            // 检查Spine缓存
            if (loadedSpines.TryGetValue(cacheKey, out SkeletonDataAsset cachedSpine))
            {
                onComplete?.Invoke(cachedSpine, item.SpineAnimName);
                return;
            }

            // 检查是否正在加载
            if (loadingSpines.ContainsKey(cacheKey))
            {
                loadingSpines[cacheKey].Add(spine =>
                {
                    onComplete?.Invoke(spine, item.SpineAnimName);
                });
                return;
            }

            // 开始加载Spine
            loadingSpines[cacheKey] = new List<Action<SkeletonDataAsset>> { spine =>
            {
                onComplete?.Invoke(spine, item.SpineAnimName);
            }};
            
            LoadSpineAsset(item, spine =>
            {
                // 缓存结果
                if (spine != null)
                {
                    loadedSpines[cacheKey] = spine;
                }

                // 通知所有等待的回调
                var callbacks = loadingSpines[cacheKey];
                loadingSpines.Remove(cacheKey);
                foreach (var callback in callbacks)
                {
                    callback?.Invoke(spine);
                }
            });
        }

        /// <summary>
        /// 预加载Sprite（内部方法）
        /// </summary>
        private void PreloadSprite(int tableId, int itemId, ArtItemData item, Action<bool> onComplete)
        {
            string cacheKey = $"{tableId}_{itemId}";
            
            if (loadedSprites.ContainsKey(cacheKey))
            {
                onComplete?.Invoke(true);
                return;
            }

            LoadSpriteAsset(item, sprite =>
            {
                if (sprite != null)
                {
                    loadedSprites[cacheKey] = sprite;
                    onComplete?.Invoke(true);
                }
                else
                {
                    onComplete?.Invoke(false);
                }
            });
        }

        /// <summary>
        /// 预加载Spine（内部方法）
        /// </summary>
        private void PreloadSpine(int tableId, int itemId, ArtItemData item, Action<bool> onComplete)
        {
            string cacheKey = $"{tableId}_{itemId}";
            
            if (loadedSpines.ContainsKey(cacheKey))
            {
                onComplete?.Invoke(true);
                return;
            }

            LoadSpineAsset(item, spine =>
            {
                if (spine != null)
                {
                    loadedSpines[cacheKey] = spine;
                    onComplete?.Invoke(true);
                }
                else
                {
                    onComplete?.Invoke(false);
                }
            });
        }

        /// <summary>
        /// 加载Sprite资源（同时支持Editor和Runtime模式）
        /// Editor模式：优先使用Sprite引用
        /// Runtime模式：使用SpritePath通过GameFramework加载
        /// </summary>
        private void LoadSpriteAsset(ArtItemData item, Action<Sprite> onComplete)
        {
            // Editor模式：直接使用引用
            if (item.Sprite != null)
            {
                onComplete?.Invoke(item.Sprite);
                return;
            }

            // Runtime模式：需要通过路径加载
            if (string.IsNullOrEmpty(item.SpritePath))
            {
                Debug.LogError($"[ArtResourceManager] Sprite资源引用和路径都为空: {item.Name}");
                onComplete?.Invoke(null);
                return;
            }

            var loadCallbacks = new LoadAssetCallbacks(
                // 成功回调
                (assetName, asset, duration, userData) =>
                {
                    var sprite = asset as Sprite;
                    if (sprite != null)
                    {
                        onComplete?.Invoke(sprite);
                    }
                    else
                    {
                        Debug.LogError($"[ArtResourceManager] 加载Sprite失败，资源类型错误: {item.SpritePath}");
                        onComplete?.Invoke(null);
                    }
                },
                // 失败回调
                (assetName, status, errorMessage, userData) =>
                {
                    Debug.LogError($"[ArtResourceManager] 加载Sprite异常 [{item.SpritePath}]: {errorMessage}");
                    onComplete?.Invoke(null);
                }
            );

            GameEntry.Resource.LoadAsset(item.SpritePath, typeof(Sprite), loadCallbacks);
        }

        /// <summary>
        /// 加载Spine资源（同时支持Editor和Runtime模式）
        /// Editor模式：优先使用SpineAsset引用
        /// Runtime模式：使用SpineAssetPath通过GameFramework加载
        /// </summary>
        private void LoadSpineAsset(ArtItemData item, Action<SkeletonDataAsset> onComplete)
        {
            // Editor模式：直接使用引用
            if (item.SpineAsset != null)
            {
                onComplete?.Invoke(item.SpineAsset);
                return;
            }

            // Runtime模式：需要通过路径加载
            if (string.IsNullOrEmpty(item.SpineAssetPath))
            {
                Debug.LogError($"[ArtResourceManager] Spine资源引用和路径都为空: {item.Name}");
                onComplete?.Invoke(null);
                return;
            }

            var loadCallbacks = new LoadAssetCallbacks(
                // 成功回调
                (assetName, asset, duration, userData) =>
                {
                    var spine = asset as SkeletonDataAsset;
                    if (spine != null)
                    {
                        onComplete?.Invoke(spine);
                    }
                    else
                    {
                        Debug.LogError($"[ArtResourceManager] 加载Spine失败，资源类型错误: {item.SpineAssetPath}");
                        onComplete?.Invoke(null);
                    }
                },
                // 失败回调
                (assetName, status, errorMessage, userData) =>
                {
                    Debug.LogError($"[ArtResourceManager] 加载Spine异常 [{item.SpineAssetPath}]: {errorMessage}");
                    onComplete?.Invoke(null);
                }
            );

            GameEntry.Resource.LoadAsset(item.SpineAssetPath, typeof(SkeletonDataAsset), loadCallbacks);
        }

        #endregion

        #region 查询方法

        /// <summary>
        /// 检查是否已初始化完成
        /// </summary>
        public bool IsInitialized => isInitialized;

        /// <summary>
        /// 获取Spine动画名称（表ID + 资源项ID）
        /// </summary>
        public string GetSpineAnimName(int tableId, int itemId)
        {
            return GetSpineAnimNameInternal(tableId, itemId, null);
        }

        /// <summary>
        /// 获取Spine动画名称（表ID + 资源项Name）
        /// </summary>
        public string GetSpineAnimName(int tableId, string itemName)
        {
            return GetSpineAnimNameInternal(tableId, null, itemName);
        }

        /// <summary>
        /// 获取Spine动画名称（表Name + 资源项ID）
        /// </summary>
        public string GetSpineAnimName(string tableName, int itemId)
        {
            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 找不到表名称 '{tableName}'");
                return "";
            }
            return GetSpineAnimNameInternal(table.TableId, itemId, null);
        }

        /// <summary>
        /// 获取Spine动画名称（表Name + 资源项Name）
        /// </summary>
        public string GetSpineAnimName(string tableName, string itemName)
        {
            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 找不到表名称 '{tableName}'");
                return "";
            }
            return GetSpineAnimNameInternal(table.TableId, null, itemName);
        }

        /// <summary>
        /// 内部获取Spine动画名称实现
        /// </summary>
        private string GetSpineAnimNameInternal(int tableId, int? itemId, string itemName)
        {
            if (!allTables.TryGetValue(tableId, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 找不到表ID {tableId}");
                return "";
            }

            ArtItemData item;
            if (itemId.HasValue)
            {
                item = table.Items.FirstOrDefault(x => x.Id == itemId.Value);
                if (item == null)
                {
                    Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 资源表{tableId} ({table.TableName}) 中找不到ID为{itemId.Value} 的资源项");
                    return "";
                }
            }
            else
            {
                item = table.Items.FirstOrDefault(x => x.Name == itemName);
                if (item == null)
                {
                    Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 资源表{tableId} ({table.TableName}) 中找不到Name为'{itemName}' 的资源项");
                    return "";
                }
            }

            return item.SpineAnimName ?? "";
        }

        #endregion

        #region 工具方法

        /// <summary>
        /// 检查资源表是否存在
        /// </summary>
        public bool HasTable(int tableId)
        {
            return allTables.ContainsKey(tableId);
        }

        /// <summary>
        /// 检查资源表是否存在（按Name）
        /// </summary>
        public bool HasTable(string tableName)
        {
            return tablesByName.ContainsKey(tableName);
        }

        /// <summary>
        /// 获取资源表信息（不加载资源）
        /// </summary>
        public ArtTableSO GetTable(int tableId)
        {
            allTables.TryGetValue(tableId, out ArtTableSO table);
            return table;
        }

        /// <summary>
        /// 获取资源表信息（按Name，不加载资源）
        /// </summary>
        public ArtTableSO GetTable(string tableName)
        {
            tablesByName.TryGetValue(tableName, out ArtTableSO table);
            return table;
        }

        /// <summary>
        /// 清空指定表的所有资源缓存（保留SO）
        /// </summary>
        public void ClearTableCache(int tableId)
        {
            int clearedCount = 0;
            
            // 清理Sprite缓存
            var spriteKeys = loadedSprites.Keys.Where(k => k.StartsWith($"{tableId}_")).ToList();
            foreach (var key in spriteKeys)
            {
                loadedSprites.Remove(key);
                clearedCount++;
            }

            // 清理Spine缓存
            var spineKeys = loadedSpines.Keys.Where(k => k.StartsWith($"{tableId}_")).ToList();
            foreach (var key in spineKeys)
            {
                loadedSpines.Remove(key);
                clearedCount++;
            }

            Debug.Log($"[ArtResourceManager] 清空资源表 {tableId} 缓存: {clearedCount} 项资源");
        }

        /// <summary>
        /// 清空所有资源缓存（保留SO）
        /// </summary>
        public void ClearAllCache()
        {
            int spriteCount = loadedSprites.Count;
            int spineCount = loadedSpines.Count;

            loadedSprites.Clear();
            loadedSpines.Clear();

            Debug.Log($"[ArtResourceManager] 清空所有资源缓存: {spriteCount} 个Sprite, {spineCount} 个Spine（SO保留）");
        }

        /// <summary>
        /// 获取缓存统计信息
        /// </summary>
        public string GetCacheInfo()
        {
            int totalItems = allTables.Values.Sum(table => table.Items.Count);
            
            return $"SO缓存: {allTables.Count} 个表 ({totalItems} 项资源定义)\n" +
                   $"Sprite缓存: {loadedSprites.Count} 个\n" +
                   $"Spine缓存: {loadedSpines.Count} 个";
        }

        /// <summary>
        /// 获取所有表ID
        /// </summary>
        public List<int> GetAllTableIds()
        {
            return new List<int>(allTables.Keys);
        }

        /// <summary>
        /// 获取所有表名称
        /// </summary>
        public List<string> GetAllTableNames()
        {
            return new List<string>(tablesByName.Keys);
        }

        /// <summary>
        /// 获取Sprite资源的完整路径
        /// </summary>
        /// <param name="tableId">表ID</param>
        /// <param name="itemId">资源项ID</param>
        /// <returns>资源完整路径，如果找不到返回null</returns>
        public string GetSpritePath(int tableId, int itemId)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                return null;
            }

            if (!allTables.TryGetValue(tableId, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表ID {tableId}");
                return null;
            }

            var item = table.Items.FirstOrDefault(x => x.Id == itemId);
            if (item == null)
            {
                Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 表{tableId}中找不到ID为{itemId}的资源项");
                return null;
            }

            if (string.IsNullOrEmpty(item.SpritePath))
            {
                Debug.LogWarning($"[ArtResourceManager] 资源项 {tableId}_{itemId} 没有配置Sprite路径");
                return null;
            }

            return item.SpritePath;
        }

        /// <summary>
        /// 获取Sprite资源的完整路径（表ID + 资源项名称）
        /// </summary>
        /// <param name="tableId">表ID</param>
        /// <param name="itemName">资源项名称</param>
        /// <returns>资源完整路径，如果找不到返回null</returns>
        public string GetSpritePath(int tableId, string itemName)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                return null;
            }

            if (!allTables.TryGetValue(tableId, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表ID {tableId}");
                return null;
            }

            var item = table.Items.FirstOrDefault(x => x.Name == itemName);
            if (item == null)
            {
                Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 表{tableId}中找不到名称为'{itemName}'的资源项");
                return null;
            }

            if (string.IsNullOrEmpty(item.SpritePath))
            {
                Debug.LogWarning($"[ArtResourceManager] 资源项 {tableId}/{itemName} 没有配置Sprite路径");
                return null;
            }

            return item.SpritePath;
        }

        /// <summary>
        /// 获取Sprite资源的完整路径（表名称 + 资源项ID）
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <param name="itemId">资源项ID</param>
        /// <returns>资源完整路径，如果找不到返回null</returns>
        public string GetSpritePath(string tableName, int itemId)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                return null;
            }

            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表名 {tableName}");
                return null;
            }

            var item = table.Items.FirstOrDefault(x => x.Id == itemId);
            if (item == null)
            {
                Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 表{tableName}中找不到ID为{itemId}的资源项");
                return null;
            }

            if (string.IsNullOrEmpty(item.SpritePath))
            {
                Debug.LogWarning($"[ArtResourceManager] 资源项 {tableName}/{itemId} 没有配置Sprite路径");
                return null;
            }

            return item.SpritePath;
        }

        /// <summary>
        /// 获取Sprite资源的完整路径（按名称查询）
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <param name="itemName">资源项名称</param>
        /// <returns>资源完整路径，如果找不到返回null</returns>
        public string GetSpritePath(string tableName, string itemName)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                return null;
            }

            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表名 {tableName}");
                return null;
            }

            var item = table.Items.FirstOrDefault(x => x.Name == itemName);
            if (item == null)
            {
                Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 表{tableName}中找不到名称为'{itemName}'的资源项");
                return null;
            }

            if (string.IsNullOrEmpty(item.SpritePath))
            {
                Debug.LogWarning($"[ArtResourceManager] 资源项 {tableName}/{itemName} 没有配置Sprite路径");
                return null;
            }

            return item.SpritePath;
        }

        /// <summary>
        /// 获取SkeletonDataAsset资源的完整路径
        /// </summary>
        /// <param name="tableId">表ID</param>
        /// <param name="itemId">资源项ID</param>
        /// <returns>资源完整路径，如果找不到返回null</returns>
        public string GetSpinePath(int tableId, int itemId)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                return null;
            }

            if (!allTables.TryGetValue(tableId, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 找不到表ID {tableId}");
                return null;
            }

            var item = table.Items.FirstOrDefault(x => x.Id == itemId);
            if (item == null)
            {
                Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 表{tableId}中找不到ID为{itemId}的资源项");
                return null;
            }

            if (string.IsNullOrEmpty(item.SpineAssetPath))
            {
                Debug.LogWarning($"[ArtResourceManager] 资源项 {tableId}_{itemId} 没有配置Spine路径");
                return null;
            }

            return item.SpineAssetPath;
        }

        /// <summary>
        /// 获取SkeletonDataAsset资源的完整路径（表ID + 资源项名称）
        /// </summary>
        /// <param name="tableId">表ID</param>
        /// <param name="itemName">资源项名称</param>
        /// <returns>资源完整路径，如果找不到返回null</returns>
        public string GetSpinePath(int tableId, string itemName)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                return null;
            }

            if (!allTables.TryGetValue(tableId, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 找不到表ID {tableId}");
                return null;
            }

            var item = table.Items.FirstOrDefault(x => x.Name == itemName);
            if (item == null)
            {
                Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 表{tableId}中找不到名称为'{itemName}'的资源项");
                return null;
            }

            if (string.IsNullOrEmpty(item.SpineAssetPath))
            {
                Debug.LogWarning($"[ArtResourceManager] 资源项 {tableId}/{itemName} 没有配置Spine路径");
                return null;
            }

            return item.SpineAssetPath;
        }

        /// <summary>
        /// 获取SkeletonDataAsset资源的完整路径（表名称 + 资源项ID）
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <param name="itemId">资源项ID</param>
        /// <returns>资源完整路径，如果找不到返回null</returns>
        public string GetSpinePath(string tableName, int itemId)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                return null;
            }

            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 找不到表名 {tableName}");
                return null;
            }

            var item = table.Items.FirstOrDefault(x => x.Id == itemId);
            if (item == null)
            {
                Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 表{tableName}中找不到ID为{itemId}的资源项");
                return null;
            }

            if (string.IsNullOrEmpty(item.SpineAssetPath))
            {
                Debug.LogWarning($"[ArtResourceManager] 资源项 {tableName}/{itemId} 没有配置Spine路径");
                return null;
            }

            return item.SpineAssetPath;
        }

        /// <summary>
        /// 获取SkeletonDataAsset资源的完整路径（按名称查询）
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <param name="itemName">资源项名称</param>
        /// <returns>资源完整路径，如果找不到返回null</returns>
        public string GetSpinePath(string tableName, string itemName)
        {
            if (!isInitialized)
            {
                Debug.LogError("[ArtResourceManager] 未初始化，请先调用Initialize()并等待回调完成");
                return null;
            }

            if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
            {
                Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 找不到表名 {tableName}");
                return null;
            }

            var item = table.Items.FirstOrDefault(x => x.Name == itemName);
            if (item == null)
            {
                Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 表{tableName}中找不到名称为'{itemName}'的资源项");
                return null;
            }

            if (string.IsNullOrEmpty(item.SpineAssetPath))
            {
                Debug.LogWarning($"[ArtResourceManager] 资源项 {tableName}/{itemName} 没有配置Spine路径");
                return null;
            }

            return item.SpineAssetPath;
        }

        #endregion
    }
}
