package com.remax.bill.ads

import android.content.Context
import android.util.Log
import android.view.View
import android.view.ViewGroup
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdSize
import com.google.android.gms.ads.AdValue
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.OnPaidEventListener
import com.remax.bill.BuildConfig
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.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.log.AdLogger
import kotlin.math.ceil
import com.remax.bill.ui.BannerAdView
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch

/**
 * Banner广告控制器
 * 提供标准Banner广告显示功能
 */
class BannerAdController private constructor() {
    
    // 累积点击统计（持久化）
    private var totalClickCount by KvIntDelegate("banner_ad_total_clicks", 0)

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

    // 累积加载成功次数统计（持久化）
    private var totalLoadSucCount by KvIntDelegate("banner_ad_total_load_suc", 0)
    
    // 累积展示失败次数统计（持久化）
    private var totalShowFailCount by KvIntDelegate("banner_ad_total_show_fails", 0)
    
    // 累积触发统计（持久化）
    private var totalShowTriggerCount by KvIntDelegate("banner_ad_total_show_triggers", 0)
    
    // 累积展示统计（持久化）
    private var totalShowCount by KvIntDelegate("banner_ad_total_shows", 0)
    
    // 当前广告的收益信息（临时存储）
    private var currentAdValue: AdValue? = null
    
    companion object {
        private const val TAG = "BannerAdController"
        private const val AD_TIMEOUT = 1 * 60 * 60 * 1000L
        private const val DEFAULT_CACHE_SIZE_PER_AD_UNIT = 1
        
        @Volatile
        private var INSTANCE: BannerAdController? = null
        
        fun getInstance(): BannerAdController {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: BannerAdController().also { INSTANCE = it }
            }
        }
    }
    
    // 内存缓存池 - 存储预加载的广告
    private val adCachePool = mutableListOf<CachedBannerAd>()
    private val maxCacheSizePerAdUnit = DEFAULT_CACHE_SIZE_PER_AD_UNIT
    
    // 拦截器链
    private val interceptorChain = InterceptorChain(
        interceptors = listOf(
            GlobalAdSwitchInterceptor(),
            ShowCountLimitInterceptor(),
            ShowIntervalLimitInterceptor(),
            ClickLimitInterceptor()
        )
    )
    
    /**
     * 缓存的Banner广告数据类
     */
    private data class CachedBannerAd(
        val adView: AdView,
        val adUnitId: String,
        val loadTime: Long = System.currentTimeMillis()
    ) {
        fun isExpired(): Boolean {
            return System.currentTimeMillis() - loadTime > AD_TIMEOUT
        }
    }
    
    private var bannerAdView: AdView? = null
    private var loadTime: Long = 0L
    private val adUnitId = BuildConfig.ADMOB_BANNER_ID
    private val bannerView = BannerAdView()
    
    // 状态流
    private val _loadingState = MutableStateFlow<AdResult<AdView>>(AdResult.Loading)
    val loadingState: StateFlow<AdResult<AdView>> = _loadingState.asStateFlow()
    
    private val _adExpiredState = MutableStateFlow(false)
    val adExpiredState: StateFlow<Boolean> = _adExpiredState.asStateFlow()
    
    /**
     * 创建Banner广告视图
     * @param context 上下文
     * @param adUnitId 广告位ID，如果为空则使用默认ID
     */
    fun createBannerAdView(context: Context, adUnitId: String? = null): AdView {
        return AdView(context).apply {
            this.adUnitId = adUnitId ?: BuildConfig.ADMOB_BANNER_ID
            setAdSize(AdSize.BANNER) // 320x50 标准Banner尺寸
        }
    }
    
    /**
     * 从缓存获取广告
     */
    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
    }
    
    /**
     * 创建广告异常
     */
    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 "Admob",
            "ad_format" to "Banner"
        )
        
        // 直接合并传入的参数
        data.putAll(params)

        if(eventName == "ad_impression"){
            DataReportManager.reportDataByName("ThinkingData",eventName, data)
        } else{
            DataReportManager.reportData(eventName, data)
        }
    }
    
    /**
     * 加载Banner广告
     * @param context 上下文
     * @param adView AdView实例
     */
    private suspend fun loadAdInternal(context: Context, adView: AdView): AdView? {
        // 累积加载次数统计
        totalLoadCount++
        AdLogger.d("AdmobBanner广告累积加载次数: $totalLoadCount")
        
        reportAdData(
            eventName = "ad_start_load",
            params = mapOf(
                "ad_unit_name" to adView.adUnitId,
                "number" to totalLoadCount
            )
        )
        
        return suspendCancellableCoroutine { continuation ->
            // 设置收益监听器
            adView.onPaidEventListener = OnPaidEventListener { adValue ->
                AdLogger.d("AdmobBanner广告收益回调: value=${adValue.valueMicros}, currency=${adValue.currencyCode}")

                // 存储当前广告的收益信息
                currentAdValue = adValue

                reportAdData(
                    eventName = "ad_impression",
                    params = mapOf(
                        "ad_unit_name" to adView.adUnitId,
                        "position" to context::class.java.simpleName,
                        "number" to totalShowCount,
                        "ad_source" to (adView.responseInfo?.loadedAdapterResponseInfo?.adSourceName.orEmpty()),
                        "value" to (currentAdValue?.let { it.valueMicros / 1_000_000.0 } ?: 0.0),
                        "currency" to (currentAdValue?.currencyCode ?: "")
                    )
                )

                // 上报真实的广告收益数据
                reportAdRevenueWithValue(adView, adValue)
            }

            adView.adListener = object : AdListener() {
                private var loadStartTime = System.currentTimeMillis()
                
                override fun onAdLoaded() {
                    val loadTime = System.currentTimeMillis() - loadStartTime
                    AdLogger.d("AdmobBanner广告加载成功，广告位ID: %s, 耗时: %dms", adView.adUnitId, loadTime)
                    totalLoadSucCount++
                    reportAdData(
                        eventName = "ad_loaded",
                        params = mapOf(
                            "ad_unit_name" to adView.adUnitId,
                            "number" to totalLoadSucCount,
                            "ad_source" to (adView.responseInfo?.loadedAdapterResponseInfo?.adSourceName.orEmpty()),
                            "pass_time" to ceil(loadTime / 1000.0).toInt()
                        )
                    )
                    // 重置开始时间，为下次刷新做准备
                    loadStartTime = System.currentTimeMillis()
                    continuation.resume(adView)
                }
                
                override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                    val loadTime = System.currentTimeMillis() - loadStartTime
                    AdLogger.e("AdmobBanner广告加载失败，广告位ID: %s, 耗时: %dms, 错误: %s", adView.adUnitId, loadTime, loadAdError.message)
                    
                    reportAdData(
                        eventName = "ad_load_fail",
                        params = mapOf(
                            "ad_unit_name" to adView.adUnitId,
                            "number" to totalLoadSucCount,
                            "ad_source" to (loadAdError.responseInfo?.loadedAdapterResponseInfo?.adSourceName.orEmpty()),
                            "pass_time" to ceil(loadTime / 1000.0).toInt(),
                            "reason" to loadAdError.message
                        )
                    )
                    
                    // 重置开始时间，为下次刷新做准备
                    loadStartTime = System.currentTimeMillis()
                    continuation.resume(null)
                }
                
                override fun onAdClicked() {
                    AdLogger.d("AdmobBanner广告被点击")
                    
                    // 累积点击统计
                    totalClickCount++
                    AdLogger.d("AdmobBanner广告累积点击次数: $totalClickCount")
                    
                    AdConfigManager.getBannerConfig().recordClick()
                    
                    reportAdData(
                        eventName = "ad_click",
                        params = mapOf(
                            "ad_unit_name" to adView.adUnitId,
                            "position" to context::class.java.simpleName,
                            "number" to totalClickCount,
                            "ad_source" to (adView.responseInfo?.loadedAdapterResponseInfo?.adSourceName.orEmpty()),
                            "value" to (currentAdValue?.let { it.valueMicros / 1_000_000.0 } ?: 0.0),
                            "currency" to (currentAdValue?.currencyCode ?: "")
                        )
                    )
                }
                
                override fun onAdImpression() {
                    AdLogger.d("AdmobBanner广告展示完成")
                    
                    // 累积展示统计
                    totalShowCount++
                    AdLogger.d("AdmobBanner广告累积展示次数: $totalShowCount")
                }
                
                override fun onAdOpened() {
                    AdLogger.d("AdmobBanner广告打开")
                }
                
                override fun onAdClosed() {
                    AdLogger.d("AdmobBanner广告关闭")
                    totalCloseCount++
                    reportAdData(
                        eventName = "ad_close",
                        params = mapOf(
                            "ad_unit_name" to adUnitId,
                            "position" to context::class.java.simpleName,
                            "number" to totalCloseCount,
                            "ad_source" to (adView.responseInfo?.loadedAdapterResponseInfo?.adSourceName.orEmpty()),
                            "value" to ((currentAdValue?.valueMicros ?: 0) / 1_000_000.0),
                            "currency" to (currentAdValue?.currencyCode ?: "")
                        )
                    )
                }
            }
            
            // 加载广告
            adView.loadAd(AdRequest.Builder().build())
        }
    }
    
    /**
     * 加载广告到缓存
     */
    private suspend fun loadAdToCache(context: Context, adUnitId: String): AdResult<Unit> {
        return try {
            // 检查缓存是否已满
            val currentAdUnitCount = getCachedAdCount(adUnitId)
            if (currentAdUnitCount >= maxCacheSizePerAdUnit) {
                AdLogger.w("Admob广告位 %s 缓存已满，当前缓存: %d/%d", adUnitId, currentAdUnitCount, maxCacheSizePerAdUnit)
                return AdResult.Success(Unit)
            }
            val adView = createBannerAdView(context, adUnitId)
            val loadedAdView = loadAdInternal(context, adView)
            if (loadedAdView != null) {
                synchronized(adCachePool) {
                    adCachePool.add(CachedBannerAd(loadedAdView, adUnitId))
                    val currentCount = getCachedAdCount(adUnitId)
                    AdLogger.d("AdmobBanner广告加载成功并缓存，广告位ID: %s，该广告位缓存数量: %d/%d", adUnitId, currentCount, maxCacheSizePerAdUnit)
                }
                AdResult.Success(Unit)
            } else {
                AdResult.Failure(createAdException("广告加载失败"))
            }
        } catch (e: Exception) {
            AdLogger.e("AdmobBanner loadAdToCache异常", e)
            AdResult.Failure(AdException(0, "加载异常: ${e.message}", e))
        }
    }
    
    /**
     * 预加载Banner广告（可选，用于提前准备）
     * @param context 上下文
     * @param adUnitId 广告位ID，如果为空则使用默认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.ADMOB_BANNER_ID
        return loadAdToCache(context, finalAdUnitId)
    }
    
    /**
     * 显示Banner广告（自动处理加载）
     * @param context 上下文
     * @param container 目标容器
     * @param adUnitId 广告位ID，如果为空则使用默认ID
     */
    suspend fun showAd(context: Context, container: ViewGroup, adUnitId: String? = null): AdResult<AdView> {
        val finalAdUnitId = adUnitId ?: BuildConfig.ADMOB_BANNER_ID
        
        // 累积触发统计
        totalShowTriggerCount++
        AdLogger.d("AdmobBanner广告累积触发展示次数: $totalShowTriggerCount")
        
        reportAdData(
            eventName = "ad_position",
            params = mapOf(
                "ad_unit_name" to finalAdUnitId,
                "position" to context::class.java.simpleName,
                "number" to totalShowTriggerCount
            )
        )
        
        // 拦截器检查
        when (val interceptResult = interceptorChain.intercept(context, AdConfigManager.getBannerConfig())) {
            is AdResult.Failure -> {
                // 累积展示失败次数统计
                totalShowFailCount++
                AdLogger.d("AdmobBanner广告累积展示失败次数: $totalShowFailCount")
                
                reportAdData(
                    eventName = "ad_show_fail",
                    params = mapOf(
                        "ad_unit_name" to finalAdUnitId,
                        "position" to context::class.java.simpleName,
                        "number" to totalShowFailCount,
                        "reason" to interceptResult.error.message
                    )
                )
                
                AdLogger.w("AdmobBanner广告拦截器检查失败: %s", interceptResult.error.message)
                return AdResult.Failure(interceptResult.error)
            }
            else -> { /* continue */ }
        }
        
        return try {
            // 1. 尝试从缓存获取广告
            var cachedAd = getCachedAd(finalAdUnitId)
            if (cachedAd == null) {
                AdLogger.d("Admob缓存为空，立即加载Banner广告，广告位ID: %s", finalAdUnitId)
                loadAdToCache(context, finalAdUnitId)
                cachedAd = getCachedAd(finalAdUnitId)
            }
            
            if (cachedAd != null) {
                AdLogger.d("Admob使用缓存中的Banner广告，广告位ID: %s", finalAdUnitId)
                
                // 显示加载视图
                container.removeAllViews()
//                container.addView(bannerView.createBannerLoadingView(context))
                
                val success = bannerView.bindBannerAdToContainer(
                    context, container, cachedAd.adView, null
                )
                
                if (success) {
                    AdConfigManager.getBannerConfig().recordShow()
                    if (!isCacheFull(finalAdUnitId)) {
                        PreloadController.preload(context)
                    }
                    AdResult.Success(cachedAd.adView)
                } else {
                    AdResult.Failure(createAdException("广告绑定失败"))
                }
            } else {
                // 累积展示失败次数统计
                totalShowFailCount++
                AdLogger.d("AdmobBanner广告累积展示失败次数: $totalShowFailCount")

                reportAdData(
                    eventName = "ad_show_fail",
                    params = mapOf(
                        "ad_unit_name" to finalAdUnitId,
                        "position" to context::class.java.simpleName,
                        "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 context::class.java.simpleName,
                    "number" to totalShowFailCount,
                    "reason" to e.message.orEmpty()
                )
            )
            AdLogger.e("Admob显示Banner广告失败", e)
            container.removeAllViews()
            AdResult.Failure(
                AdException(
                    code = -1,
                    message = "显示Banner广告异常: ${e.message}",
                    cause = e
                )
            )
        }
    }
    

    
    /**
     * 获取当前广告视图
     */
    fun getCurrentAdView(): AdView? {
        return if (!isAdExpired()) bannerAdView else null
    }
    
    /**
     * 检查是否有可用的广告
     */
    fun isAdLoaded(): Boolean {
        return bannerAdView != null && !isAdExpired()
    }
    
    /**
     * 检查广告是否已过期
     */
    fun isAdExpired(): Boolean {
        val expired = loadTime != 0L && System.currentTimeMillis() - loadTime > AD_TIMEOUT
        if (expired && !_adExpiredState.value) {
            _adExpiredState.value = true
            AdLogger.d("Banner广告已过期")
        }
        return expired
    }
    

    
    /**
     * 获取剩余有效时间（毫秒）
     */
    fun getRemainingTime(): Long {
        if (loadTime == 0L) return 0L
        val remaining = AD_TIMEOUT - (System.currentTimeMillis() - loadTime)
        return if (remaining > 0) remaining else 0L
    }
    
    /**
     * 暂停广告
     */
    fun pauseAd() {
        bannerAdView?.pause()
        AdLogger.d("Banner广告已暂停")
    }
    
    /**
     * 上报广告收益数据（使用真实收益值）
     * @param adView Banner广告视图
     * @param adValue 广告收益值
     */
    private fun reportAdRevenueWithValue(adView: AdView, adValue: AdValue) {
        // 创建广告收益数据
        val adRevenueData = AdRevenueData(
            revenue = RevenueInfo(
                value = adValue.valueMicros / 1_000_000.0,
                currencyCode = adValue.currencyCode
            ),
            adRevenueNetwork = adView.responseInfo?.loadedAdapterResponseInfo?.adSourceName.orEmpty(),
            adRevenueUnit = adView.adUnitId,
            adRevenuePlacement = adView.responseInfo?.loadedAdapterResponseInfo?.adSourceInstanceName.orEmpty(),
            adFormat = "Banner"
        )
        
        // 上报收益数据（内部已处理初始化和异常）
        AdRevenueManager.reportAdRevenue(adRevenueData)
        AdLogger.d("Banner广告真实收益数据已上报，广告位ID: ${adView.adUnitId}, 收益: ${adValue.valueMicros}微元 ${adValue.currencyCode}")
    }
    
    /**
     * 恢复广告
     */
    fun resumeAd() {
        bannerAdView?.resume()
        AdLogger.d("Banner广告已恢复")
    }
    
    /**
     * 销毁广告
     */
    fun destroyAd() {
        synchronized(adCachePool) {
            adCachePool.forEach { cachedAd -> cachedAd.adView.destroy() }
            adCachePool.clear()
        }
        bannerAdView = null
        bannerView.reset()
        loadTime = 0L
        AdLogger.d("Banner广告已销毁")
    }
    
    /**
     * 清理资源
     */
    fun destroy() {
        destroyAd()
        _loadingState.value = AdResult.Loading
        _adExpiredState.value = false
        AdLogger.d("Banner广告控制器已清理")
    }
} 