package com.ama.core.architecture.base.views

import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.RelativeLayout
import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
import com.ama.core.architecture.R
import com.ama.core.architecture.base.BaseActivity
import com.ama.core.architecture.base.BaseViewModel
import com.ama.core.architecture.interfaces.ViewBindingActivity
import com.ama.core.architecture.interfaces.ViewModelOwner
import com.ama.core.architecture.message.MessageCollector
import com.ama.core.architecture.message.MessageCollectorOwner
import com.ama.core.architecture.message.collector.ToastMessageCollector
import com.ama.core.architecture.stateview.interfaces.DefaultStateViewManager
import com.ama.core.architecture.stateview.util.initLoadStateUiStateCollect
import com.ama.core.designsystem.widget.interfaces.LoadingDialog
import com.ama.core.designsystem.widget.interfaces.StateView
import com.remax.bill.ads.AdResult
import com.remax.bill.ads.ext.AdShowExt
import kotlinx.coroutines.launch



abstract class BaseViewsActivity<Binding : ViewBinding, UiState : Any,
        ViewModel : BaseViewModel<UiState>> :
    BaseActivity(), ViewBindingActivity<Binding, UiState>, ViewModelOwner<UiState, ViewModel>, DefaultStateViewManager, MessageCollectorOwner {
    private lateinit var mFinalRootView: ViewGroup
    private var mAdContainer: ViewGroup? = null
    protected open var mEnableBannerAd = true

    override val binding: Binding by lazy { inflateViewBinding(layoutInflater) }

    // 此处为了性能，没用反射直接获取，而是让调用者自己选择。可在AppViewsActivity覆盖此实现（使用反射），或者每个具体子类（如MainActivity）具体类型实现。
//    override val viewModel: ViewModel by reflectViewModels()

    // StateView相关
    // -stateView只有你调用的时候，才会在第一次添加。
    override val stateView: Lazy<StateView> = lazy { createStateViewImpl() }

    // -LoadingDialog只有你调用的时候，才会在第一次创建。
    override val loadingDialog: Lazy<LoadingDialog> = lazy { createLoadingDialogImpl(this) }

    // -StateView要替换的View，默认为根布局。
    override fun getStateViewReplaceView(): View = binding.root

    // 消息的收集者，默认为Toast，子类可覆写为Snakbar等。
    override val messageCollector: MessageCollector by lazy {
        ToastMessageCollector(
            applicationContext
        )
    }
//    override val messageCollector: MessageCollector by lazy { SnakbarViewMessageCollector(binding.root) }

    // 此处为了性能，没用反射直接获取，而是让调用者自己选择。可在AppViewsActivity覆盖此实现（使用反射），或者每个具体子类（如MainActivity）具体类型实现。
//    override fun inflateViewBinding(inflater: LayoutInflater) = reflectInflateViewBinding(inflater)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initEdgeToEdge()
        readIntent(intent)
        setContentView(getContentView())
        binding.initWindowInsets()
        binding.initViews()
        binding.initListeners()
        binding.initBaseObservers()
        binding.initObservers()

        tryShowBannerAd()
    }

    private fun tryShowBannerAd() {
        if (mEnableBannerAd) {
            mAdContainer?.let {
                lifecycleScope.launch {
                    try {
                        when (AdShowExt.showBannerAd(this@BaseViewsActivity, it)) {
                            is AdResult.Success<*> -> {

                            }

                            is AdResult.Failure -> {

                            }

                            AdResult.Loading -> {
                            }
                        }
                    } catch (e: Exception) {

                    }
                }
            }
        }
    }


    override fun readIntent(intent: Intent) {

    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        readIntent(intent)
    }

    open fun initEdgeToEdge() {
        enableEdgeToEdge()
    }

    override fun Binding.initBaseObservers() {
        // 初始化UiState收集
        lifecycleScope.launch {
            mViewModel.uiState
                .flowWithLifecycle(lifecycle)
                .collect { uiState ->
                    onUiStateCollect(uiState)
                }
        }
        // 初始化Message收集
        messageCollector.initCollect(
            mViewModel.messageController,
            lifecycleScope,
            lifecycle,
        )

        // 初始化LoadStateUiState收集
        initLoadStateUiStateCollect(mViewModel, lifecycleScope, lifecycle)
    }


    protected fun setImmerseRootView(rootView: View) {
        ViewCompat.setOnApplyWindowInsetsListener(rootView) { v, insets ->
            val systemBars = insets.getInsets(
                WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() or WindowInsetsCompat.Type.ime()
            )
            if (mEnableBannerAd) {
                v.setPadding(systemBars.left, systemBars.top, systemBars.right, 0)
                mFinalRootView.run {
                    setPadding(paddingLeft, paddingTop, paddingRight,systemBars.bottom)
                }
            } else {
                v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            }

            insets
        }
    }

    private fun getContentView(): View {
        if (mEnableBannerAd) {
            mFinalRootView = RelativeLayout(this)
            mAdContainer = FrameLayout(this).apply {
                layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.WRAP_CONTENT).apply {
                    addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
                }
                setBackgroundResource(R.color.gray_3)
                id = ViewCompat.generateViewId()
            }
            mFinalRootView.addView(mAdContainer)

            val bindingRootLayoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT).apply {
                addRule(RelativeLayout.ABOVE, mAdContainer!!.id)
            }
            mFinalRootView.addView(binding.root, bindingRootLayoutParams)
        } else {
            return binding.root
        }
        return mFinalRootView
    }


}