package com.remax.bill.ads.pangle

import android.app.Activity
import android.content.Context
import com.bytedance.sdk.openadsdk.api.model.PAGAdEcpmInfo
import com.bytedance.sdk.openadsdk.api.model.PAGErrorModel
import com.bytedance.sdk.openadsdk.api.model.PAGRevenueInfo
import com.bytedance.sdk.openadsdk.api.reward.PAGRewardItem
import com.bytedance.sdk.openadsdk.api.reward.PAGRewardedAd
import com.bytedance.sdk.openadsdk.api.reward.PAGRewardedAdInteractionCallback
import com.bytedance.sdk.openadsdk.api.reward.PAGRewardedAdLoadCallback
import com.bytedance.sdk.openadsdk.api.reward.PAGRewardedRequest
import com.remax.bill.BuildConfig
import com.remax.bill.ads.AdException
import com.remax.bill.ads.AdResult
import com.remax.bill.ads.config.AdConfigManager
import com.remax.bill.ads.interceptor.ClickLimitInterceptor
import com.remax.bill.ads.interceptor.GlobalAdSwitchInterceptor
import com.remax.bill.ads.interceptor.InterceptorChain
import com.remax.bill.ads.interceptor.ShowCountLimitInterceptor
import com.remax.bill.ads.interceptor.ShowIntervalLimitInterceptor
import com.remax.bill.ads.log.AdLogger
import com.remax.base.ads.AdRevenueData
import com.remax.base.ads.AdRevenueManager
import com.remax.base.ads.RevenueInfo
import com.remax.bill.ads.util.PositionGet
import com.remax.bill.ui.dialog.ADLoadingDialog
import com.remax.base.ext.KvIntDelegate
import com.remax.base.report.DataReportManager
import com.remax.bill.ads.ext.CommonRewardedData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.math.ceil

/**
 * Pangle激励视频广告控制器
 * 参考文档：https://www.pangleglobal.com/integration/android-rewarded-video-ads
 */
class PangleRewardedAdController private constructor() {

    private var totalClickCount by KvIntDelegate("pangle_rewarded_ad_total_clicks", 0)
    private var totalCloseCount by KvIntDelegate("pangle_rewarded_ad_total_close", 0)
    private var totalLoadCount by KvIntDelegate("pangle_rewarded_ad_total_loads", 0)
    private var totalLoadSucCount by KvIntDelegate("pangle_rewarded_ad_total_load_suc", 0)
    private var totalShowFailCount by KvIntDelegate("pangle_rewarded_ad_total_show_fails", 0)
    private var totalShowTriggerCount by KvIntDelegate("pangle_rewarded_ad_total_show_triggers", 0)
    private var totalShowCount by KvIntDelegate("pangle_rewarded_ad_total_shows", 0)
    private var totalRewardEarnedCount by KvIntDelegate("pangle_rewarded_ad_total_reward_earned", 0)

    private var currentRewardedAd: PAGRewardedAd? = null
    private var currentAdUnitId: String? = null
    private var isShowing: Boolean = false

    companion object {
        private const val TAG = "PangleRewardedAd"

        @Volatile
        private var INSTANCE: PangleRewardedAdController? = null

        fun getInstance(): PangleRewardedAdController {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: PangleRewardedAdController().also { INSTANCE = it }
            }
        }
    }

    private val interceptorChain = InterceptorChain(
        interceptors = listOf(
            GlobalAdSwitchInterceptor(),
            ShowCountLimitInterceptor(),
            ShowIntervalLimitInterceptor(),
            ClickLimitInterceptor()
        )
    )

    suspend fun preloadAd(context: Context, adUnitId: String? = null): AdResult<Unit> {
        if (!GlobalAdSwitchInterceptor.isGlobalAdEnabled()) {
            return AdResult.Failure(
                AdException(
                    code = -100,
                    message = "激励广告全局开关已关闭，中断加载"
                )
            )
        }
        val finalAdUnitId = adUnitId ?: BuildConfig.PANGLE_REWARDED_ID
        
        // 检查当前缓存是否存在且广告已就绪
        val cachedAd = getCurrentAd(finalAdUnitId)
        if (cachedAd != null && cachedAd.isReady) {
            AdLogger.d("Pangle激励广告已有有效缓存且已就绪，广告位ID: %s，跳过加载", finalAdUnitId)
            return AdResult.Success(Unit)
        }
        
        return loadAd(context, finalAdUnitId)
    }

    suspend fun showAd(
        activity: Activity,
        adUnitId: String? = null,
        onRewardEarned: ((PAGRewardItem, CommonRewardedData) -> Unit)? = null,
        closeCallback: () -> Unit
    ): AdResult<Unit> {
        val finalAdUnitId = adUnitId ?: BuildConfig.PANGLE_REWARDED_ID

        totalShowTriggerCount++
        AdLogger.d("Pangle激励广告累积触发展示次数: $totalShowTriggerCount")
        reportAdData(
            eventName = "ad_position",
            params = mapOf(
                "ad_unit_name" to finalAdUnitId,
                "position" to PositionGet.get(),
                "number" to totalShowTriggerCount
            )
        )

//        when (val interceptResult = interceptorChain.intercept(activity, AdConfigManager.getRewardedConfig())) {
//            is AdResult.Failure -> {
//                totalShowFailCount++
//                reportAdData(
//                    eventName = "ad_show_fail",
//                    params = mapOf(
//                        "ad_unit_name" to finalAdUnitId,
//                        "position" to PositionGet.get(),
//                        "number" to totalShowFailCount,
//                        "reason" to interceptResult.error.message
//                    )
//                )
//                return interceptResult
//            }
//            else -> Unit
//        }

        return try {
            if (currentRewardedAd == null || currentAdUnitId != finalAdUnitId) {
                ADLoadingDialog.show(activity)
                val loadResult = loadAd(activity, finalAdUnitId)
                if (loadResult is AdResult.Failure) {
                    ADLoadingDialog.hide()
                    return loadResult
                }
            }

            val ad = currentRewardedAd
            if (ad != null) {
                ADLoadingDialog.hide()
                currentRewardedAd = null
                currentAdUnitId = null
                showAdInternal(activity, ad, finalAdUnitId, onRewardEarned, closeCallback)
            } else {
                ADLoadingDialog.hide()
                totalShowFailCount++
                reportAdData(
                    eventName = "ad_show_fail",
                    params = mapOf(
                        "ad_unit_name" to finalAdUnitId,
                        "position" to PositionGet.get(),
                        "number" to totalShowFailCount,
                        "reason" to "load_failed"
                    )
                )
                AdResult.Failure(createAdException("广告加载失败"))
            }
        } catch (e: Exception) {
            ADLoadingDialog.hide()
            totalShowFailCount++
            reportAdData(
                eventName = "ad_show_fail",
                params = mapOf(
                    "ad_unit_name" to finalAdUnitId,
                    "position" to PositionGet.get(),
                    "number" to totalShowFailCount,
                    "reason" to e.message.orEmpty()
                )
            )
            AdLogger.e("显示Pangle激励广告异常", e)
            AdResult.Failure(createAdException("显示广告异常: ${e.message}", e))
        }
    }

    suspend fun loadAd(context: Context, adUnitId: String): AdResult<Unit> {
        if (adUnitId.isBlank()) {
            return AdResult.Failure(createAdException("广告位ID为空"))
        }

        totalLoadCount++
        AdLogger.d("Pangle激励广告开始加载，广告位ID: $adUnitId")
        reportAdData(
            eventName = "ad_start_load",
            params = mapOf(
                "ad_unit_name" to adUnitId,
                "number" to totalLoadCount
            )
        )

        return suspendCancellableCoroutine { continuation ->
            val startTime = System.currentTimeMillis()
            val request = PAGRewardedRequest(context)

            PAGRewardedAd.loadAd(adUnitId, request, object : PAGRewardedAdLoadCallback {
                override fun onAdLoaded(ad: PAGRewardedAd) {
                    val loadTime = System.currentTimeMillis() - startTime
                    AdLogger.d("Pangle激励广告加载成功，广告位ID: %s, 耗时: %dms", adUnitId, loadTime)
                    totalLoadSucCount++
                    reportAdData(
                        eventName = "ad_loaded",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "number" to totalLoadSucCount,
                            "ad_source" to "Pangle",
                            "pass_time" to ceil(loadTime / 1000.0).toInt()
                        )
                    )
                    currentRewardedAd = ad
                    currentAdUnitId = adUnitId
                    continuation.resume(AdResult.Success(Unit))
                }

                override fun onError(model: PAGErrorModel) {
                    val code = model.errorCode
                    val message = model.errorMessage
                    val loadTime = System.currentTimeMillis() - startTime
                    AdLogger.e("Pangle激励广告加载失败，广告位ID: %s, 耗时: %dms, 错误码: %d, 错误信息: %s", adUnitId, loadTime, code, message)
                    reportAdData(
                        eventName = "ad_load_fail",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "number" to totalLoadSucCount,
                            "ad_source" to "Pangle",
                            "pass_time" to ceil(loadTime / 1000.0).toInt(),
                            "reason" to message
                        )
                    )
                    continuation.resume(AdResult.Failure(createAdException("加载失败: $message")))
                }
            })
        }
    }

    fun getCurrentAd(adUnitId: String? = null): PAGRewardedAd? {
        val targetUnitId = adUnitId ?: currentAdUnitId
        return if (currentAdUnitId == targetUnitId) currentRewardedAd else null
    }

    private suspend fun showAdInternal(
        activity: Activity,
        rewardedAd: PAGRewardedAd,
        adUnitId: String,
        onRewardEarned: ((PAGRewardItem, CommonRewardedData) -> Unit)?,
        closeCallback: () -> Unit
    ): AdResult<Unit> {
        val applicationContext = activity.applicationContext
        return suspendCancellableCoroutine { continuation ->
            var hasRewarded = false
            var currentRevenueUsd: Double? = null
            var currentCurrency: String? = null
            var currentAdSource: String? = null
            var currentPlacement: String? = null
            var currentRevenueAdUnit: String? = null

            rewardedAd.setAdInteractionCallback(object : PAGRewardedAdInteractionCallback() {
                override fun onAdShowed() {
                    AdLogger.d("Pangle激励广告开始显示")
                    isShowing = true
                    val pagRevenueInfo: PAGRevenueInfo? = rewardedAd.pagRevenueInfo
                    val ecpmInfo: PAGAdEcpmInfo? = pagRevenueInfo?.showEcpm
                    currentCurrency = ecpmInfo?.currency
                    currentAdSource = ecpmInfo?.adnName
                    currentPlacement = ecpmInfo?.placement
                    currentRevenueAdUnit = ecpmInfo?.adUnit
                    // Pangle 的 revenue 本身就是美元，直接使用
                    val revenueUsd = ecpmInfo?.revenue?.toDoubleOrNull() ?: 0.0
                    currentRevenueUsd = revenueUsd
                    val impressionValue = revenueUsd
                    totalShowCount++
                    AdConfigManager.getRewardedConfig()?.recordShow()
                    reportAdData(
                        eventName = "ad_impression",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "position" to PositionGet.get(),
                            "number" to totalShowCount,
                            "ad_source" to (currentAdSource ?: "Pangle"),
                            "value" to impressionValue,
                            "currency" to (currentCurrency ?: "USD")
                        )
                    )

                    currentRevenueUsd?.let { revenueValue ->
                        reportAdRevenueWithValue(
                            adUnitId = adUnitId,
                            valueUsd = revenueValue,
                            currencyCode = currentCurrency,
                            adNetwork = currentAdSource,
                            placement = currentPlacement,
                            ecpmAdUnitId = currentRevenueAdUnit
                        )
                        // Pangle 的 revenue 本身就是美元，直接使用
                        val revenueUsdLong = revenueValue.toLong()
                        AdLogger.d(
                            "Pangle激励广告收益上报(onShow): adUnit=%s, placement=%s, adn=%s, revenueUsd=%.4f, currency=%s",
                            currentRevenueAdUnit ?: adUnitId,
                            currentPlacement ?: "",
                            currentAdSource ?: "Pangle",
                            revenueValue,
                            currentCurrency ?: ""
                        )
                    }
                }

                override fun onAdClicked() {
                    AdLogger.d("Pangle激励广告被点击")
                    totalClickCount++
                    AdConfigManager.getRewardedConfig()?.recordClick()
                    reportAdData(
                        eventName = "ad_click",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "position" to PositionGet.get(),
                            "number" to totalClickCount,
                            "ad_source" to (currentAdSource ?: "Pangle"),
                            "value" to (rewardedAd.pagRevenueInfo?.showEcpm?.revenue?.toDoubleOrNull() ?: 0.0),
                            "currency" to (currentCurrency ?: "USD")
                        )
                    )
                }

                override fun onAdDismissed() {
                    AdLogger.d("Pangle激励广告关闭")
                    isShowing = false
                    closeEvent(
                        adUnitId = adUnitId,
                        adSource = currentAdSource,
                        valueUsd = currentRevenueUsd,
                        currencyCode = currentCurrency,
                        isEnded = if (hasRewarded) "true" else ""
                    )
                    
                    // 激励关闭时重新预缓存
                    CoroutineScope(SupervisorJob() + Dispatchers.IO).launch {
                        try {
                            AdLogger.d("Pangle激励广告关闭，开始重新预缓存，广告位ID: %s", adUnitId)
                            preloadAd(applicationContext, adUnitId)
                        } catch (e: Exception) {
                            AdLogger.e("Pangle激励广告重新预缓存失败", e)
                        }
                    }
                    
                    if (continuation.isActive) {
                        continuation.resume(AdResult.Success(Unit))
                    }

                    closeCallback.invoke()
                }

                override fun onUserEarnedReward(rewardItem: PAGRewardItem) {
                    AdLogger.d("Pangle激励广告发放奖励: name=${rewardItem.rewardName}, amount=${rewardItem.rewardAmount}")
                    totalRewardEarnedCount++
                    hasRewarded = true
                    reportAdData(
                        eventName = "ad_reward_earned",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "position" to PositionGet.get(),
                            "number" to totalRewardEarnedCount,
                            "reward_name" to rewardItem.rewardName,
                            "reward_amount" to rewardItem.rewardAmount,
                            "ad_source" to (currentAdSource ?: "Pangle")
                        )
                    )

                    val pagRevenueInfo: PAGRevenueInfo? = rewardedAd.pagRevenueInfo
                    val ecpmInfo: PAGAdEcpmInfo? = pagRevenueInfo?.showEcpm
                    // Pangle 的 revenue 本身就是美元，直接使用
                    val revenueUsd = ecpmInfo?.revenue?.toDoubleOrNull() ?: 0.0
                    onRewardEarned?.invoke(rewardItem, CommonRewardedData(revenueUsd.toDouble()))
                }

                override fun onAdReturnRevenue(pagAdEcpmInfo: PAGAdEcpmInfo?) {
                    super.onAdReturnRevenue(pagAdEcpmInfo)
                    //onRewardEarned?.invoke()
                }

                override fun onUserEarnedRewardFail(model: PAGErrorModel) {
                    AdLogger.w("Pangle激励广告奖励下发失败，错误码: ${model.errorCode}")
                }

                override fun onAdShowFailed(model: PAGErrorModel) {
                    super.onAdShowFailed(model)
                    totalShowFailCount++
                    AdLogger.e(
                        "Pangle激励广告显示失败: code=%d, message=%s",
                        model.errorCode,
                        model.errorMessage
                    )
                    reportAdData(
                        eventName = "ad_show_fail",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "position" to PositionGet.get(),
                            "number" to totalShowFailCount,
                            "reason" to model.errorMessage.orEmpty(),
                            "ad_source" to (currentAdSource ?: "Pangle")
                        )
                    )
                }
            })

            try {
                if (!rewardedAd.isReady) {
                    AdLogger.w("Pangle激励广告未就绪，无法显示")
                    isShowing = false
                    totalShowFailCount++
                    reportAdData(
                        eventName = "ad_show_fail",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "position" to PositionGet.get(),
                            "number" to totalShowFailCount,
                            "reason" to "rewarded_not_ready",
                            "ad_source" to (currentAdSource ?: "Pangle")
                        )
                    )
                    if (continuation.isActive) {
                        continuation.resume(AdResult.Failure(createAdException("广告未准备就绪")))
                    }
                    return@suspendCancellableCoroutine
                }

                rewardedAd.show(activity)
            } catch (e: Exception) {
                isShowing = false
                totalShowFailCount++
                reportAdData(
                    eventName = "ad_show_fail",
                    params = mapOf(
                        "ad_unit_name" to adUnitId,
                        "position" to PositionGet.get(),
                        "number" to totalShowFailCount,
                        "reason" to e.message.orEmpty(),
                        "ad_source" to (currentAdSource ?: "Pangle")
                    )
                )
                if (continuation.isActive) {
                    continuation.resume(AdResult.Failure(createAdException("显示异常: ${e.message}", e)))
                }
            }
        }
    }

    fun hasCachedAd(): Boolean {
        return currentRewardedAd != null
    }

    fun destroy() {
        currentRewardedAd = null
        currentAdUnitId = null
        AdLogger.d("Pangle激励广告控制器已清理")
    }

    private fun closeEvent(
        adUnitId: String,
        adSource: String? = "Pangle",
        valueUsd: Double? = null,
        currencyCode: String? = null,
        isEnded: String = ""
    ) {
        totalCloseCount++
        reportAdData(
            eventName = "ad_close",
            params = mapOf(
                "ad_unit_name" to adUnitId,
                "position" to PositionGet.get(),
                "number" to totalCloseCount,
                "ad_source" to (adSource ?: "Pangle"),
                "value" to (valueUsd ?: 0.0),
                "currency" to (currencyCode ?: "USD"),
                "isended" to isEnded
            )
        )
    }

    private fun reportAdData(eventName: String, params: Map<String, Any>) {
        val data = mutableMapOf<String, Any>(
            "ad_platform" to "Pangle",
            "ad_format" to "Rewarded"
        )
        data.putAll(params)
        if (eventName == "ad_impression") {
            DataReportManager.reportDataByName("ThinkingData", eventName, data)
        } else {
            DataReportManager.reportData(eventName, data)
        }
    }

    private fun createAdException(message: String, cause: Throwable? = null): AdException {
        return AdException(
            code = -1,
            message = message,
            cause = cause
        )
    }

    private fun reportAdRevenueWithValue(
        adUnitId: String,
        valueUsd: Double,
        currencyCode: String?,
        adNetwork: String?,
        placement: String?,
        ecpmAdUnitId: String?
    ) {
        val adRevenueData = AdRevenueData(
            revenue = RevenueInfo(
                value = valueUsd,
                currencyCode = currencyCode ?: ""
            ),
            adRevenueNetwork = adNetwork ?: "Pangle",
            adRevenueUnit = ecpmAdUnitId ?: adUnitId,
            adRevenuePlacement = placement ?: "",
            adFormat = "Rewarded"
        )

        AdRevenueManager.reportAdRevenue(adRevenueData)
        AdLogger.d(
            "Pangle激励广告真实收益数据已上报，广告位ID: %s, 收益: %.4f %s, adn=%s, placement=%s",
            ecpmAdUnitId ?: adUnitId,
            valueUsd,
            currencyCode ?: "",
            adNetwork ?: "Pangle",
            placement ?: ""
        )
    }
}
