package com.lg

import android.content.Context
import android.text.TextUtils
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.core.HaloApp
import com.gh.gamecenter.core.provider.IAcceleratorDataHolderProvider
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.ISentryProvider
import com.gh.sentry.BuildConfig
import com.lightgame.utils.AppManager
import com.lightgame.utils.Utils
import com.therouter.TheRouter
import io.sentry.*
import io.sentry.android.core.SentryAndroid
import io.sentry.android.fragment.FragmentLifecycleIntegration
import io.sentry.protocol.Message
import io.sentry.protocol.User

@com.therouter.inject.ServiceProvider
class SentryProviderImpl : ISentryProvider {

    override fun init(context: Context, channel: String, flavor: String, versionName: String) {
        SentryAndroid.init(context) { options ->
            // Sentry 疯狂报 ANR (很大一部分还是莫名奇妙的 ANR)严重影响到其它闪退日志的收集
            // 这里将它局限到只有官网渠道的包才统计 ANR
            if ("GH_206" == channel || com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
                options.setAnrEnabled(true)
                options.setAnrTimeoutIntervalMillis(6000)
            } else {
                options.setAnrEnabled(false)
            }

            val androidId = MetaUtil.getBase64EncodedAndroidId()

            if (androidId.isNotEmpty()) {
                val user = User()
                user.id = androidId
                Sentry.setUser(user)
            }

            options.setDebug(BuildConfig.DEBUG)
            options.setEnableAutoSessionTracking(true)
            options.setEnvironment(flavor)
            options.setEnableRootCheck(false)
            options.setEnableSystemEventBreadcrumbs(false)
            options.setDsn("https://6b1caf0d17c1408e8680f3f73ff80bd0@sentry.shanqu.cc/22")
            // 禁止Sentry上报Fragment和View生命周期相关的信息，因为目前Sentry上报的这些内容相关的类名仍然是混淆后的类名，没有什么参考价值
            options.addIntegration(
                FragmentLifecycleIntegration(
                    HaloApp.getInstance(),
                    enableFragmentLifecycleBreadcrumbs = false, // enabled by default
                    enableAutoFragmentLifecycleTracing = false  // disabled by default
                )
            )

            options.beforeSend = object : SentryOptions.BeforeSendCallback {
                override fun execute(event: SentryEvent, hint: Hint): SentryEvent? {
                    return if (BuildConfig.DEBUG) {
                        null
                    } else {
                        event
                    }
                }
            }

            options.setBeforeBreadcrumb { breadcrumb, _ ->
                if ("ui.lifecycle" == breadcrumb.getCategory() && "started" == breadcrumb.getData("state") && AppManager.getInstance()
                        .currentActivity() is BaseActivity
                ) {
                    val businessId = (AppManager.getInstance().currentActivity() as? BaseActivity)?.getBusinessId()
                    if (businessId != null) {
                        breadcrumb.setData("businessId1", businessId.component1())
                        breadcrumb.setData("businessId2", businessId.component2())
                    }
                }
                breadcrumb
            }
        }

        Sentry.configureScope(object : ScopeCallback {
            override fun run(scope: Scope) {
                if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
                    scope.setTag("alias", "内测版$versionName")
                } else {
                    scope.setTag("alias", "正式版$versionName")
                    scope.setTag("channel", channel)
                }
            }
        })
    }

    override fun onEvent(eventId: String, vararg kv: String?) {
        val sentryEvent = SentryEvent()
        val message = Message()
        message.message = eventId
        sentryEvent.message = message
        sentryEvent.level = SentryLevel.INFO

        for (i in kv.indices) {
            if (i % 2 != 0) {
                val key = kv[i - 1]
                val value = kv[i]
                if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
                    sentryEvent.setTag(key!!, value!!)
                    if (BuildConfig.DEBUG && isContainChinese(key)) {
                        throw RuntimeException("tag-key 不支持中文")
                    }
                }
            }
        }

        Utils.log("Sentry", "$eventId + [${kv.joinToString(" , ")}]")
        val appProvider = TheRouter.get(IAppProvider::class.java)
        // 仅 GH_206 渠道上报测试用的日志
        if (appProvider?.getChannel() == "GH_206") {
            Sentry.captureEvent(sentryEvent)
        }
    }

    override fun onEventInAllChannel(eventId: String, vararg kv: String?) {
        val sentryEvent = SentryEvent()
        val message = Message()
        message.message = eventId
        sentryEvent.message = message
        sentryEvent.level = SentryLevel.INFO

        for (i in kv.indices) {
            if (i % 2 != 0) {
                val key = kv[i - 1]
                val value = kv[i]
                if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
                    sentryEvent.setTag(key!!, value!!)
                    if (BuildConfig.DEBUG && isContainChinese(key)) {
                        throw RuntimeException("tag-key 不支持中文")
                    }
                }
            }
        }

        Utils.log("Sentry", "$eventId + [${kv.joinToString(" , ")}]")
        Sentry.captureEvent(sentryEvent)
    }

    override fun captureException(e: Throwable) {
        Sentry.captureException(e)
    }

    // 判断一个字符串是否含有中文
    private fun isContainChinese(str: String?): Boolean {
        if (str == null) return false
        for (c in str.toCharArray()) {
            if (c.toInt() in 0x4E00..0x9FA5) return true
        }
        return false
    }
}
