package com.remax.bill.ads.pangle

import android.content.Context
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.bytedance.sdk.openadsdk.api.banner.PAGBannerAd
import com.bytedance.sdk.openadsdk.api.banner.PAGBannerAdInteractionCallback
import com.bytedance.sdk.openadsdk.api.banner.PAGBannerAdLoadCallback
import com.bytedance.sdk.openadsdk.api.banner.PAGBannerRequest
import com.bytedance.sdk.openadsdk.api.banner.PAGBannerSize
import com.bytedance.sdk.openadsdk.api.model.PAGErrorModel
import com.bytedance.sdk.openadsdk.api.model.PAGAdEcpmInfo
import com.bytedance.sdk.openadsdk.api.model.PAGRevenueInfo
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.base.ext.KvIntDelegate
import com.remax.base.report.DataReportManager
import com.remax.bill.ads.util.PositionGet
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.math.ceil
import kotlin.math.roundToLong

/**
 * Pangle Banner广告控制器
 * 提供标准Banner广告显示功能
 * 参考文档: https://www.pangleglobal.com/integration/android-banner-ads-sdk
 * 
 * 注意：Pangle仅支持两种Banner尺寸：300x250(dp)和320x50(dp)
 */
class PangleBannerAdController private constructor() {
    
    // 累积点击统计（持久化）
    private var totalClickCount by KvIntDelegate("pangle_banner_ad_total_clicks", 0)

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

    // 累积加载成功次数统计（持久化）
    private var totalLoadSucCount by KvIntDelegate("pangle_banner_ad_total_load_suc", 0)
    
    // 累积展示失败次数统计（持久化）
    private var totalShowFailCount by KvIntDelegate("pangle_banner_ad_total_show_fails", 0)
    
    // 累积触发统计（持久化）
    private var totalShowTriggerCount by KvIntDelegate("pangle_banner_ad_total_show_triggers", 0)
    
    // 累积展示统计（持久化）
    private var totalShowCount by KvIntDelegate("pangle_banner_ad_total_shows", 0)
    
    companion object {
        private const val TAG = "PangleBannerAdController"
        private const val AD_TIMEOUT = 1 * 60 * 60 * 1000L // 1小时过期
        private const val DEFAULT_CACHE_SIZE_PER_AD_UNIT = 1
        
        // Pangle支持的Banner尺寸
        private const val BANNER_WIDTH_320 = 320 // 320x50标准Banner
        private const val BANNER_WIDTH_300 = 300 // 300x250矩形Banner
        
        @Volatile
        private var INSTANCE: PangleBannerAdController? = null
        
        fun getInstance(): PangleBannerAdController {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: PangleBannerAdController().also { INSTANCE = it }
            }
        }
    }
    
    // 内存缓存池 - 存储预加载的广告
    private val adCachePool = mutableListOf<CachedBannerAd>()
    private val maxCacheSizePerAdUnit = DEFAULT_CACHE_SIZE_PER_AD_UNIT
    
    // 当前显示的Banner广告
    private var currentBannerAd: PAGBannerAd? = null
    
    // 拦截器链
    private val interceptorChain = InterceptorChain(
        interceptors = listOf(
            GlobalAdSwitchInterceptor(),
            ShowCountLimitInterceptor(),
            ShowIntervalLimitInterceptor(),
            ClickLimitInterceptor()
        )
    )
    
    /**
     * 缓存的Banner广告数据类
     */
    private data class CachedBannerAd(
        val ad: PAGBannerAd,
        val adUnitId: String,
        val loadTime: Long = System.currentTimeMillis()
    ) {
        fun isExpired(): Boolean {
            return System.currentTimeMillis() - loadTime > AD_TIMEOUT
        }
    }
    
    /**
     * 创建Banner尺寸对象
     * @param width Banner宽度（dp），支持320或300
     * @return PAGBannerSize对象
     */
    private fun createBannerSize(width: Int = BANNER_WIDTH_320): PAGBannerSize {
        return when (width) {
            BANNER_WIDTH_300 -> PAGBannerSize.BANNER_W_300_H_250
            else -> PAGBannerSize.BANNER_W_320_H_50
        }
    }
    
    /**
     * 预加载Banner广告
     * @param context 上下文
     * @param adUnitId 广告位ID，如果为空则使用默认ID
     * @param width Banner宽度（dp），默认320
     */
    suspend fun preloadAd(context: Context, adUnitId: String? = null, width: Int = BANNER_WIDTH_320): AdResult<Unit> {
        if(!GlobalAdSwitchInterceptor.isGlobalAdEnabled()){
            return AdResult.Failure(
                AdException(
                    code = -100,
                    message = "Banner全局广告已关闭，中断加载"
                ))
        }
        val finalAdUnitId = adUnitId ?: BuildConfig.PANGLE_BANNER_ID
        return loadAdToCache(context, finalAdUnitId, width)
    }

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

            // 创建PAGBannerSize对象
            val bannerSize = createBannerSize(width)
            
            // 创建PAGBannerRequest对象（推荐作为Activity的成员变量）
            val request = PAGBannerRequest(context,bannerSize)
            
            // 加载广告并注册回调
            PAGBannerAd.loadAd(adUnitId, request, object : PAGBannerAdLoadCallback {
                override fun onAdLoaded(ad: PAGBannerAd) {
                    val loadTime = System.currentTimeMillis() - startTime
                    AdLogger.d("Pangle Banner广告加载成功，广告位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()
                        )
                    )

                    continuation.resume(ad)
                }

                override fun onError(model :PAGErrorModel) {
                    val code = model.errorCode
                    val message = model.errorMessage
                    val loadTime = System.currentTimeMillis() - startTime
                    AdLogger.e("Pangle Banner广告加载失败，广告位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(null)
                }
            })
        }
    }
    
    /**
     * 加载广告到缓存
     */
    private suspend fun loadAdToCache(context: Context, adUnitId: String, width: Int = BANNER_WIDTH_320): AdResult<Unit> {
        return try {
            // 检查缓存是否已满
            val currentAdUnitCount = getCachedAdCount(adUnitId)
            if (currentAdUnitCount >= maxCacheSizePerAdUnit) {
                AdLogger.w("广告位 %s 缓存已满，当前缓存: %d/%d", adUnitId, currentAdUnitCount, maxCacheSizePerAdUnit)
                return AdResult.Success(Unit)
            }
            
            // 加载广告
            val bannerAd = loadAd(context, adUnitId, width)
            if (bannerAd != null) {
                synchronized(adCachePool) {
                    adCachePool.add(CachedBannerAd(bannerAd, adUnitId))
                    val currentCount = getCachedAdCount(adUnitId)
                    AdLogger.d("Pangle Banner广告加载成功并缓存，广告位ID: %s，该广告位缓存数量: %d/%d", adUnitId, currentCount, maxCacheSizePerAdUnit)
                }
                AdResult.Success(Unit)
            } else {
                AdResult.Failure(createAdException("广告加载失败"))
            }
        } catch (e: Exception) {
            AdLogger.e("Pangle Banner loadAdToCache异常", e)
            AdResult.Failure(AdException(0, "加载异常: ${e.message}", e))
        }
    }
    
    /**
     * 显示Banner广告（自动处理加载）
     * @param context 上下文
     * @param container 目标容器
     * @param adUnitId 广告位ID，如果为空则使用默认ID
     * @param width Banner宽度（dp），默认320
     */
    suspend fun showAd(
        context: Context, 
        container: ViewGroup, 
        adUnitId: String? = null,
        width: Int = BANNER_WIDTH_320
    ): AdResult<View> {
        val finalAdUnitId = adUnitId ?: BuildConfig.PANGLE_BANNER_ID
        
        // 累积触发统计
        totalShowTriggerCount++
        AdLogger.d("Pangle Banner广告累积触发展示次数: $totalShowTriggerCount")
        
        reportAdData(
            eventName = "ad_position",
            params = mapOf(
                "ad_unit_name" to finalAdUnitId,
                "position" to PositionGet.get(),
                "number" to totalShowTriggerCount
            )
        )
        
        // 拦截器检查
        when (val interceptResult = interceptorChain.intercept(context, AdConfigManager.getBannerConfig())) {
            is AdResult.Failure -> {
                // 累积展示失败次数统计
                totalShowFailCount++
                AdLogger.d("Pangle Banner广告累积展示失败次数: $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
                    )
                )
                
                AdLogger.w("Pangle Banner广告拦截器检查失败: %s", interceptResult.error.message)
                return AdResult.Failure(interceptResult.error)
            }
            else -> { /* continue */ }
        }
        
        return try {
            // 1. 尝试从缓存获取广告
            var cachedAd = getCachedAd(finalAdUnitId)
            if (cachedAd == null) {
                AdLogger.d("缓存为空，立即加载Pangle Banner广告，广告位ID: %s", finalAdUnitId)
                loadAdToCache(context, finalAdUnitId, width)
                cachedAd = getCachedAd(finalAdUnitId)
            }
            
            if (cachedAd != null) {
                if(!cachedAd.ad.isReady){
                    throw IllegalArgumentException("banner_not_ready")
                }
                AdLogger.d("使用缓存中的Pangle Banner广告，广告位ID: %s", finalAdUnitId)
                
                // 2. 获取Banner View并添加到容器
                val bannerView = cachedAd.ad.getBannerView()
                if (bannerView != null) {
                    // 清空容器
                    container.removeAllViews()
                    
                    // 注册广告事件回调（需要在显示前注册）
                    val bannerAd = cachedAd.ad
                    var currentRevenueUsd: Double? = null
                    var currentCurrency: String? = null
                    var currentAdSource: String? = null
                    var currentPlacement: String? = null
                    var currentRevenueAdUnit: String? = null

                    bannerAd.setAdInteractionListener(object : PAGBannerAdInteractionCallback() {
                        override fun onAdShowed() {
                            AdLogger.d("Pangle Banner广告开始显示")
                            val pagRevenueInfo: PAGRevenueInfo? = bannerAd.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++
                            AdLogger.d("Pangle Banner广告累积展示次数: $totalShowCount")

                            AdConfigManager.getBannerConfig().recordShow()

                            // 上报展示事件
                            reportAdData(
                                eventName = "ad_impression",
                                params = mapOf(
                                    "ad_unit_name" to finalAdUnitId,
                                    "position" to PositionGet.get(),
                                    "number" to totalShowCount,
                                    "ad_source" to (currentAdSource ?: "Pangle"),
                                    "value" to impressionValue,
                                    "currency" to (currentCurrency ?: "USD")
                                )
                            )

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

                        override fun onAdClicked() {
                            AdLogger.d("Pangle Banner广告被点击")
                            
                            // 累积点击统计
                            totalClickCount++
                            AdLogger.d("Pangle Banner广告累积点击次数: $totalClickCount")
                            
                            AdConfigManager.getBannerConfig().recordClick()
                            
                            reportAdData(
                                eventName = "ad_click",
                                params = mapOf(
                                    "ad_unit_name" to finalAdUnitId,
                                    "position" to PositionGet.get(),
                                    "number" to totalClickCount,
                                    "ad_source" to (currentAdSource ?: "Pangle"),
                                    "value" to (bannerAd.pagRevenueInfo?.showEcpm?.revenue?.toDoubleOrNull() ?: 0.0),
                                    "currency" to (currentCurrency ?: "USD")
                                )
                            )
                        }

                        override fun onAdDismissed() {
                            AdLogger.d("Pangle Banner广告关闭")
                            
                            totalCloseCount++
                            
                            reportAdData(
                                eventName = "ad_close",
                                params = mapOf(
                                    "ad_unit_name" to finalAdUnitId,
                                    "position" to PositionGet.get(),
                                    "number" to totalCloseCount,
                                    "ad_source" to (currentAdSource ?: "Pangle"),
                                    "value" to (bannerAd.pagRevenueInfo?.showEcpm?.revenue?.toDoubleOrNull() ?: 0.0),
                                    "currency" to (currentCurrency ?: "USD")
                                )
                            )
                        }

                        override fun onAdShowFailed(model: PAGErrorModel) {
                            super.onAdShowFailed(model)
                            totalShowFailCount++
                            AdLogger.e(
                                "Pangle Banner广告显示失败: code=%d, message=%s",
                                model.errorCode,
                                model.errorMessage
                            )
                            reportAdData(
                                eventName = "ad_show_fail",
                                params = mapOf(
                                    "ad_unit_name" to finalAdUnitId,
                                    "position" to PositionGet.get(),
                                    "number" to totalShowFailCount,
                                    "reason" to model.errorMessage.orEmpty(),
                                    "ad_source" to (currentAdSource ?: "Pangle")
                                )
                            )
                        }
                    })
                    
                    // 添加到容器，设置居中布局
                    val layoutParams = when (container) {
                        is FrameLayout -> {
                            FrameLayout.LayoutParams(
                                ViewGroup.LayoutParams.WRAP_CONTENT,
                                ViewGroup.LayoutParams.WRAP_CONTENT
                            ).apply {
                                gravity = Gravity.CENTER
                            }
                        }
                        else -> {
                            ViewGroup.LayoutParams(
                                ViewGroup.LayoutParams.WRAP_CONTENT,
                                ViewGroup.LayoutParams.WRAP_CONTENT
                            )
                        }
                    }
                    bannerView.layoutParams = layoutParams
                    container.addView(bannerView)
                    
                    // 保存当前广告引用
                    currentBannerAd = bannerAd
                    
                    AdResult.Success(bannerView)
                } else {
                    AdResult.Failure(createAdException("Banner View获取失败"))
                }
            } else {
                // 累积展示失败次数统计
                totalShowFailCount++
                AdLogger.d("Pangle Banner广告累积展示失败次数: $totalShowFailCount")

                reportAdData(
                    eventName = "ad_show_fail",
                    params = mapOf(
                        "ad_unit_name" to finalAdUnitId,
                        "position" to PositionGet.get(),
                        "number" to totalShowFailCount,
                        "reason" to "No fill"
                    )
                )

                AdResult.Failure(createAdException("广告加载失败"))
            }
        } catch (e: Exception) {
            reportAdData(
                eventName = "ad_show_fail",
                params = mapOf(
                    "ad_unit_name" to finalAdUnitId,
                    "position" to PositionGet.get(),
                    "number" to totalShowFailCount,
                    "reason" to e.message.orEmpty(),
                    "ad_source" to "Pangle"
                )
            )
            AdLogger.e("显示Pangle Banner广告失败", e)
            container.removeAllViews()
            AdResult.Failure(
                AdException(
                    code = -1,
                    message = "显示Pangle Banner广告异常: ${e.message}",
                    cause = e
                )
            )
        }
    }
    
    /**
     * 从缓存获取广告
     */
    private fun getCachedAd(adUnitId: String): CachedBannerAd? {
        synchronized(adCachePool) {
            val index = adCachePool.indexOfFirst { it.adUnitId == adUnitId && !it.isExpired() }
            return if (index != -1) {
                adCachePool.removeAt(index)
            } else {
                null
            }
        }
    }
    
    /**
     * 获取指定广告位的缓存数量
     */
    private fun getCachedAdCount(adUnitId: String): Int {
        synchronized(adCachePool) {
            return adCachePool.count { it.adUnitId == adUnitId && !it.isExpired() }
        }
    }
    
    /**
     * 检查指定广告位缓存是否已满
     */
    private fun isCacheFull(adUnitId: String): Boolean {
        return getCachedAdCount(adUnitId) >= maxCacheSizePerAdUnit
    }
    
    /**
     * 获取当前Banner广告View
     */
    fun getCurrentBannerView(): View? {
        return currentBannerAd?.getBannerView()
    }

    fun getCurrentAd(): PAGBannerAd? = currentBannerAd
    
    /**
     * 检查是否有可用的广告
     */
    fun isAdLoaded(): Boolean {
        return currentBannerAd != null
    }
    
    /**
     * 销毁广告
     */
    fun destroyAd() {
        synchronized(adCachePool) {
            adCachePool.forEach { it.ad.destroy() }
            adCachePool.clear()
        }
        currentBannerAd?.destroy()
        currentBannerAd = null
        AdLogger.d("Pangle Banner广告已销毁")
    }
    
    /**
     * 销毁控制器
     */
    fun destroy() {
        destroyAd()
        AdLogger.d("Pangle Banner广告控制器已清理")
    }
    
    /**
     * 创建广告异常
     */
    private fun createAdException(message: String, cause: Throwable? = null): AdException {
        return AdException(
            code = -1,
            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 "Banner"
        )
        
        // 直接合并传入的参数
        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 = "Banner"
        )

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

