using UnityEditor;
using UnityEngine;

namespace VisioForge.Unity.Editor
{
    /// <summary>
    /// One-time project configurator that ships inside the VisioForge MediaBlocks Unity
    /// package. The SDK requires two project settings the customer would otherwise have to
    /// set by hand (the #1 source of "TypeLoadException" / "Editor hangs on Play" reports):
    ///
    ///   1. Api Compatibility Level = .NET Framework (<see cref="ApiCompatibilityLevel.NET_Unity_4_8"/>,
    ///      enum value 3) — the managed SDK is a net48 build and will not load under .NET Standard 2.1.
    ///   2. Enter Play Mode Options with Disable Domain Reload — GStreamer runs on a native GLib
    ///      main-loop thread Unity cannot abort, so a domain reload on Play/Stop hangs the Editor.
    ///
    /// A <c>.unitypackage</c> cannot ship <c>ProjectSettings/*.asset</c> without clobbering the
    /// customer's project, so instead we change ONLY these two keys via the Editor API, after a
    /// one-time <b>Apply / Skip</b> dialog. If the user picks Skip we never prompt again for this
    /// project (a per-project EditorPrefs flag) and just log how to do it manually.
    /// </summary>
    [InitializeOnLoad]
    internal static class VisioForgeSetup
    {
        static VisioForgeSetup()
        {
            // Defer: never mutate project settings, touch UnityEngine.Application, or pop UI
            // during the static-constructor / asset-import phase. delayCall fires once the
            // Editor is idle on the main thread, where Application.dataPath is safe to read.
            EditorApplication.delayCall += CheckAndPrompt;
        }

        // Stable per-project EditorPrefs key. Application.dataPath.GetHashCode() is NOT stable
        // across runtime/Editor versions (and is read lazily here, not in a static initializer),
        // so derive a deterministic key from an MD5 of the project path instead.
        private static string DismissedKey()
        {
            using var md5 = System.Security.Cryptography.MD5.Create();
            byte[] hash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(Application.dataPath));
            return "VisioForge.SetupDismissed." + System.BitConverter.ToString(hash).Replace("-", "");
        }

        private static void CheckAndPrompt()
        {
            if (IsConfigured()) return;                 // already correct (e.g. after a previous Apply)
            string dismissedKey = DismissedKey();
            if (EditorPrefs.GetBool(dismissedKey, false)) return; // user chose Skip earlier

            bool apply = EditorUtility.DisplayDialog(
                "VisioForge MediaBlocks SDK",
                "The VisioForge MediaBlocks SDK requires two project settings:\n\n" +
                "  • Api Compatibility Level = .NET Framework\n" +
                "  • Enter Play Mode Options → Disable Domain Reload\n\n" +
                "Without them the SDK fails to load (TypeLoadException) and the Editor hangs when " +
                "leaving Play mode.\n\nApply these settings now?",
                "Apply", "Skip");

            if (apply)
            {
                ApplySettings();
                Debug.Log("[VisioForge] Applied: Api Compatibility Level = .NET Framework, " +
                          "Enter Play Mode Options = Disable Domain Reload.");
            }
            else
            {
                EditorPrefs.SetBool(dismissedKey, true);
                Debug.LogWarning("[VisioForge] Skipped automatic setup. Set manually before using the SDK: " +
                                 "Project Settings → Player → Other Settings → Api Compatibility Level = " +
                                 ".NET Framework; Project Settings → Editor → Enter Play Mode Options (enabled) " +
                                 "with Reload Domain OFF.");
            }
        }

        private static bool IsConfigured()
        {
            bool apiOk = PlayerSettings.GetApiCompatibilityLevel(BuildTargetGroup.Standalone)
                         == ApiCompatibilityLevel.NET_Unity_4_8;
            bool reloadOff = EditorSettings.enterPlayModeOptionsEnabled
                             && (EditorSettings.enterPlayModeOptions & EnterPlayModeOptions.DisableDomainReload) != 0;
            return apiOk && reloadOff;
        }

        private static void ApplySettings()
        {
            PlayerSettings.SetApiCompatibilityLevel(BuildTargetGroup.Standalone,
                                                    ApiCompatibilityLevel.NET_Unity_4_8);

            EditorSettings.enterPlayModeOptionsEnabled = true;
            // OR in only the domain-reload flag (the one that hangs on the GLib thread); preserve
            // any other flags the customer may have set (e.g. DisableSceneReload) rather than
            // overwriting the whole value.
            EditorSettings.enterPlayModeOptions |= EnterPlayModeOptions.DisableDomainReload;

            AssetDatabase.SaveAssets();
        }
    }
}
