package com.gh.gamecenter.feature.exposure

import android.os.Parcelable
import android.text.TextUtils
import androidx.annotation.Keep
import com.therouter.TheRouter
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.ExposureEntity
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.exposure.meta.Meta
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.pagelevel.IPageLevelProvider
import com.gh.gamecenter.common.tracker.IBusiness
import com.gh.gamecenter.common.utils.getFirstElementDividedByDivider
import com.gh.gamecenter.core.provider.IBrowserInstallHelperProvider
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.time.TimeUtil
import com.gh.gamecenter.feature.provider.IRegionSettingHelperProvider
import com.lightgame.download.DownloadEntity
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import java.util.*

@Keep
@Parcelize
data class ExposureEvent(
    var payload: ExposureEntity,
    var source: List<ExposureSource>,
    var eTrace: List<ExposureEvent>? = arrayListOf(),
    var event: ExposureType,
    val meta: Meta = MetaUtil.getMeta(),
    var time: Int = TimeUtil.currentTime(),
    var timeInMillisecond: Long = System.currentTimeMillis(),
    var id: String = UUID.randomUUID().toString(),
) : Parcelable, Cloneable {

    // 一些未在 ExposureEntity 定义的字段
    val additional: Array<String>
        get() = eTrace?.firstOrNull()?.payload?.additional ?: payload.additional ?: emptyArray()

    // 是否已经被使用过
    @IgnoredOnParcel
    private var isUsed: Boolean = false

    private fun initExposureEventData(
        gameEntity: GameEntity?,
        source: List<ExposureSource>,
        eTrace: List<ExposureEvent>? = null,
        event: ExposureType = ExposureType.EXPOSURE
    ) {
        val currentActivity = CurrentActivityHolder.getCurrentActivity()
        val currentActivitySimpleName = if (currentActivity != null) currentActivity::class.simpleName else "unknown"
        val businessId = if (currentActivity is IBusiness) currentActivity.getBusinessId() else null

        val subPageCode = gameEntity?.subPageCode
        val subPageId = gameEntity?.subPageId

        var currentPageCode = currentActivitySimpleName
        var currentPageId = businessId?.first

        // 子页面的 pageCode 添加到主页面后， pageId 优先级高于主页面 pageId
        if (!subPageCode.isNullOrEmpty()) {
            currentPageCode = "$currentActivitySimpleName-$subPageCode"
            if (!subPageId.isNullOrEmpty()) {
                currentPageId = subPageId
            }
        }

        var pageLevelString = gameEntity?.pageLevelString

        if (TextUtils.isEmpty(pageLevelString)) {
            val pageLevelProvider = currentActivity as? IPageLevelProvider
            pageLevelString = pageLevelProvider?.getPageLevel()?.toFormattedString()
        }

        if (gameEntity?.adIconActive == true) {
            gameEntity.isAdData = true
        }

        // 尝试为 gameEntity 空的 platform 赋值
        if (gameEntity?.platform == null || gameEntity.platform?.isEmpty() == true) {
            if (gameEntity?.getApk()?.size == 1) {
                val apk = gameEntity.getApk().firstOrNull()
                gameEntity.platform = apk?.getPlatform()
            } else if (gameEntity != null && gameEntity.getApk().size > 1) {
                gameEntity.platform = "全版本"
            }
        }

        // 尝试 gameEntity 的 gameVersion 赋值
        if (gameEntity?.getApk()?.size == 1) {
            gameEntity.gameVersion = gameEntity.getApk().firstOrNull()?.version ?: ""
        }

        val browserInstallHelper = TheRouter.get(IBrowserInstallHelperProvider::class.java)
        val regionSettingHelper = TheRouter.get(IRegionSettingHelperProvider::class.java)

        val firstTracePayload = eTrace?.firstOrNull()?.payload

        val adGroupId = if (!gameEntity?.adGroupId.isNullOrEmpty()) {
            gameEntity?.adGroupId
        } else {
            firstTracePayload?.adGroupId
        }

        this.payload = ExposureEntity(
            gameId = gameEntity?.id?.getFirstElementDividedByDivider(DownloadEntity.GAME_ID_DIVIDER),
            gameName = if (!firstTracePayload?.gameName.isNullOrEmpty()) {
                firstTracePayload?.gameName
            } else {
                gameEntity?.name?.removeSuffix(Constants.GAME_NAME_DECORATOR)
            },
            gameVersion = firstTracePayload?.gameVersion ?: gameEntity?.gameVersion,
            subjectId = firstTracePayload?.subjectId ?: gameEntity?.subjectId ?: gameEntity?.subjectData?.id,
            isMirrorData = firstTracePayload?.isMirrorData ?: (gameEntity?.getMirrorPosition() == 1),
            isMirrorData2 = firstTracePayload?.isMirrorData2 ?: (gameEntity?.getMirrorPosition() == 2),
            isWebDownload = browserInstallHelper?.shouldUseBrowserToInstall() ?: false
                    && browserInstallHelper?.isUseBrowserToInstallEnabled() ?: false
                    && gameEntity?.isSplitXApk() != true, // 实时的值，不用从 eTrace 里取
            sequence = firstTracePayload?.sequence ?: gameEntity?.sequence,
            outerSequence = firstTracePayload?.outerSequence ?: gameEntity?.outerSequence,
            platform = gameEntity?.platform ?: firstTracePayload?.platform,
            downloadType = gameEntity?.downloadType,
            downloadCompleteType = gameEntity?.downloadCompleteType,
            displayType = firstTracePayload?.displayType ?: gameEntity?.displayContent,
            isPlatformRecommend = gameEntity?.isPlatformRecommend,
            // ugly
            welcomeDialogId = gameEntity?.welcomeDialogId ?: firstTracePayload?.welcomeDialogId,
            welcomeDialogLinkTitle = gameEntity?.welcomeDialogTitle ?: firstTracePayload?.welcomeDialogLinkTitle,
            isAdData = gameEntity?.isAdData ?: firstTracePayload?.isAdData ?: false,
            adSpaceId = gameEntity?.adSpaceId ?: firstTracePayload?.adSpaceId ?: "",
            gameAdSourceId = gameEntity?.gameAdSourceId ?: firstTracePayload?.gameAdSourceId ?: "",
            country = regionSettingHelper?.getIpInfo()?.country ?: "",
            province = regionSettingHelper?.getIpInfo()?.province ?: "",
            city = regionSettingHelper?.getIpInfo()?.city ?: "",
            controlLinkDesc = firstTracePayload?.controlLinkDesc,
            controlLinkName = firstTracePayload?.controlLinkName,
            controlLinkType = firstTracePayload?.controlLinkType,
            miniGameUid = gameEntity?.miniGameUid ?: "",
            miniGameId = gameEntity?.miniGameAppId ?: "",
            miniGameType = gameEntity?.miniGameType ?: "",
            miniGameRecommendId = gameEntity?.miniGameRecommendId,
            downloadUrl = firstTracePayload?.downloadUrl ?:gameEntity?.downloadUrl,
            showUrl = firstTracePayload?.showUrl ?:gameEntity?.showUrl,
            additional = gameEntity?.customPageTrackData?.toKV(),
            adId = if (gameEntity?.isDspGame == true) gameEntity.dspAdId else "",

            pageLevel = pageLevelString ?: firstTracePayload?.pageLevel ?: "",
            currentPageCode = firstTracePayload?.currentPageCode ?: currentPageCode ?: "", // 这里没写错，优先使用历史的 pageCode，没有再使用当前的
            currentPageId =  firstTracePayload?.currentPageId ?: currentPageId ?: "", // 这里没写错，优先使用历史的 pageId，没有再使用当前的
            moduleStyle = gameEntity?.customPageTrackData?.modulePattern ?: firstTracePayload?.moduleStyle ?: "",
            moduleType = gameEntity?.customPageTrackData?.moduleType ?: firstTracePayload?.moduleType ?: "",
            moduleName = gameEntity?.customPageTrackData?.linkContentName ?: firstTracePayload?.moduleName ?: "",
            moduleId = gameEntity?.customPageTrackData?.linkContentId ?: firstTracePayload?.moduleId ?: "",
            searchContent = firstTracePayload?.searchContent ?: "",
            isAd = !adGroupId.isNullOrEmpty(),
            adGroupId = adGroupId,
            backendSequence = gameEntity?.backendSequence ?: firstTracePayload?.backendSequence ?: -1,
        )
        this.id = UUID.randomUUID().toString()
        this.timeInMillisecond = System.currentTimeMillis()
        this.time = TimeUtil.currentTime()
        this.source = source
        this.eTrace = eTrace
        this.event = event
        this.also {
            it.payload.categoryId = firstTracePayload?.categoryId
            it.payload.categoryV2Id = firstTracePayload?.categoryV2Id
            it.payload.testServerId = firstTracePayload?.testServerId
            it.payload.blockId = firstTracePayload?.blockId

            it.payload.setContainerInfo(
                firstTracePayload?.containerId ?: gameEntity?.containerId,
                firstTracePayload?.containerType ?: gameEntity?.containerType
            )

            it.payload.sourcePage = firstTracePayload?.sourcePage
            it.payload.sourcePageId = firstTracePayload?.sourcePageId
            it.payload.sourcePageName = firstTracePayload?.sourcePageName
            gameEntity?.exposureEvent = it
        }
    }

    fun shallowCopy(): ExposureEvent {
        return super.clone() as ExposureEvent
    }

    /**
     * 刷新曝光 ID 和曝光时间
     */
    private fun refresh() {
        this.id = UUID.randomUUID().toString()
        this.timeInMillisecond = System.currentTimeMillis()
        this.time = TimeUtil.currentTime()
        this.isUsed = false
    }

    /**
     * 获取新鲜没被使用过的曝光事件
     * 若当前 ExposureEvent 被使用过，会刷新曝光 ID 和曝光时间后再返回
     */
    fun getFreshExposureEvent(): ExposureEvent {
        if (isUsed) {
            refresh()
        }
        return this
    }

    /**
     * 曝光时间
     */
    fun refreshTime() {
        this.timeInMillisecond = System.currentTimeMillis()
        this.time = TimeUtil.currentTime()
    }

    fun markIsUsed() {
        this.isUsed = true
    }

    fun isUsed(): Boolean {
        return isUsed
    }

    override fun equals(other: Any?): Boolean {
        return if (other is ExposureEvent) {
            this.id == other.id
        } else {
            false
        }
    }

    override fun hashCode(): Int {
        return super.hashCode()
    }

    companion object {

        @JvmStatic
        fun createEvent(
            gameEntity: GameEntity?,
            source: List<ExposureSource>,
            eTrace: List<ExposureEvent>? = null,
            event: ExposureType = ExposureType.EXPOSURE
        ): ExposureEvent {
            val exposureEvent = ExposureEvent(
                payload = ExposureEntity(),
                source = source,
                eTrace = eTrace,
                event = event
            )
            exposureEvent.initExposureEventData(gameEntity, source, eTrace, event)
            return exposureEvent
        }

        @JvmStatic
        fun createEventWithSourceConcat(
            gameEntity: GameEntity?,
            basicSource: List<ExposureSource>,
            source: List<ExposureSource>,
            eTrace: List<ExposureEvent>? = null,
            event: ExposureType = ExposureType.EXPOSURE
        ): ExposureEvent {
            val concatSourceList = ArrayList<ExposureSource>().apply {
                addAll(basicSource)
                addAll(source)
            }
            return createEvent(gameEntity, concatSourceList, eTrace, event)
        }
    }
}