@file:Suppress("RedundantNullableInit")

package com.remax.bill.ads.pangle

import android.app.Activity
import android.content.Context
import com.bytedance.sdk.openadsdk.api.interstitial.PAGInterstitialAd
import com.bytedance.sdk.openadsdk.api.interstitial.PAGInterstitialAdInteractionCallback
import com.bytedance.sdk.openadsdk.api.interstitial.PAGInterstitialAdLoadCallback
import com.bytedance.sdk.openadsdk.api.interstitial.PAGInterstitialRequest
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.remax.base.ads.AdRevenueData
import com.remax.base.ads.AdRevenueManager
import com.remax.base.ads.RevenueInfo
import com.remax.base.ext.KvIntDelegate
import com.remax.base.report.DataReportManager
import com.remax.bill.BuildConfig
import com.remax.bill.ads.AdException
import com.remax.bill.ads.AdResult
import com.remax.bill.ads.FullScreenNativeAdController
import com.remax.bill.ads.config.AdConfigManager
import com.remax.bill.ads.ext.AdShowExt
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.bill.ads.util.PositionGet
import com.remax.bill.ui.FullScreenNativeAdActivity
import com.remax.bill.ui.dialog.ADLoadingDialog
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-interstitial-ads
 * 
 * 预加载说明：
 * - Pangle SDK会在广告显示或关闭后自动开始新的广告请求（自动预加载后续广告）
 * - 但第一次显示时，如果没有预加载，可能需要等待加载时间
 * - 建议在应用启动时调用preloadAd()预加载第一个广告，以提升首次显示体验
 * - 后续广告由SDK自动处理，无需手动预加载
 */
class PangleInterstitialAdController private constructor() {
    
    // 累积点击统计（持久化）
    private var totalClickCount by KvIntDelegate("pangle_interstitial_ad_total_clicks", 0)

    // 累积关闭统计（持久化）
    private var totalCloseCount by KvIntDelegate("pangle_interstitial_ad_total_close", 0)
    
    // 累积加载次数统计（持久化）
    private var totalLoadCount by KvIntDelegate("pangle_interstitial_ad_total_loads", 0)

    // 累积加载成功次数统计（持久化）
    private var totalLoadSucCount by KvIntDelegate("pangle_interstitial_ad_total_load_suc", 0)
    
    // 累积展示失败次数统计（持久化）
    private var totalShowFailCount by KvIntDelegate("pangle_interstitial_ad_total_show_fails", 0)
    
    // 累积触发统计（持久化）
    private var totalShowTriggerCount by KvIntDelegate("pangle_interstitial_ad_total_show_triggers", 0)
    
    // 累积展示统计（持久化）
    private var totalShowCount by KvIntDelegate("pangle_interstitial_ad_total_shows", 0)
    
    // 插页广告是否正在显示的标识
    private var isShowing: Boolean = false
    
    companion object {
        private const val TAG = "PangleInterstitialAdController"
        private const val LOAD_TIMEOUT = 7000L // 加载超时时间7秒
        
        @Volatile
        private var INSTANCE: PangleInterstitialAdController? = null
        
        fun getInstance(): PangleInterstitialAdController {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: PangleInterstitialAdController().also { INSTANCE = it }
            }
        }
    }
    
    // 当前加载的广告请求（推荐作为Activity的成员变量）
    private var currentInterstitialRequest: PAGInterstitialRequest? = null
    
    // 当前加载的广告对象
    private var currentInterstitialAd: PAGInterstitialAd? = null
    
    // 拦截器链
    private val interceptorChain = InterceptorChain(
        interceptors = listOf(
            GlobalAdSwitchInterceptor(),
            ShowCountLimitInterceptor(),
            ShowIntervalLimitInterceptor(),
            ClickLimitInterceptor()
        )
    )
    
    /**
     * 预加载插页广告
     * 建议在应用启动时调用此方法预加载第一个广告，以提升首次显示体验
     * 注意：后续广告由Pangle SDK自动预加载，无需手动调用
     * 
     * @param context 上下文
     * @param adUnitId 广告位ID
     */
    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_INTERSTITIAL_ID
        
        // 检查当前缓存是否存在且广告已就绪
        val cachedAd = getCurrentAd()
        if (cachedAd != null && cachedAd.isReady) {
            AdLogger.d("Pangle插页广告已有有效缓存且已就绪，广告位ID: %s，跳过加载", finalAdUnitId)
            return AdResult.Success(Unit)
        }
        
        return loadAd(context, finalAdUnitId)
    }

    /**
     * 基础广告加载方法
     */
    private suspend fun loadAd(context: Context, adUnitId: String): AdResult<Unit> {
        // 累积加载次数统计
        totalLoadCount++
        AdLogger.d("Pangle插页广告累积加载次数: $totalLoadCount")
        
        reportAdData(
            eventName = "ad_start_load",
            params = mapOf(
                "ad_unit_name" to adUnitId,
                "number" to totalLoadCount
            )
        )
        
        return suspendCancellableCoroutine { continuation ->
            val startTime = System.currentTimeMillis()

            // 创建PAGInterstitialRequest对象（推荐作为Activity的成员变量）
            val request = PAGInterstitialRequest(context)
            currentInterstitialRequest = request
            
            // 加载广告并注册回调
            PAGInterstitialAd.loadAd(adUnitId, request, object : PAGInterstitialAdLoadCallback {
                override fun onAdLoaded(ad: PAGInterstitialAd) {
                    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()
                        )
                    )

                    currentInterstitialAd = ad
                    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
                        )
                    )
                    
                    currentInterstitialAd = null
                    continuation.resume(AdResult.Failure(
                        createAdException("广告加载失败: ${message} (code: ${code})")
                    ))
                }
            })
        }
    }
    
    /**
     * 显示插页广告
     * @param activity Activity上下文
     * @param adUnitId 广告位ID，如果为空则使用默认ID
     * @param ignoreFullNative 是否忽略全屏原生广告
     */
    suspend fun showAd(
        activity: Activity, 
        adUnitId: String? = null,
        ignoreFullNative: Boolean = false
    ): AdResult<Unit> {
        val finalAdUnitId = adUnitId ?: BuildConfig.PANGLE_INTERSTITIAL_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.getInterstitialConfig())) {
            is AdResult.Failure -> {
                // 累积展示失败次数统计
                totalShowFailCount++
                AdLogger.d("Pangle插页广告累积展示失败次数: $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 -> { /* continue */ }
        }

        // 是否加载全屏原生
        val interval = AdConfigManager.getFullscreenNativeAfterInterstitialCount()
        val todayShowInter = AdConfigManager.getInterstitialConfig().getDailyShowCount()
        val needShowNativeFull = interval > 0 && todayShowInter > 0 && todayShowInter % interval == 0
        AdLogger.d("当日已展示${todayShowInter}个插页，每显示${interval}个插页将显示原生，下一个是否显示全屏原生${needShowNativeFull}")

        if(!ignoreFullNative && needShowNativeFull){
            return AdShowExt.showFullScreenNativeAdInContainer(activity,true)
        }

        return try {
            // 1. 如果当前没有加载的广告，先加载
            if (currentInterstitialAd == null) {
                // 插页阻塞loading
                ADLoadingDialog.show(activity)
                AdLogger.d("当前没有广告，立即加载Pangle插页广告，广告位ID: %s", finalAdUnitId)
                val loadResult = loadAd(activity, finalAdUnitId)
                if (loadResult is AdResult.Failure) {
                    ADLoadingDialog.hide()
                    return loadResult
                }
            }

            val ad = currentInterstitialAd
            if (ad != null) {
                ADLoadingDialog.hide()
                AdLogger.d("显示Pangle插页广告，广告位ID: %s", finalAdUnitId)

                // 2. 显示广告
                val result = showAdInternal(activity, ad, finalAdUnitId)
                
                // 清空当前广告，Pangle SDK会自动加载下一个
                currentInterstitialAd = null
                
                result
            } else {
                ADLoadingDialog.hide()
                AdResult.Failure(createAdException("广告加载失败"))
            }
        } catch (e: Exception) {
            AdLogger.e("显示Pangle插页广告异常", e)
            AdResult.Failure(createAdException("显示广告异常: ${e.message}", e))
        } finally {
            ADLoadingDialog.hide()
        }
    }
    
    /**
     * 显示广告的内部实现
     */
    @Suppress("RedundantNullableInit")
    private suspend fun showAdInternal(
        activity: Activity, 
        interstitialAd: PAGInterstitialAd, 
        adUnitId: String
    ): AdResult<Unit> {
        val applicationContext = activity.applicationContext
        return suspendCancellableCoroutine { continuation ->
            // 临时变量保存收益数据
            var currentRevenueUsd: Double? = null
            var currentCurrency: String? = null
            var currentAdSource: String? = null
            interstitialAd.setAdInteractionListener(object : PAGInterstitialAdInteractionCallback() {
                override fun onAdShowed() {
                    AdLogger.d("Pangle插页广告开始显示")
                    val pagRevenueInfo: PAGRevenueInfo? = interstitialAd.pagRevenueInfo
                    val ecpmInfo: PAGAdEcpmInfo? = pagRevenueInfo?.showEcpm
                    currentCurrency = ecpmInfo?.currency
                    currentAdSource = ecpmInfo?.adnName
                    val currentPlacement = ecpmInfo?.placement
                    val currentRevenueAdUnit = ecpmInfo?.adUnit
                    // Pangle 的 revenue 本身就是美元，直接使用
                    val revenueUsd = ecpmInfo?.revenue?.toDoubleOrNull() ?: 0.0
                    currentRevenueUsd = revenueUsd
                    val impressionValue = revenueUsd

                    // 设置广告正在显示标识
                    isShowing = true

                    // 累积展示统计
                    totalShowCount++
                    AdLogger.d("Pangle插页广告累积展示次数: $totalShowCount")

                    AdConfigManager.getInterstitialConfig().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++
                    AdLogger.d("Pangle插页广告累积点击次数: $totalClickCount")
                    
                    AdConfigManager.getInterstitialConfig().recordClick()
                    
                    val pagRevenueInfo: PAGRevenueInfo? = interstitialAd.pagRevenueInfo
                    val ecpmInfo: PAGAdEcpmInfo? = pagRevenueInfo?.showEcpm
                    val revenueValue = ecpmInfo?.revenue?.toDoubleOrNull() ?: 0.0
                    
                    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 revenueValue,
                            "currency" to (currentCurrency ?: "USD")
                        )
                    )
                }

                override fun onAdDismissed() {
                    AdLogger.d("Pangle插页广告关闭")
                    
                    // 设置广告不再显示标识
                    isShowing = false
                    
                    totalCloseCount++
                    
                    val pagRevenueInfo: PAGRevenueInfo? = interstitialAd.pagRevenueInfo
                    val ecpmInfo: PAGAdEcpmInfo? = pagRevenueInfo?.showEcpm
                    val revenueValue = ecpmInfo?.revenue?.toDoubleOrNull() ?: 0.0
                    
                    reportAdData(
                        eventName = "ad_close",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "position" to PositionGet.get(),
                            "number" to totalCloseCount,
                            "ad_source" to (currentAdSource ?: "Pangle"),
                            "value" to revenueValue,
                            "currency" to (currentCurrency ?: "USD")
                        )
                    )
                    
                    // 插页关闭时重新预缓存
                    CoroutineScope(SupervisorJob() + Dispatchers.IO).launch {
                        try {
                            AdLogger.d("Pangle插页广告关闭，开始重新预缓存，广告位ID: %s", adUnitId)
                            preloadAd(applicationContext, adUnitId)
                        } catch (e: Exception) {
                            AdLogger.e("Pangle插页广告重新预缓存失败", e)
                        }
                    }
                    
                    val result = AdResult.Success(Unit)
                    if (continuation.isActive) {
                        continuation.resume(result)
                    }
                }

                override fun onAdShowFailed(error: PAGErrorModel) {
                    super.onAdShowFailed(error)
                    totalShowFailCount++
                    AdLogger.e(
                        "Pangle插页广告显示失败: code=%d, message=%s",
                        error.errorCode,
                        error.errorMessage
                    )
                    reportAdData(
                        eventName = "ad_show_fail",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "position" to PositionGet.get(),
                            "number" to totalShowFailCount,
                            "reason" to error.errorMessage.orEmpty(),
                            "ad_source" to (currentAdSource ?: "Pangle")
                        )
                    )
                }
            })
            
            if (!interstitialAd.isReady) {
                AdLogger.w("Pangle插页广告未就绪，无法显示")
                totalShowFailCount++
                reportAdData(
                    eventName = "ad_show_fail",
                    params = mapOf(
                        "ad_unit_name" to adUnitId,
                        "position" to PositionGet.get(),
                        "number" to totalShowFailCount,
                        "reason" to "interstitial_not_ready",
                        "ad_source" to (currentAdSource ?: "Pangle")
                    )
                )
                val result = AdResult.Failure(createAdException("广告未准备就绪"))
                if (continuation.isActive) {
                    continuation.resume(result)
                }
                return@suspendCancellableCoroutine
            }

            // 显示广告（必须在主线程调用）
            try {
                interstitialAd.show(activity)
            } catch (e: Exception) {
                AdLogger.e("显示Pangle插页广告异常", e)
                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")
                    )
                )
                val result = AdResult.Failure(createAdException("显示失败: ${e.message}", e))
                if (continuation.isActive) {
                    continuation.resume(result)
                }
            }
        }
    }

    fun getCurrentAd(): PAGInterstitialAd? = currentInterstitialAd

    /**
     * 销毁广告
     */
    fun destroyAd() {
        currentInterstitialAd = null
        currentInterstitialRequest = null
        AdLogger.d("Pangle插页广告已销毁")
    }
    
    /**
     * 销毁控制器
     */
    fun destroy() {
        destroyAd()
        AdLogger.d("Pangle插页广告控制器已清理")
    }
    
    /**
     * 获取插页广告是否正在显示的状态
     * @return true 如果插页广告正在显示，false 否则
     */
    fun isAdShowing(): Boolean {
        return isShowing
    }
    
    /**
     * 创建广告异常
     */
    private fun createAdException(message: String, cause: Throwable? = null): AdException {
        return AdException(
            code = 0,
            message = message,
            cause = cause
        )
    }
    
    /**
     * 通用数据上报函数
     * @param eventName 事件名称
     * @param params 参数Map，会与基础参数合并
     */
    private fun reportAdData(eventName: String, params: Map<String, Any>) {
        val data = mutableMapOf<String, Any>(
            "ad_platform" to "Pangle",
            "ad_format" to "Interstitial"
        )
        
        // 直接合并传入的参数
        data.putAll(params)

        if(eventName == "ad_impression"){
            DataReportManager.reportDataByName("ThinkingData", eventName, data)
        } else{
            DataReportManager.reportData(eventName, data)
        }
    }

    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 = "Interstitial"
        )

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

