#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;

namespace IGP.UnitySDK.Editor
{
    [CustomEditor(typeof(global::IGP.UnitySDK.IGPRuntimeManager))]
    public sealed class IGPRuntimeManagerEditor : UnityEditor.Editor
    {
        private const string EditorDebugPrefsPrefix = "IGP.UnitySDK.Editor.HostedDebug.";
        private static readonly string[] SensitiveHostedDebugPrefNames =
        {
            "LaunchPackageJson",
            "LaunchTicket",
            "BootstrapSecret",
        };

        private bool showHostedDebug = true;
        private bool hostedDebugPrefsLoaded;
        private string hostedDebugLaunchPackageJson = string.Empty;
        private string hostedDebugLaunchTicket = string.Empty;
        private string hostedDebugBootstrapEndpoint = string.Empty;
        private string hostedDebugBootstrapSecret = string.Empty;
        private bool hostedDebugAutoConnect = true;
        private int hostedDebugAppIdOverride;
        private Task<bool>? hostedBootstrapTask;
        private string hostedBootstrapStatus = string.Empty;
        private MessageType hostedBootstrapStatusType = MessageType.Info;

        [Serializable]
        private sealed class HostedLaunchPackage
        {
            public string roomId = string.Empty;
            public int appId;
            public string ticket = string.Empty;
            public string endpoint = string.Empty;
            public string secret = string.Empty;
            public bool autoConnect = true;
            public string generatedAt = string.Empty;
        }

        public override void OnInspectorGUI()
        {
            EnsureHostedDebugPrefsLoaded();
            serializedObject.Update();

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("IGP Runtime Manager", EditorStyles.boldLabel);
            EditorGUILayout.HelpBox("Unity runtime entrypoint for desktop-session achievements plus hosted room lifecycle, realtime messaging, and data plane.", MessageType.Info);
            EditorGUILayout.HelpBox("如果切场景后还要保留联机，这个对象必须做成 DontDestroyOnLoad，并且游戏里只能保留一个 IGPRuntimeManager。对象被销毁时，当前连接会断开。", MessageType.Warning);
            EditorGUILayout.Space();

            DrawHostedDebugSection();

            DrawDefaultInspector();

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Runtime Status", EditorStyles.boldLabel);

            if (target is global::IGP.UnitySDK.IGPRuntimeManager manager)
            {
                GUI.enabled = false;
                EditorGUILayout.Toggle("Hosted Session Attached", manager.IsHostedSessionAttached);
                EditorGUILayout.Toggle("WebSocket Connected", manager.IsWebSocketConnected);
                EditorGUILayout.Toggle("Hosted Data Plane Attached", manager.IsHostedDataPlaneAttached);
                EditorGUILayout.Toggle("KCP Connected", manager.IsKcpConnected);
                GUI.enabled = true;
            }

            EditorGUILayout.Space();
            if (GUILayout.Button("Generate New Player ID"))
            {
                var idProp = serializedObject.FindProperty("playerId");
                if (idProp != null)
                {
                    idProp.stringValue = "player_" + Guid.NewGuid().ToString("N").Substring(0, 8);
                }
            }

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Testing", EditorStyles.boldLabel);
            if (GUILayout.Button("Open Unity Test Runner"))
            {
                EditorApplication.ExecuteMenuItem("Window/General/Test Runner");
            }

            if (GUILayout.Button("Run IGP Runtime Tests"))
            {
                IGPTestRunner.RunAllTests();
            }

            serializedObject.ApplyModifiedProperties();
        }

        private void DrawHostedDebugSection()
        {
            if (target is not global::IGP.UnitySDK.IGPRuntimeManager manager)
            {
                return;
            }

            UpdateHostedBootstrapTaskState();

            EditorGUILayout.Space();
            var nextShowHostedDebug = EditorGUILayout.Foldout(showHostedDebug, "Unity Editor 联调", true);
            if (nextShowHostedDebug != showHostedDebug)
            {
                showHostedDebug = nextShowHostedDebug;
                SaveHostedDebugPrefs();
            }

            if (!showHostedDebug)
            {
                return;
            }

            EditorGUILayout.HelpBox(
                "默认主线是：先在 desktop 里创建或加入测试房间，再复制 Unity 启动包，把整包粘贴到这里。下面的单项输入保留给手工排查时兜底使用。",
                MessageType.Info);
            EditorGUILayout.HelpBox(
                "Launch Package、Launch Ticket 和 Bootstrap Secret 只保留在当前 Inspector 会话里，不会写入本机偏好设置。",
                MessageType.None);

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.LabelField("Launch Package JSON");
            hostedDebugLaunchPackageJson = EditorGUILayout.TextArea(hostedDebugLaunchPackageJson, GUILayout.MinHeight(90f));
            hostedDebugLaunchTicket = EditorGUILayout.TextField("Launch Ticket", hostedDebugLaunchTicket);
            hostedDebugBootstrapEndpoint = EditorGUILayout.TextField("Bootstrap Endpoint", hostedDebugBootstrapEndpoint);
            hostedDebugBootstrapSecret = EditorGUILayout.PasswordField("Bootstrap Secret", hostedDebugBootstrapSecret);
            hostedDebugAutoConnect = EditorGUILayout.Toggle("Auto Connect", hostedDebugAutoConnect);
            hostedDebugAppIdOverride = EditorGUILayout.IntField("App Id Override", hostedDebugAppIdOverride);
            if (EditorGUI.EndChangeCheck())
            {
                SaveHostedDebugPrefs();
            }

            var effectiveAppId = hostedDebugAppIdOverride > 0
                ? hostedDebugAppIdOverride
                : manager.Config?.appId ?? 0;

            if (effectiveAppId <= 0)
            {
                EditorGUILayout.HelpBox("完整调试前要保证 appId 有值。可以填在 IGPConfig 里，也可以只填这里的 App Id Override。", MessageType.Warning);
            }

            if (string.IsNullOrWhiteSpace(manager.Config?.desktopExecutablePathDebugOverride))
            {
                EditorGUILayout.HelpBox(
                    "如果你还想在 Editor 里一起调成就或其他 desktop 能力，记得在 IGPConfig 的调试参数里填 Desktop Executable Path Debug Override。",
                    MessageType.Warning);
            }

            if (!string.IsNullOrWhiteSpace(hostedBootstrapStatus))
            {
                EditorGUILayout.HelpBox(hostedBootstrapStatus, hostedBootstrapStatusType);
            }

            EditorGUILayout.BeginHorizontal();

            GUI.enabled = hostedBootstrapTask == null;
            if (GUILayout.Button("Paste Launch Package"))
            {
                hostedDebugLaunchPackageJson = EditorGUIUtility.systemCopyBuffer ?? string.Empty;
                SaveHostedDebugPrefs();
            }

            GUI.enabled = hostedBootstrapTask == null;
            if (GUILayout.Button("Apply Launch Package"))
            {
                TryApplyHostedLaunchPackage();
            }

            GUI.enabled = hostedBootstrapTask == null;
            if (GUILayout.Button("Copy Launch Args"))
            {
                EditorGUIUtility.systemCopyBuffer = BuildHostedDebugCommandLine(manager);
                hostedBootstrapStatus = "命令行参数已经复制到剪贴板。";
                hostedBootstrapStatusType = MessageType.Info;
            }

            GUI.enabled = hostedBootstrapTask == null;
            if (GUILayout.Button("Clear"))
            {
                ClearHostedDebugPrefs();
            }

            GUI.enabled = EditorApplication.isPlaying && hostedBootstrapTask == null;
            if (GUILayout.Button("Connect Current Test Room"))
            {
                StartHostedBootstrap(manager);
            }

            GUI.enabled = true;
            EditorGUILayout.EndHorizontal();

            if (!EditorApplication.isPlaying)
            {
                EditorGUILayout.HelpBox("先进入 Play，再点 Connect Current Test Room。", MessageType.None);
            }
            else if (hostedBootstrapTask != null)
            {
                EditorGUILayout.HelpBox("正在连接，完成后这里会显示结果。", MessageType.None);
                Repaint();
            }
        }

        private void EnsureHostedDebugPrefsLoaded()
        {
            if (hostedDebugPrefsLoaded)
            {
                return;
            }

            showHostedDebug = EditorPrefs.GetBool(EditorDebugPrefsPrefix + "ShowSection", true);
            hostedDebugLaunchPackageJson = string.Empty;
            hostedDebugLaunchTicket = string.Empty;
            hostedDebugBootstrapEndpoint = EditorPrefs.GetString(EditorDebugPrefsPrefix + "BootstrapEndpoint", string.Empty);
            hostedDebugBootstrapSecret = string.Empty;
            hostedDebugAutoConnect = EditorPrefs.GetBool(EditorDebugPrefsPrefix + "AutoConnect", true);
            hostedDebugAppIdOverride = EditorPrefs.GetInt(EditorDebugPrefsPrefix + "AppIdOverride", 0);
            DeleteSensitiveHostedDebugPrefs();
            hostedDebugPrefsLoaded = true;
        }

        private void SaveHostedDebugPrefs()
        {
            EditorPrefs.SetBool(EditorDebugPrefsPrefix + "ShowSection", showHostedDebug);
            EditorPrefs.SetString(EditorDebugPrefsPrefix + "BootstrapEndpoint", hostedDebugBootstrapEndpoint ?? string.Empty);
            EditorPrefs.SetBool(EditorDebugPrefsPrefix + "AutoConnect", hostedDebugAutoConnect);
            EditorPrefs.SetInt(EditorDebugPrefsPrefix + "AppIdOverride", hostedDebugAppIdOverride);
            DeleteSensitiveHostedDebugPrefs();
        }

        private void ClearHostedDebugPrefs()
        {
            hostedDebugLaunchPackageJson = string.Empty;
            hostedDebugLaunchTicket = string.Empty;
            hostedDebugBootstrapEndpoint = string.Empty;
            hostedDebugBootstrapSecret = string.Empty;
            hostedDebugAutoConnect = true;
            hostedDebugAppIdOverride = 0;
            hostedBootstrapStatus = string.Empty;
            hostedBootstrapStatusType = MessageType.Info;
            SaveHostedDebugPrefs();
        }

        private static void DeleteSensitiveHostedDebugPrefs()
        {
            foreach (var name in SensitiveHostedDebugPrefNames)
            {
                EditorPrefs.DeleteKey(EditorDebugPrefsPrefix + name);
            }
        }

        private void TryApplyHostedLaunchPackage()
        {
            if (string.IsNullOrWhiteSpace(hostedDebugLaunchPackageJson))
            {
                hostedBootstrapStatus = "还没有启动包内容。先从 desktop 复制 Unity 启动包，再点 Apply Launch Package。";
                hostedBootstrapStatusType = MessageType.Warning;
                return;
            }

            try
            {
                var launchPackage = JsonUtility.FromJson<HostedLaunchPackage>(hostedDebugLaunchPackageJson);
                if (launchPackage == null ||
                    string.IsNullOrWhiteSpace(launchPackage.ticket) ||
                    string.IsNullOrWhiteSpace(launchPackage.endpoint) ||
                    string.IsNullOrWhiteSpace(launchPackage.secret))
                {
                    hostedBootstrapStatus = "启动包内容不完整。请确认你粘贴的是 desktop 里复制出来的整包 JSON。";
                    hostedBootstrapStatusType = MessageType.Error;
                    return;
                }

                hostedDebugLaunchTicket = launchPackage.ticket.Trim();
                hostedDebugBootstrapEndpoint = launchPackage.endpoint.Trim();
                hostedDebugBootstrapSecret = launchPackage.secret.Trim();
                hostedDebugAutoConnect = launchPackage.autoConnect;
                if (launchPackage.appId > 0)
                {
                    hostedDebugAppIdOverride = launchPackage.appId;
                }

                SaveHostedDebugPrefs();

                hostedBootstrapStatus = string.IsNullOrWhiteSpace(launchPackage.roomId)
                    ? "启动包已应用。现在可以进入 Play，然后点 Connect Current Test Room。"
                    : $"启动包已应用。当前房间: {launchPackage.roomId}。现在可以进入 Play，然后点 Connect Current Test Room。";
                hostedBootstrapStatusType = MessageType.Info;
            }
            catch (Exception ex)
            {
                hostedBootstrapStatus = $"启动包解析失败：{ex.Message}";
                hostedBootstrapStatusType = MessageType.Error;
            }
        }

        private string BuildHostedDebugCommandLine(global::IGP.UnitySDK.IGPRuntimeManager manager)
        {
            var args = BuildHostedDebugArgs(manager);
            return string.Join(" ", args.ConvertAll(QuoteIfNeeded));
        }

        private List<string> BuildHostedDebugArgs(global::IGP.UnitySDK.IGPRuntimeManager manager)
        {
            var args = new List<string>
            {
                "--arena-launch-ticket",
                hostedDebugLaunchTicket.Trim(),
                "--arena-bootstrap-endpoint",
                hostedDebugBootstrapEndpoint.Trim(),
                "--arena-bootstrap-secret",
                hostedDebugBootstrapSecret.Trim(),
                "--arena-auto-connect",
                hostedDebugAutoConnect ? "true" : "false",
            };

            var effectiveAppId = hostedDebugAppIdOverride > 0
                ? hostedDebugAppIdOverride
                : manager.Config?.appId ?? 0;
            if (effectiveAppId > 0)
            {
                args.Add("--igp-app-id");
                args.Add(effectiveAppId.ToString());
            }

            return args;
        }

        private void StartHostedBootstrap(global::IGP.UnitySDK.IGPRuntimeManager manager)
        {
            var launchTicket = hostedDebugLaunchTicket.Trim();
            var bootstrapEndpoint = hostedDebugBootstrapEndpoint.Trim();
            var bootstrapSecret = hostedDebugBootstrapSecret.Trim();

            if (string.IsNullOrWhiteSpace(launchTicket) ||
                string.IsNullOrWhiteSpace(bootstrapEndpoint) ||
                string.IsNullOrWhiteSpace(bootstrapSecret))
            {
                hostedBootstrapStatus = "还缺启动信息。至少要填 launch ticket、bootstrap endpoint 和 bootstrap secret。";
                hostedBootstrapStatusType = MessageType.Error;
                return;
            }

            SaveHostedDebugPrefs();
            hostedBootstrapStatus = "正在连接...";
            hostedBootstrapStatusType = MessageType.Info;
            hostedBootstrapTask = manager.TryBootstrapFromLaunchTicketAsync(BuildHostedDebugArgs(manager).ToArray());
        }

        private void UpdateHostedBootstrapTaskState()
        {
            if (hostedBootstrapTask == null || !hostedBootstrapTask.IsCompleted)
            {
                return;
            }

            try
            {
                var success = hostedBootstrapTask.GetAwaiter().GetResult();
                hostedBootstrapStatus = success
                    ? "已完成附着。Unity 现在已经连进当前房间，可以继续检查房间状态、消息和同步。"
                    : "没有连进当前房间。先检查启动包或下面三项字段，再看 Unity Console 里的错误。";
                hostedBootstrapStatusType = success ? MessageType.Info : MessageType.Error;
            }
            catch (Exception ex)
            {
                hostedBootstrapStatus = $"启动失败：{ex.Message}";
                hostedBootstrapStatusType = MessageType.Error;
            }
            finally
            {
                hostedBootstrapTask = null;
            }
        }

        private static string QuoteIfNeeded(string value)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return "\"\"";
            }

            return value.Contains(" ", StringComparison.Ordinal)
                ? $"\"{value}\""
                : value;
        }
    }
}
#endif
