using System;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;

namespace Sud.UnityExporter
{
    public class SudExporterWindow : EditorWindow
    {
        private const string WindowTitle = "SUD 小游戏";
        private const string MenuPath = "SUD 小游戏/转换小游戏";

        private const string EditorPrefsKey_OutputFolder = "SudExporter_OutputFolder";

        private string _outputFolderAbsolutePath;
        private Vector2 _scrollPos;
        private Vector2 _scenesScrollPos;
        private bool _scenesFoldout = true;
        private bool _developmentBuild;
        private SudExporterSettings _settings;

        [MenuItem(MenuPath)]
        public static void ShowWindow()
        {
            var window = GetWindow<SudExporterWindow>(utility: false, title: WindowTitle, focus: true);
            window.minSize = new Vector2(420, 400);
            window.maxSize = new Vector2(520, 700);
            window.Show();
        }

        private void OnEnable()
        {
            _settings = SudExporterSettings.LoadOrCreate();
            _outputFolderAbsolutePath = EditorPrefs.GetString(EditorPrefsKey_OutputFolder, string.Empty);
            if (string.IsNullOrEmpty(_outputFolderAbsolutePath))
            {
                _outputFolderAbsolutePath = GetDefaultOutputFolder();
            }

            _developmentBuild = _settings.developmentBuild;
        }

        private void OnDisable()
        {
            EditorPrefs.SetString(EditorPrefsKey_OutputFolder, _outputFolderAbsolutePath ?? string.Empty);
            if (_settings != null)
            {
                _settings.developmentBuild = _developmentBuild;
                UnityEditor.EditorUtility.SetDirty(_settings);
                UnityEditor.AssetDatabase.SaveAssets();
            }
        }

        private void OnGUI()
        {
            _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);

            EditorGUILayout.Space(6);

            DrawOutputFolderSelector();

            EditorGUILayout.Space(8);
            DrawWebGLInfo();

            EditorGUILayout.Space(8);
            DrawScenesInBuild();

            EditorGUILayout.Space(40);
            var btnWidth = GUILayout.Width(100);
            EditorGUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("手动清理缓存", btnWidth, GUILayout.Height(30)))
            {
                ClearBuildCache();
            }
            if (GUILayout.Button("导出", btnWidth, GUILayout.Height(30)))
            {
                EditorApplication.delayCall += RunWebGLExportAndConvert;
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndScrollView();
        }

        private void DrawWebGLInfo()
        {
            EditorGUILayout.LabelField("基本信息配置", EditorStyles.boldLabel);

            EditorGUI.indentLevel++;

            _developmentBuild = EditorGUILayout.Toggle("Development Build", _developmentBuild);
            PlayerSettings.colorSpace = (ColorSpace)EditorGUILayout.EnumPopup("Color Space", PlayerSettings.colorSpace);
            DrawReflectionEnumField(typeof(EditorUserBuildSettings), "webGLBuildSubtarget", "Texture Compression");
            PlayerSettings.WebGL.exceptionSupport = (WebGLExceptionSupport)EditorGUILayout.EnumPopup(
                "Exception Support", PlayerSettings.WebGL.exceptionSupport);

            EditorGUILayout.Space(4);
            EditorGUI.BeginDisabledGroup(true);
            EditorGUILayout.EnumPopup("Compression Format", WebGLCompressionFormat.Disabled);
            EditorGUILayout.LabelField("Data Caching", "Disabled");
            EditorGUI.EndDisabledGroup();

            EditorGUI.indentLevel--;
        }

        private void DrawScenesInBuild()
        {
            var scenes = EditorBuildSettings.scenes;
            _scenesFoldout = EditorGUILayout.Foldout(_scenesFoldout, $"Scenes In Build ({scenes.Length})", true, EditorStyles.foldoutHeader);

            if (!_scenesFoldout) return;

            if (scenes.Length == 0)
            {
                EditorGUILayout.HelpBox("没有场景。请在 Build Settings 中添加场景。", MessageType.Warning);
            }
            else
            {
                _scenesScrollPos = EditorGUILayout.BeginScrollView(_scenesScrollPos, EditorStyles.helpBox, GUILayout.Height(100));
                EditorGUI.indentLevel++;
                for (int i = 0; i < scenes.Length; i++)
                {
                    var scene = scenes[i];
                    var sceneName = Path.GetFileNameWithoutExtension(scene.path);
                    var label = $"{i}: {sceneName}";
                    if (string.IsNullOrEmpty(scene.path))
                        label = $"{i}: (Missing)";

                    var newEnabled = EditorGUILayout.ToggleLeft(label, scene.enabled);
                    if (newEnabled != scene.enabled)
                    {
                        scenes[i].enabled = newEnabled;
                        EditorBuildSettings.scenes = scenes;
                    }
                }
                EditorGUI.indentLevel--;
                EditorGUILayout.EndScrollView();
            }
        }

        private void DrawOutputFolderSelector()
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("导出路径", GUILayout.Width(50));
            _outputFolderAbsolutePath = EditorGUILayout.TextField(_outputFolderAbsolutePath ?? string.Empty);

            var hasPath = !string.IsNullOrEmpty(_outputFolderAbsolutePath);
            EditorGUI.BeginDisabledGroup(!hasPath);
            if (GUILayout.Button("打开", GUILayout.Width(40)))
            {
                OpenOutputFolder();
            }
            EditorGUI.EndDisabledGroup();

            if (GUILayout.Button("选择", GUILayout.Width(40)))
            {
                var selected = EditorUtility.OpenFolderPanel("Select Output Folder", _outputFolderAbsolutePath, "");
                if (!string.IsNullOrEmpty(selected))
                {
                    _outputFolderAbsolutePath = selected;
                    Repaint();
                }
            }
            EditorGUILayout.EndHorizontal();
        }

        private static void DrawReflectionEnumField(System.Type type, string propertyName, string label)
        {
            var prop = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Static);
            if (prop == null) return;

            var current = prop.GetValue(null);
            var newValue = EditorGUILayout.EnumPopup(label, (Enum)current);
            if (!newValue.Equals(current))
            {
                prop.SetValue(null, newValue);
            }
        }

        private void RunWebGLExportAndConvert()
        {
            var textureSubtargetProp = typeof(EditorUserBuildSettings).GetProperty("webGLBuildSubtarget",
                BindingFlags.Public | BindingFlags.Static);
            object originalTextureSubtarget = textureSubtargetProp?.GetValue(null);
            var originalCompressionFormat = PlayerSettings.WebGL.compressionFormat;
            var originalDataCaching = PlayerSettings.WebGL.dataCaching;

            try
            {
                var outputRoot = string.IsNullOrEmpty(_outputFolderAbsolutePath)
                    ? GetDefaultOutputFolder()
                    : _outputFolderAbsolutePath;

                if (!Directory.Exists(outputRoot))
                {
                    Directory.CreateDirectory(outputRoot);
                }

                var webglDir = Path.Combine(outputRoot, "webgl");
                var sudDir = Path.Combine(outputRoot, "sud");

                // ============================================
                // 第一次构建：标准 Unity WebGL 项目
                // ============================================
                Debug.Log("[SudExporter] Step 1: Building standard Unity WebGL project...");

                var buildOptions = BuildOptions.None;
                if (_developmentBuild)
                {
                    buildOptions |= BuildOptions.Development;
                }
                buildOptions |= BuildOptions.CleanBuildCache;

                PlayerSettings.WebGL.compressionFormat = WebGLCompressionFormat.Disabled;
                PlayerSettings.WebGL.dataCaching = false;

                var enabledScenes = EditorBuildSettings.scenes;
                var scenePaths = Array.ConvertAll(enabledScenes, s => s.path);
                scenePaths = Array.FindAll(scenePaths, p => !string.IsNullOrEmpty(p) && File.Exists(p));
                if (scenePaths.Length == 0)
                {
                    EditorUtility.DisplayDialog("Export WebGL", "无可用场景可导出。请在 Build Settings 勾选至少一个场景。", "OK");
                    return;
                }

                if (!Directory.Exists(webglDir)) Directory.CreateDirectory(webglDir);

                var buildPlayerOptions = new BuildPlayerOptions
                {
                    scenes = scenePaths,
                    locationPathName = webglDir,
                    target = BuildTarget.WebGL,
                    options = buildOptions
                };

                var subtargetProp = typeof(BuildPlayerOptions).GetProperty("subtarget");
                if (subtargetProp != null && textureSubtargetProp != null)
                {
                    var value = (int)textureSubtargetProp.GetValue(null);
                    subtargetProp.SetValue(buildPlayerOptions, value);
                    Debug.Log($"[SudExporter] Texture subtarget: {textureSubtargetProp.GetValue(null)}");
                }

                Debug.Log($"[SudExporter] Building to: {webglDir}");
                var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
                var summary = report.summary;

                if (summary.result != BuildResult.Succeeded)
                {
                    Debug.LogError($"[SudExporter] WebGL 导出失败。状态: {summary.result}, 错误数: {summary.totalErrors}");
                    ShowNotification(new GUIContent("WebGL 导出失败。详见 Console"));
                    return;
                }

                Debug.Log($"[SudExporter] ✅ Step 1 completed: Standard WebGL project built");
                Debug.Log($"[SudExporter] Output: {webglDir}");

                // ============================================
                // 第二次转换：生成 sud Runtime 项目
                // ============================================
                Debug.Log("[SudExporter] ╔════════════════════════════════════════════════════════╗");
                Debug.Log("[SudExporter] ║ Step 2: Converting to sud Runtime (main.js entry)  ║");
                Debug.Log("[SudExporter] ╚════════════════════════════════════════════════════════╝");

                SudTemplateConverter.ConvertWebGLToMinigameUsingTemplate(webglDir, sudDir, _developmentBuild);

                Debug.Log($"[SudExporter] ╔════════════════════════════════════════════════════════╗");
                Debug.Log($"[SudExporter] ║           🎉 Export Completed Successfully!          ║");
                Debug.Log($"[SudExporter] ╚════════════════════════════════════════════════════════╝");
                Debug.Log($"[SudExporter] 📦 WebGL: {webglDir}");
                Debug.Log($"[SudExporter] 📦 SUD:   {sudDir}");
                Debug.Log($"[SudExporter] 🚀 Entry: main.js");
                Debug.Log($"[SudExporter] 🔧 Mode: {(_developmentBuild ? "Development" : "Release")}");
                ShowNotification(new GUIContent("✅ Export completed!"));
                EditorUtility.RevealInFinder(sudDir);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[SudExporter] 导出异常: {ex}");
                ShowNotification(new GUIContent("导出异常。详见 Console"));
            }
            finally
            {
                PlayerSettings.WebGL.compressionFormat = originalCompressionFormat;
                PlayerSettings.WebGL.dataCaching = originalDataCaching;
                if (textureSubtargetProp != null && originalTextureSubtarget != null)
                {
                    textureSubtargetProp.SetValue(null, originalTextureSubtarget);
                }
            }
        }

        private void OpenOutputFolder()
        {
            var path = string.IsNullOrEmpty(_outputFolderAbsolutePath) ? GetDefaultOutputFolder() : _outputFolderAbsolutePath;
            try
            {
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                EditorUtility.RevealInFinder(path);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[SudExporter] Open folder failed: {ex}");
            }
        }

        private static string GetDefaultOutputFolder()
        {
            var root = GetProjectRoot();
            return Path.Combine(root, "Build");
        }

        private static string GetProjectRoot()
        {
            var dataPath = Application.dataPath;
            var root = Directory.GetParent(dataPath)?.FullName ?? dataPath;
            return root;
        }

        private void ClearBuildCache()
        {
            try
            {
                Debug.Log("[SudExporter] Clearing build cache...");

                var buildCachePath = Path.Combine(GetProjectRoot(), "Library", "BuildCache");
                if (Directory.Exists(buildCachePath))
                {
                    Directory.Delete(buildCachePath, true);
                    Debug.Log("[SudExporter] Cleared Unity BuildCache");
                }

                var il2cppCachePath = Path.Combine(GetProjectRoot(), "Library", "il2cpp_cache");
                if (Directory.Exists(il2cppCachePath))
                {
                    Directory.Delete(il2cppCachePath, true);
                    Debug.Log("[SudExporter] Cleared IL2CPP cache");
                }

                var webglCachePath = Path.Combine(GetProjectRoot(), "Library", "PlayerDataCache", "WebGL");
                if (Directory.Exists(webglCachePath))
                {
                    Directory.Delete(webglCachePath, true);
                    Debug.Log("[SudExporter] Cleared WebGL player data cache");
                }

                AssetDatabase.Refresh();

                Debug.Log("[SudExporter] Build cache cleared successfully");
                ShowNotification(new GUIContent("Build cache cleared"));
            }
            catch (Exception ex)
            {
                Debug.LogError($"[SudExporter] Failed to clear build cache: {ex}");
                ShowNotification(new GUIContent("Failed to clear cache"));
            }
        }
    }
}
