using Sentry.Unity;
using Sentry;
using System.Collections.Generic;
using System;
using Combo.Platform;

#if !UNITY_WEBGL
using Newtonsoft.Json;
#endif

namespace Combo.Core
{
    public class SentryManager : SentryRuntimeOptionsConfiguration
    {
        /// Called at the player startup by SentryInitialization.
        /// You can alter configuration for the C# error handling and also
        /// native error handling in platforms **other** than iOS, macOS and Android.
        /// Learn more at https://docs.sentry.io/platforms/unity/configuration/options/#programmatic-configuration
        [System.Serializable]
        internal class Parameters
        {
#if UNITY_WEBGL
            // WebGL 不使用 Newtonsoft，需要手动映射 key
            public string sentry_webgl_dsn;
            public string sentry_unity_enabled;
            public string sentry_unity_debug_enabled;
            public string sentry_unity_send_default_pii_enabled;
            public string sentry_unity_attach_screenshot_enabled;
            public string sentry_unity_capture_logging_error_enabled;
            public string sentry_unity_max_breadcrumbs;
            public string sentry_unity_add_breadcrumb_log_types;

            public string dsn => sentry_webgl_dsn;
            public bool enabled =>
                !string.IsNullOrEmpty(sentry_unity_enabled) &&
                bool.TryParse(sentry_unity_enabled, out var v1) ? v1 : false;

            public bool debugEnabled =>
                !string.IsNullOrEmpty(sentry_unity_debug_enabled) &&
                bool.TryParse(sentry_unity_debug_enabled, out var v2) ? v2 : false;

            public bool sendDefaultPiiEnabled =>
                !string.IsNullOrEmpty(sentry_unity_send_default_pii_enabled) &&
                bool.TryParse(sentry_unity_send_default_pii_enabled, out var v3) ? v3 : false;

            public bool attachScreenShotEnabled =>
                !string.IsNullOrEmpty(sentry_unity_attach_screenshot_enabled) &&
                bool.TryParse(sentry_unity_attach_screenshot_enabled, out var v4) ? v4 : false;

            public bool captureLoggingErrorEnabled =>
                !string.IsNullOrEmpty(sentry_unity_capture_logging_error_enabled) &&
                bool.TryParse(sentry_unity_capture_logging_error_enabled, out var v5) ? v5 : false;

            public int maxBreadcrumbs
            {
                get
                {
                    if (string.IsNullOrEmpty(sentry_unity_max_breadcrumbs))
                        return 100;

                    if (int.TryParse(sentry_unity_max_breadcrumbs, out int v))
                        return v;

                    return 100;
                }
            }

            public string addBreadcrumbsForLogTypes => sentry_unity_add_breadcrumb_log_types;

#else
            // 其他平台继续使用 Newtonsoft
#if UNITY_ANDROID
            [JsonProperty("sentry_android_dsn")]
#elif UNITY_IOS
            [JsonProperty("sentry_ios_dsn")]
#elif UNITY_STANDALONE
            [JsonProperty("sentry_windows_dsn")]
#elif UNITY_OPENHARMONY
            [JsonProperty("sentry_harmonyos_dsn")]
#endif
            public string dsn;

            [JsonProperty("sentry_unity_enabled")]
            [JsonConverter(typeof(EmptyStringToBoolConverter))]
            public bool enabled = true;

            [JsonProperty("sentry_unity_debug_enabled")]
            [JsonConverter(typeof(EmptyStringToBoolConverter))]
            public bool debugEnabled = false;

            [JsonProperty("sentry_unity_send_default_pii_enabled")]
            [JsonConverter(typeof(EmptyStringToBoolConverter))]
            public bool sendDefaultPiiEnabled = true;

            [JsonProperty("sentry_unity_attach_screenshot_enabled")]
            public bool attachScreenShotEnabled = false;

            [JsonProperty("sentry_unity_max_breadcrumbs")]
            public int maxBreadcrumbs = 100;

            [JsonProperty("sentry_unity_add_breadcrumb_log_types")]
            public string addBreadcrumbsForLogTypes;

            [JsonProperty("sentry_unity_capture_logging_error_enabled")]
            public bool captureLoggingErrorEnabled = false;
#endif
        }

        public override void Configure(SentryUnityOptions options)
        {
#if UNITY_EDITOR
            options.Enabled = false;
            return;
#else
            var parameters = Native.GetParameters<Parameters>();

#if UNITY_ANDROID
            options.AndroidNativeSupportEnabled = true;
            options.NdkIntegrationEnabled = true;
            options.NdkScopeSyncEnabled = true;
#elif UNITY_IOS
            options.IosNativeSupportEnabled = true;
#elif UNITY_STANDALONE
            options.WindowsNativeSupportEnabled = true;
#endif

            if (string.IsNullOrEmpty(parameters.dsn))
            {
                Log.E("The sentry dsn must be is not empty!");
                return;
            }
            Log.I($"Start sentry, dsn = {parameters.dsn}");
            options.Enabled = parameters.enabled;
            options.Debug = parameters.debugEnabled;
            options.AttachScreenshot = false;
            options.AttachStacktrace = true;
            options.SendDefaultPii = parameters.sendDefaultPiiEnabled;
            options.Dsn = parameters.dsn;
            options.AttachScreenshot = parameters.attachScreenShotEnabled;
            options.MaxBreadcrumbs = parameters.maxBreadcrumbs;
            options.CaptureLogErrorEvents = parameters.captureLoggingErrorEnabled;
            options.AddBreadcrumbsForLogType = GetBreadcrumbsForLogType(parameters.addBreadcrumbsForLogTypes);
            options.DisableAnrIntegration();
#endif
        }

        internal static Dictionary<UnityEngine.LogType, bool> GetBreadcrumbsForLogType(string logTypesCsv)
        {
            Dictionary<UnityEngine.LogType, bool> result = new Dictionary<UnityEngine.LogType, bool>
            {
                { UnityEngine.LogType.Log, false },
                { UnityEngine.LogType.Warning, false },
                { UnityEngine.LogType.Assert, false },
                { UnityEngine.LogType.Error, false },
                { UnityEngine.LogType.Exception, false }
            };

            if (string.IsNullOrEmpty(logTypesCsv))
            {
                return result;
            }

            string[] logTypes = logTypesCsv.Split(',');
            foreach (string type in logTypes)
            {
                if (Enum.TryParse(type.Trim(), out UnityEngine.LogType logType))
                {
                    result[logType] = true;
                }
            }

            return result;
        }

        internal static void Setup()
        {
#if !UNITY_EDITOR
            // TODO: Add more
            SentrySdk.ConfigureScope(scope =>
            {
                var variant = Native.GetVariant();
                if (!string.IsNullOrEmpty(variant))
                {
                    scope.SetTag("combo.variant", variant);
                }

                var subvariant = Native.GetSubvariant();
                if (!string.IsNullOrEmpty(subvariant))
                {
                    scope.SetTag("combo.subvariant", subvariant);
                }
                scope.SetTag("combo.device_id", Native.GetDeviceId());
                scope.SetTag("combo.distro", Native.GetDistro());
                scope.SetTag("combo.sdk.unity_version", Version.SDKVersion);
            });
#endif
        }
    }
}