using UnityEngine;
using UnityEditor;
using ArtResource;
using System.Diagnostics;
using Debug = UnityEngine.Debug;

namespace CrazyMaple.Editor
{
    /// <summary>
    /// 测试工具：验证SO加载时是否会连带加载引用资源
    /// 
    /// 测试方法：
    /// 1. 在加载SO前后检查内存中的资源数量
    /// 2. 分别测试带引用和不带引用的SO
    /// 3. 分析加载耗时差异
    /// </summary>
    public class ArtResourceLoadTest : EditorWindow
    {
        [MenuItem("美术工具/性能测试工具/测试SO加载行为")]
        public static void ShowWindow()
        {
            GetWindow<ArtResourceLoadTest>("SO加载测试");
        }

        private void OnGUI()
        {
            GUILayout.Label("SO加载行为测试", EditorStyles.boldLabel);
            GUILayout.Space(10);

            if (GUILayout.Button("测试1: 检查SO序列化大小", GUILayout.Height(40)))
            {
                TestSerializationSize();
            }

            GUILayout.Space(5);

            if (GUILayout.Button("测试2: 对比加载时间（带引用 vs 纯路径）", GUILayout.Height(40)))
            {
                TestLoadingTime();
            }

            GUILayout.Space(5);

            if (GUILayout.Button("测试3: 检查内存占用（加载前后）", GUILayout.Height(40)))
            {
                TestMemoryUsage();
            }

            GUILayout.Space(10);
            EditorGUILayout.HelpBox(
                "这些测试将帮助确定：\n" +
                "1. SO是否会连带加载引用资源\n" +
                "2. 引用字段对加载速度的影响\n" +
                "3. 内存占用差异",
                MessageType.Info);
        }

        /// <summary>
        /// 测试1: 检查SO序列化后的文件大小
        /// </summary>
        private void TestSerializationSize()
        {
            Debug.Log("========== 测试1: SO序列化大小 ==========");

            string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
            
            if (guids.Length == 0)
            {
                Debug.LogWarning("未找到任何ArtTableSO");
                return;
            }

            foreach (var guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
                
                if (table != null)
                {
                    // 获取文件大小
                    var fileInfo = new System.IO.FileInfo(path);
                    long fileSize = fileInfo.Length;

                    // 统计引用数量
                    int spriteRefCount = 0;
                    int spineRefCount = 0;
                    int pathCount = 0;

                    foreach (var item in table.Items)
                    {
                        if (item.Sprite != null) spriteRefCount++;
                        if (item.SpineAsset != null) spineRefCount++;
                        if (!string.IsNullOrEmpty(item.SpritePath) || !string.IsNullOrEmpty(item.SpineAssetPath))
                            pathCount++;
                    }

                    Debug.Log($"SO: {table.TableName}\n" +
                             $"  文件大小: {fileSize / 1024f:F2} KB\n" +
                             $"  资源项数: {table.Items.Count}\n" +
                             $"  Sprite引用: {spriteRefCount}\n" +
                             $"  Spine引用: {spineRefCount}\n" +
                             $"  路径字段: {pathCount}");
                }
            }

            Debug.Log("========== 测试1 完成 ==========");
            EditorUtility.DisplayDialog("测试完成", "请查看Console日志了解SO文件大小和引用情况", "确定");
        }

        /// <summary>
        /// 测试2: 对比加载时间
        /// </summary>
        private void TestLoadingTime()
        {
            Debug.Log("========== 测试2: 加载时间对比 ==========");

            string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
            
            if (guids.Length == 0)
            {
                Debug.LogWarning("未找到任何ArtTableSO");
                return;
            }

            foreach (var guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                
                // 卸载以确保测试准确
                Resources.UnloadUnusedAssets();
                System.GC.Collect();

                // 测试加载时间
                var sw = Stopwatch.StartNew();
                var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
                sw.Stop();

                if (table != null)
                {
                    // 统计引用情况
                    int refCount = 0;
                    foreach (var item in table.Items)
                    {
                        if (item.Sprite != null || item.SpineAsset != null)
                            refCount++;
                    }
                    
                    Debug.Log($"SO: {table.TableName}\n" +
                             $"  加载耗时: {sw.Elapsed.TotalMilliseconds:F2} ms\n" +
                             $"  资源项数: {table.Items.Count}\n" +
                             $"  含引用项: {refCount}\n" +
                             $"  平均耗时: {sw.Elapsed.TotalMilliseconds / table.Items.Count:F3} ms/项");

                    // 尝试访问一个引用，看看是否触发额外加载
                    if (table.Items.Count > 0 && table.Items[0].Sprite != null)
                    {
                        var sw2 = Stopwatch.StartNew();
                        var sprite = table.Items[0].Sprite; // 访问引用
                        var name = sprite.name; // 访问属性
                        sw2.Stop();
                        Debug.Log($"  访问第1个Sprite引用: {sw2.Elapsed.TotalMilliseconds:F2} ms");
                    }
                }
            }

            Debug.Log("========== 测试2 完成 ==========");
            EditorUtility.DisplayDialog("测试完成", "请查看Console日志了解加载时间差异", "确定");
        }

        /// <summary>
        /// 测试3: 检查内存占用
        /// </summary>
        private void TestMemoryUsage()
        {
            Debug.Log("========== 测试3: 内存占用测试 ==========");

            // 清理内存
            Resources.UnloadUnusedAssets();
            System.GC.Collect();
            
            long memBefore = System.GC.GetTotalMemory(true);
            int textureBefore = Resources.FindObjectsOfTypeAll<Texture2D>().Length;
            int spriteBefore = Resources.FindObjectsOfTypeAll<Sprite>().Length;

            Debug.Log($"加载前:\n" +
                     $"  托管内存: {memBefore / 1024f / 1024f:F2} MB\n" +
                     $"  Texture2D数量: {textureBefore}\n" +
                     $"  Sprite数量: {spriteBefore}");

            // 加载所有SO
            string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
            var tables = new System.Collections.Generic.List<ArtTableSO>();
            
            foreach (var guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
                if (table != null)
                {
                    tables.Add(table);
                }
            }

            long memAfter = System.GC.GetTotalMemory(false);
            int textureAfter = Resources.FindObjectsOfTypeAll<Texture2D>().Length;
            int spriteAfter = Resources.FindObjectsOfTypeAll<Sprite>().Length;

            Debug.Log($"加载后:\n" +
                     $"  托管内存: {memAfter / 1024f / 1024f:F2} MB (+{(memAfter - memBefore) / 1024f / 1024f:F2} MB)\n" +
                     $"  Texture2D数量: {textureAfter} (+{textureAfter - textureBefore})\n" +
                     $"  Sprite数量: {spriteAfter} (+{spriteAfter - spriteBefore})");

            Debug.Log($"共加载 {tables.Count} 个SO");

            Debug.Log("========== 测试3 完成 ==========");
            
            EditorUtility.DisplayDialog(
                "测试完成",
                $"内存增加: {(memAfter - memBefore) / 1024f / 1024f:F2} MB\n" +
                $"Texture2D增加: {textureAfter - textureBefore}\n" +
                $"Sprite增加: {spriteAfter - spriteBefore}\n\n" +
                $"如果纹理/Sprite数量大幅增加，说明确实连带加载了引用资源",
                "确定");
        }
    }
}
