package com.gh.gamecenter.home.custom.ui

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Typeface
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.FixLinearLayoutManager
import com.gh.gamecenter.common.view.ScrollEventListener
import com.gh.gamecenter.common.view.TouchSlopRecyclerView
import com.gh.gamecenter.core.utils.AlphaGradientProcess
import com.gh.gamecenter.databinding.HomeSlideCardItemCustomBinding
import com.gh.gamecenter.databinding.HomeSlideWithCardsCustomBinding
import com.gh.gamecenter.entity.HomeSlide
import com.gh.gamecenter.entity.HomeSubSlide
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.view.GameIconView
import com.gh.gamecenter.home.custom.BannerInRecyclerController
import com.gh.gamecenter.home.custom.CommonContentCollectionUseCase
import com.gh.gamecenter.home.custom.adapter.CustomHomeSlideListAdapter
import com.gh.gamecenter.home.custom.model.CustomPageData
import kotlin.math.abs

/**
 * 通用内容合集-轮播banner
 * ui逻辑封装，方便多个地方复用
 */
class CommonContentHomeSlideWithCardsUi(
    private val useCase: CommonContentCollectionUseCase,
    private val lifecycleOwner: LifecycleOwner,
    val binding: HomeSlideWithCardsCustomBinding,
    private val refreshCount: Int,
    private val basicExposureSource: List<ExposureSource> ? = null,
    private val pageLevelString: String,
    private val listener: HomeSLideWithCardsEventListener,
) {
    private var collection: CustomPageData.CommonContentCollection? = null

    private val context: Context
        get() = binding.root.context

    private val layoutManager by lazy {
        FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
    }

    private val snapHelper by lazy {
        PagerSnapHelper()
    }

    private val adapter by lazy {
        CustomHomeSlideListAdapter(
            context,
            snapHelper,
            layoutManager,
            true,
            object : CustomHomeSlideListAdapter.OnEventListener {
                override fun navigateToGameDetailPage(
                    actualPosition: Int,
                    game: GameEntity,
                    text: String,
                    link: LinkEntity?
                ) {
                    listener.navigateToGameDetailPage(actualPosition, game, text, link)
                }

                override fun navigateToLinkPage(link: LinkEntity, text: String, exposureEvent: ExposureEvent?) {
                    listener.navigateToLinkPage(link, text, exposureEvent)
                }
            })
    }

    private val bannerController = BannerInRecyclerController {
        adapter.scrollToNextPage()
    }

    private var mLastX: Int = 0
    private var mLastY: Int = 0
    private var _currentDataPosition = 0

    private var firstSubSlide: HomeSubSlide? = null
    private var secondSubSlide: HomeSubSlide? = null
    private var _slideList: List<HomeSlide>? = null

    init {
        binding.recyclerView.itemAnimator = null
        lifecycleOwner.lifecycle.addObserver(bannerController)
    }

    fun bind(collection: CustomPageData.CommonContentCollection, position: Int) {
        this.collection = collection
        val rootLayoutParams = binding.root.layoutParams as? ViewGroup.MarginLayoutParams
        rootLayoutParams?.let {
            it.bottomMargin = -8f.dip2px()
            binding.root.layoutParams = it
        }
        bindSlide(collection.slides.slide)
        if (collection.slides.subSlide.isNotEmpty()) {
            bindCards(collection, collection.slides.subSlide)
        }
    }

    private fun bindSlide(
        slideList: List<HomeSlide>
    ) {
        if (binding.recyclerView.adapter == null) {
            binding.recyclerView.layoutManager = layoutManager
            binding.recyclerView.adapter = adapter

            snapHelper.attachToRecyclerView(binding.recyclerView)
            binding.recyclerView.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
                override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
                    val x = e.x.toInt()
                    val y = e.y.toInt()

                    when (e.action) {
                        MotionEvent.ACTION_DOWN -> {
                            mLastX = e.x.toInt()
                            mLastY = e.y.toInt()
                            rv.parent.parent.requestDisallowInterceptTouchEvent(true)
                        }

                        MotionEvent.ACTION_UP -> rv.parent.parent.requestDisallowInterceptTouchEvent(
                            false
                        )

                        MotionEvent.ACTION_MOVE -> {
                            val deltaX: Int = x - mLastX
                            val deltaY: Int = y - mLastY
                            val isHorizontalScroll = abs(deltaX) > abs(deltaY)
                            rv.parent.parent.requestDisallowInterceptTouchEvent(isHorizontalScroll)
                        }
                    }

                    val isStop =
                        e.action == MotionEvent.ACTION_DOWN || e.action == MotionEvent.ACTION_MOVE
                    if (isStop) bannerController.pause() else bannerController.start()

                    val touchSlopRecyclerView = binding.recyclerView.parent.parent.parent
                    if (touchSlopRecyclerView is TouchSlopRecyclerView) {
                        touchSlopRecyclerView.touchSlopEnabled = isStop
                    } else throwExceptionInDebug("TouchSlopRecyclerView not found")
                    return false
                }
            })
            binding.recyclerView.addOnScrollListener(ScrollEventListener(binding.recyclerView).apply {
                registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
                    override fun onPageSelected(position: Int) {
                        _currentDataPosition = adapter.getDataPosition(position)
                    }

                    override fun onPageScrollStateChanged(state: Int) {
                        super.onPageScrollStateChanged(state)

                        if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
                            val view = snapHelper.findSnapView(layoutManager)
                            var curPosition = 0
                            if (view != null) {
                                curPosition = adapter.getDataPosition(layoutManager.getPosition(view))
                                _currentDataPosition = curPosition
                            }
                            listener.updateImmersiveColor(
                                adapter.dataList.safelyGetInRelease(curPosition)?.placeholderColor?.hexStringToIntColor()
                                    ?: com.gh.gamecenter.common.R.color.ui_surface.toColor(binding.root.context)
                            )
                        }
                    }

                    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                        super.onPageScrolled(position, positionOffset, positionOffsetPixels)
                        binding.bannerIndicator.onPageScrolled(
                            adapter.getDataPosition(position),
                            positionOffset
                        )

                        val currentPosition = adapter.getDataPosition(position)
                        val nextPosition = adapter.getDataPosition(position + 1)
                        _currentDataPosition = currentPosition

                        val currentColor =
                            adapter.dataList.safelyGetInRelease(currentPosition)?.placeholderColor?.hexStringToIntColor()
                                ?: com.gh.gamecenter.common.R.color.ui_surface.toColor(binding.root.context)
                        val nextColor =
                            adapter.dataList.safelyGetInRelease(nextPosition)?.placeholderColor?.hexStringToIntColor()
                                ?: currentColor

                        val colorInBetween =
                            ColorUtils.blendARGB(currentColor, nextColor, positionOffset)

                        listener.updateImmersiveColor(colorInBetween)
                    }
                })
            })
            adapter.submitList(slideList)
        } else {
            if (_slideList != slideList) {
                adapter.checkResetData(slideList)
            }
        }
        _slideList = slideList

        val currentPosition = adapter.getInitPosition() + _currentDataPosition
        layoutManager.scrollToPosition(currentPosition)

        val dataPosition = adapter.getDataPosition(currentPosition)
        listener.updateImmersiveColor(
            slideList.getOrNull(dataPosition)?.placeholderColor?.hexStringToIntColor()
                ?: com.gh.gamecenter.common.R.color.ui_surface.toColor(binding.root.context)
        )

        binding.bannerIndicator.run {
            pageSize = adapter.getActualSize()
            notifyDataChanged()
        }

        bannerController.start()
    }

    private fun bindCards(
        data: CustomPageData.CommonContentCollection,
        slideList: List<HomeSubSlide>
    ) {
        val firstSubSlidePosition = (useCase.refreshCount * 2) % slideList.size
        val secondSubSlidePosition = (useCase.refreshCount * 2 + 1) % slideList.size
        slideList.getOrNull(firstSubSlidePosition)?.let {
            firstSubSlide = it
            it.sequence = firstSubSlidePosition
            it.repeatCount = (useCase.refreshCount * 2) / slideList.size
            bindCard(data, binding.firstCv, it, 0)
        }
        slideList.getOrNull(secondSubSlidePosition)?.let {
            secondSubSlide = it
            it.sequence = secondSubSlidePosition
            it.repeatCount = (useCase.refreshCount * 2 + 1) / slideList.size
            bindCard(data, binding.secondCv, it, 1)
        }
    }

    @SuppressLint("SetTextI18n")
    private fun bindCard(
        data: CustomPageData.CommonContentCollection,
        homeSlideCardItemBinding: HomeSlideCardItemCustomBinding,
        homeSubSlide: HomeSubSlide,
        position: Int
    ) {
        val cardCv = homeSlideCardItemBinding.root
        val cardContainer = homeSlideCardItemBinding.cardContainer
        val cardIv = homeSlideCardItemBinding.cardIv
        val titleTv = homeSlideCardItemBinding.titleTv
        val descTv = homeSlideCardItemBinding.descTv
        val textContainer = homeSlideCardItemBinding.textContainer
        val countTv = homeSlideCardItemBinding.countTv
        val labelIv = homeSlideCardItemBinding.labelIv
        val gameIconIv1 = homeSlideCardItemBinding.gameIconIv1
        val gameIconIv2 = homeSlideCardItemBinding.gameIconIv2
        val gameIconIv3 = homeSlideCardItemBinding.gameIconIv3
        val gameIconGroup = listOf(gameIconIv1, gameIconIv2, gameIconIv3)

        titleTv.text = homeSubSlide.title
        titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(titleTv.context))
        descTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(descTv.context))

        // 获取发现卡片游戏
        if (homeSubSlide.cardType == "game_explore" && homeSubSlide.cardData.games.isEmpty()) {
            useCase.slideDiscoveryCardGames.observe(lifecycleOwner, object : Observer<List<GameEntity>> {
                override fun onChanged(t: List<GameEntity>?) {
                    val currentSubSlide = if (position == 0) firstSubSlide else secondSubSlide
                    if (t != null && homeSubSlide == currentSubSlide) {
                        bindCard(
                            data,
                            homeSlideCardItemBinding,
                            homeSubSlide.apply { cardData.games = t },
                            position
                        )
                        useCase.slideDiscoveryCardGames.removeObserver(this)
                    }
                }
            })
            useCase.loadSlideDiscoverCardGames(homeSubSlide)
            return
        }

        when (homeSubSlide.cardType) {
            "column",
            "column_test_v2",
            "server",
            "game_explore",
            "game_list_detail" -> {
                titleTv.visibility = View.VISIBLE
                descTv.visibility = View.GONE
                gameIconGroup.forEach { it.isVisible = homeSubSlide.cardData.games.isNotEmpty() }

                if (homeSubSlide.cardData.games.size == 1) {
                    gameIconIv2.visibility = View.GONE
                    gameIconIv3.visibility = View.GONE
                }
                if (homeSubSlide.cardData.games.size == 2) {
                    gameIconIv3.visibility = View.GONE
                }

                fun GameIconView.setGame(index: Int, game: GameEntity) {
                    displayGameIcon(game, true)
                    this.setOnClickListener {
                        com.gh.common.util.NewFlatLogUtils.logRightSideCardClick(
                            homeSubSlide,
                            useCase.refreshCount,
                            "游戏"
                        )
                        listener.navigateToGameDetailPage(
                            index,
                            game,
                            "右侧卡片-游戏",
                            homeSubSlide.toLinkEntity(),
                        )
                    }
                }

                homeSubSlide.cardData.games.take(3).forEachIndexed { index, gameEntity ->
                    when (index) {
                        0 -> gameIconIv1.setGame(index, gameEntity)

                        1 -> gameIconIv2.setGame(index, gameEntity)

                        2 -> gameIconIv3.setGame(index, gameEntity)
                    }
                }

                for ((index, game) in homeSubSlide.cardData.games.take(3).withIndex()) {
                    game.pageLevelString = pageLevelString
                    game.exposureEvent = ExposureEvent.createEventWithSourceConcat(
                        gameEntity = game.apply {
                            sequence = index
                            outerSequence = refreshCount
                        },
                        basicSource = basicExposureSource ?: arrayListOf(),
                        source = listOf(
                            ExposureSource(
                                "通用内容合集",
                                "${data.name}+${data.layoutChinese}+${data.id}"
                            ),
                            ExposureSource("右侧卡片", homeSubSlide.id)
                        )
                    )
                }

                cardCv.setExposureEventList(
                    homeSubSlide.cardData.games.mapNotNull { gameEntity ->
                        gameEntity.exposureEvent
                    }
                )

                countTv.isVisible = homeSubSlide.cardData.gameTotal.game > 3
                countTv.typeface = Typeface.createFromAsset(countTv.context.assets, Constants.DIN_FONT_PATH)
                countTv.text = "+${homeSubSlide.cardData.gameTotal.game - 3}"
                labelIv.isVisible = homeSubSlide.cardData.stamp.isNotEmpty()
                labelIv.setImageDrawable(
                    when (homeSubSlide.cardData.stamp) {
                        "official" -> R.drawable.label_official.toDrawable(labelIv.context)
                        "special_choice" -> R.drawable.label_premium.toDrawable(labelIv.context)
                        else -> null
                    }
                )

                homeSlideCardItemBinding.cardIv.visibility = View.VISIBLE
                // 防止重复加载图片导致闪烁
                if (homeSubSlide.image != cardIv.getTag(R.string.tag_img_url_id)) {
                    ImageUtils.display(cardIv, homeSubSlide.image, true, AlphaGradientProcess())
                    cardIv.setTag(R.string.tag_img_url_id, homeSubSlide.image)
                }
                ConstraintSet().apply {
                    clone(cardContainer)
                    clear(textContainer.id, ConstraintSet.TOP)
                    clear(textContainer.id, ConstraintSet.BOTTOM)
                    connect(
                        textContainer.id,
                        ConstraintSet.TOP,
                        ConstraintSet.PARENT_ID,
                        ConstraintSet.TOP,
                        8F.dip2px()
                    )
                    if (homeSubSlide.cardData.stamp.isEmpty()) {
                        clear(countTv.id, ConstraintSet.START)
                        connect(countTv.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 10F.dip2px())
                    } else {
                        clear(countTv.id, ConstraintSet.END)
                        connect(countTv.id, ConstraintSet.START, gameIconIv3.id, ConstraintSet.END, 4F.dip2px())
                    }
                }.applyTo(cardContainer)
            }

            "column_collection", "common_collection" -> {
                titleTv.visibility = View.VISIBLE
                descTv.visibility = View.VISIBLE
                countTv.visibility = View.GONE
                labelIv.visibility = View.GONE

                homeSlideCardItemBinding.cardIv.visibility = View.VISIBLE
                gameIconGroup.forEach { it.visibility = View.GONE }
                descTv.text = homeSubSlide.cardDesc
                // 防止重复加载图片导致闪烁
                if (homeSubSlide.image != cardIv.getTag(R.string.tag_img_url_id)) {
                    ImageUtils.display(cardIv, homeSubSlide.image, true, AlphaGradientProcess())
                    cardIv.setTag(R.string.tag_img_url_id, homeSubSlide.image)
                }
                ConstraintSet().apply {
                    clone(cardContainer)
                    clear(textContainer.id, ConstraintSet.TOP)
                    clear(textContainer.id, ConstraintSet.BOTTOM)
                    connect(textContainer.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
                    connect(textContainer.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
                }.applyTo(cardContainer)
            }
        }

        cardCv.setOnClickListener {
            com.gh.common.util.NewFlatLogUtils.logRightSideCardClick(homeSubSlide, useCase.refreshCount, "卡片")
            listener.navigateToLinkPageInSubSlide(
                GameEntity(sequence = position, outerSequence = useCase.refreshCount),
                homeSubSlide,
                "右侧卡片"
            )
        }
    }

    fun onViewAttach(parent: RecyclerView?) {
        bannerController.onViewAttachedToWindow(parent)
    }

    fun onViewDetach(parent: RecyclerView?) {
        bannerController.onViewDetachedFromWindow(parent)
    }

    fun updateWhenTopVisibleItemCountChanged(isFirst: Boolean) {
        val bannerTopMargin = if (isFirst) {
            8f.dip2px()
        } else {
            16f.dip2px()
        }
        val layoutParams = binding.bannerCv.layoutParams as? ViewGroup.MarginLayoutParams
        layoutParams?.let {
            it.topMargin = bannerTopMargin
            it.bottomMargin = if (isFirst) 16f.dip2px() else 24f.dip2px()
            binding.bannerCv.layoutParams = it
        }
        val subSlide = collection?.slides?.subSlide ?: return
        if (subSlide.isNotEmpty()) {
            val firstSubSlidePosition = (useCase.refreshCount * 2) % subSlide.size
            val secondSubSlidePosition = (useCase.refreshCount * 2 + 1) % subSlide.size

            fun HomeSlideCardItemCustomBinding.updateCard(cardType: String) {
                if (cardType == "column_collection"
                    || cardType == "common_collection"
                ) {
                    val visibility = if (isFirst) View.VISIBLE else View.GONE
                    cardMask.visibility = visibility
                    cardGradientMask.visibility = visibility
                }
            }
            subSlide.getOrNull(firstSubSlidePosition)?.cardType?.let(binding.firstCv::updateCard)
            subSlide.getOrNull(secondSubSlidePosition)?.cardType?.let(binding.secondCv::updateCard)
        }
        val slideList = collection?.slides?.slide ?: return
        val currentPosition = if (_currentDataPosition == -1) {
            adapter.getInitPosition()
        } else {
            _currentDataPosition
        }
        val dataPosition = adapter.getDataPosition(currentPosition)
        listener.updateImmersiveColor(
            slideList.getOrNull(dataPosition)?.placeholderColor?.hexStringToIntColor()
                ?: com.gh.gamecenter.common.R.color.ui_surface.toColor(binding.root.context)
        )
    }

    interface HomeSLideWithCardsEventListener {
        fun updateImmersiveColor(color: Int)

        fun navigateToGameDetailPage(childPosition: Int, gameEntity: GameEntity, text: String, link: LinkEntity?)

        fun navigateToLinkPageInSubSlide(game: GameEntity, homeSubSlide: HomeSubSlide, text: String)

        fun navigateToLinkPage(link: LinkEntity, text: String, exposureEvent: ExposureEvent?)
    }
}