package com.gh.gamecenter.subject.tab

import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.graphics.Typeface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.CheckedTextView
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.DialogHelper.Config
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.FragmentSubjectTabBinding
import com.gh.gamecenter.databinding.LayoutColumnCollectionSettingBinding
import com.gh.gamecenter.databinding.TabItemMainBinding
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.gh.gamecenter.livedata.EventObserver
import com.gh.gamecenter.subject.SubjectFragment
import com.gh.gamecenter.subject.SubjectListFragment
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import org.json.JSONException
import org.json.JSONObject
import java.util.*
import kotlin.math.abs
import kotlin.math.roundToInt

class SubjectTabFragment : ToolbarFragment() {

    private val binding by lazy { FragmentSubjectTabBinding.inflate(layoutInflater) }
    private var settingBinding: LayoutColumnCollectionSettingBinding? = null
    private var isSubject = false
    private var isCustomEnabled = false
    private var tabStyle = TabStyle.SUBJECT_NORMAL
    private var tabBindingList = arrayListOf<TabItemMainBinding>()
    private var isSettingAnimating = false
    private var columnCollectionTabViewModel: ColumnCollectionTabViewModel? = null
    private val fragmentTag by lazy { "android:switcher:${binding.subjectViewpager.id}:" }
    private var collectionId = ""
    private var collectionName = ""
    private var collectionStyle = ""
    private val followAdapter by lazy { CustomTabFollowAdapter(columnCollectionTabViewModel) }
    private val moreAdapter by lazy { CustomTabMoreAdapter(columnCollectionTabViewModel) }
    private val showOrHideMore: (Boolean) -> Unit = { isShow ->
        settingBinding?.run {
            if (isShow == moreContainer.isVisible) return@run

            val startHeight = if (isShow) 0 else moreContainer.height
            val endHeight = if (isShow) {
                moreContainer.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
                moreContainer.measuredHeight
            } else 0
            ValueAnimator.ofInt(startHeight, endHeight).apply {
                duration = ANIMATOR_DURATION
                interpolator = AccelerateDecelerateInterpolator()
                doOnStart {
                    if (isShow) {
                        moreContainer.updateLayoutParams<MarginLayoutParams> { height = 0 }
                        moreContainer.isVisible = true
                    } else {
                        moreContainer.isInvisible = true
                    }
                }
                doOnEnd {
                    if (isShow) {
                        moreContainer.updateLayoutParams<MarginLayoutParams> { height = MarginLayoutParams.WRAP_CONTENT }
                    } else {
                        moreContainer.isVisible = false
                    }
                }
                addUpdateListener { animation ->
                    moreContainer.updateLayoutParams<MarginLayoutParams> { height = animation.animatedValue as Int }
                }
            }.start()
        }
    }
    private val itemTouchHelper by lazy {
        ItemTouchHelper(object : ItemTouchHelper.Callback() {
            override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
                return makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.START or ItemTouchHelper.END, 0)
            }

            override fun onMove(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder,
                target: RecyclerView.ViewHolder
            ): Boolean {
                val from = viewHolder.bindingAdapterPosition
                val to = target.bindingAdapterPosition
                val newList = followAdapter.currentList.toMutableList()
                Collections.swap(newList, from, to)
                followAdapter.submitList(newList)
                return true
            }

            override fun isLongPressDragEnabled(): Boolean = true

            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) = Unit
        })
    }

    override fun getLayoutId() = 0
    override fun getInflatedLayout() = binding.root

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val subjectList = arguments?.getParcelableArrayList<SubjectData>(EntranceConsts.KEY_DATA) ?: arrayListOf()
        isSubject = subjectList.isEmpty()
        tabStyle = when {
            mIsFromMainWrapper && !isSubject -> TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER
            mIsFromTabWrapper && !isSubject -> TabStyle.COLUMN_COLLECTION_TAB_WRAPPER
            isSubject -> TabStyle.SUBJECT_NORMAL
            else -> TabStyle.COLUMN_COLLECTION_NORMAL
        }
        val fragments = ArrayList<Fragment>()
        val tagList: ArrayList<String>
        if (isSubject) {
            // 专题详情
            val subjectData = arguments?.getParcelable<SubjectData>(EntranceConsts.KEY_SUBJECT_DATA)
                ?: return
            val settingsEntity =
                arguments?.getParcelable<SubjectSettingEntity>(EntranceConsts.KEY_SUBJECT_SETTING_DATA)
                    ?: return
            tagList = settingsEntity.typeEntity.content as ArrayList<String>
            if (tagList.size > 1) {
                binding.subjectTabContainer.visibility = View.VISIBLE
            }
            tagList.forEachIndexed { index, tag ->
                val element = childFragmentManager.findFragmentByTag("${fragmentTag}$index")
                    ?: SubjectListFragment()
                val bundle = arguments?.clone() as Bundle?
                val copyData = subjectData.deepCopy()
                copyData.filter = if (tag == "全部") {
                    UrlFilterUtils.getFilterQuery("tags", tag, "type", "全部")
                } else {
                    copyData.tag = tag
                    UrlFilterUtils.getFilterQuery("tags", tag)
                }
                bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, copyData)
                bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_SETTING_DATA, settingsEntity)
                element.arguments = bundle
                fragments.add(element)
            }
            if (binding.subjectTabContainer.isVisible) {
                binding.subjectTabIndicator.setupWithTabLayout(binding.subjectTab)
                binding.subjectTabIndicator.setupWithViewPager(binding.subjectViewpager)
            }

            val adapter = object : FragmentStatePagerAdapter(childFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
                override fun getItem(position: Int): Fragment {
                    return fragments[position]
                }

                override fun getCount(): Int {
                    return fragments.size
                }

                override fun getPageTitle(position: Int): CharSequence {
                    return tagList[position]
                }

                override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
//                super.destroyItem(container, position, `object`)
                }
            }
            binding.subjectViewpager.adapter = adapter
            binding.subjectTab.setupWithViewPager(binding.subjectViewpager)
            initTabLayout()
        } else {
            // 专题合集详情
            isCustomEnabled = arguments?.getBoolean(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM) ?: false
            val customSize = (arguments?.getInt(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM_SIZE)
                ?: ColumnCollectionTabViewModel.CUSTOM_MAX_TAB).coerceAtMost(ColumnCollectionTabViewModel.CUSTOM_MAX_TAB)
            collectionId = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_ID, "") ?: ""
            collectionName = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_NAME, "") ?: ""
            collectionStyle = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_STYLE, "") ?: ""
            binding.optionIv.isVisible = isCustomEnabled
            binding.maskView.isVisible = isCustomEnabled
            binding.optionIv.setOnClickListener {
                showSettingView()
                SensorsBridge.trackColumnCollectionClick(
                    location = "合集详情",
                    columnCollectionName = collectionName,
                    columnCollectionId = collectionId,
                    text = "自定义设置",
                    columnCollectionPattern = CustomPageItem.collectionTypeToComponentName[collectionStyle]
                        ?: collectionStyle
                )
            }
            binding.subjectTabContainer.visibility = View.VISIBLE
            if (isCustomEnabled) {
                val columnCollectionId = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_ID) ?: ""
                columnCollectionTabViewModel = viewModelProvider(ColumnCollectionTabViewModel.Factory(columnCollectionId, customSize, subjectList))
                observerData()
                if (SPUtils.getBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_SETTING, true)) {
                    mBaseHandler.post {
                        showSettingView()
                    }
                    SPUtils.setBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_SETTING, false)
                }
            } else {
                initColumnCollectionViewPager(subjectList)
            }
        }
    }

    private fun observerData() {
        columnCollectionTabViewModel?.tabListLiveData?.observe(viewLifecycleOwner) {
            binding.subjectTab.clearOnTabSelectedListeners()
            initColumnCollectionViewPager(it)
        }
        columnCollectionTabViewModel?.followListLiveData?.observe(viewLifecycleOwner) {
            followAdapter.submitList(it)
        }
        columnCollectionTabViewModel?.moreListLiveData?.observe(viewLifecycleOwner) {
            moreAdapter.submitList(it) {
                showOrHideMore.invoke(it.isNotEmpty())
            }
        }
        columnCollectionTabViewModel?.addFollowLiveData?.observe(viewLifecycleOwner, EventObserver {
            val newFollowList = followAdapter.currentList.toMutableList()
            if (newFollowList.size < ColumnCollectionTabViewModel.CUSTOM_MAX_TAB) {
                val newMoreList = moreAdapter.currentList.toMutableList().apply { remove(it) }
                followAdapter.submitList(newFollowList.apply { add(it) })
                moreAdapter.submitList(newMoreList) {
                    showOrHideMore.invoke(newMoreList.isNotEmpty())
                }
            } else {
                toast("最多可以添加15个关注内容哦~")
            }
        })
        columnCollectionTabViewModel?.addMoreLiveData?.observe(viewLifecycleOwner, EventObserver {
            if (followAdapter.currentList.size == 1) {
                toast("至少添加1个内容哦~")
                return@EventObserver
            }

            followAdapter.submitList(followAdapter.currentList.toMutableList().apply { remove(it) })
            val newMoreList = moreAdapter.currentList.toMutableList().apply { add(it) }
            moreAdapter.submitList(newMoreList) {
                showOrHideMore.invoke(newMoreList.isNotEmpty())
            }
        })
    }

    private fun initColumnCollectionViewPager(subjectList: List<SubjectData>) {
        val fragments = arrayListOf<Fragment>()
        val tagList = arrayListOf<String>()
        subjectList.filterIndexed { index, subject ->
            val element = childFragmentManager.findFragmentByTag("${fragmentTag}$index")
                ?: SubjectFragment()
            val bundle = arguments?.clone() as Bundle?
            bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, subject)
            bundle?.putParcelableArrayList(EntranceConsts.KEY_DATA, null)
            bundle?.putBoolean(EntranceConsts.KEY_IS_FROM_MAIN_WRAPPER, false)
            bundle?.putBoolean(EntranceConsts.KEY_IS_FROM_TAB_WRAPPER, false)
            bundle?.putBoolean(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM, false)
            if (isCustomEnabled) {
                bundle?.putInt(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM_POSITION, index)
            }
            element.arguments = bundle
            fragments.add(element)

            tagList.add(subject.subjectName ?: "")
        }

        binding.subjectViewpager.post {
            binding.subjectViewpager.offscreenPageLimit = fragments.size
            var position = arguments?.getInt(EntranceConsts.KEY_POSITION, 0) ?: 0
            val columnName = arguments?.getString(EntranceConsts.KEY_COLUMNNAME) ?: ""
            if (columnName.isNotEmpty()) {
                position = subjectList.indexOfFirst { it.subjectName == columnName }
            }
            if (position < subjectList.size) {
                binding.subjectViewpager.setCurrentItem(position, false)
            }
        }
        val categoryId = requireArguments().getString(EntranceConsts.KEY_COLUMN_COLLECTION_ID, "")
        val categoryName = requireArguments().getString(EntranceConsts.KEY_COLUMN_COLLECTION_NAME, "")

        binding.subjectViewpager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
            override fun onPageSelected(position: Int) {
                subjectList.getOrNull(position)?.let {
                    MtaHelper.onEvent("游戏专题合集", "详情Tab", it.subjectName)
                    NewLogUtils.logColumnCategoryDetailContentClick(
                        it.subjectName ?: "", it.subjectId ?: "", categoryName, categoryId
                    )

                    if (categoryName?.contains("排行榜") == true) {
                        val trackEvent = JSONObject()
                        try {
                            trackEvent.put("list_name", it.subjectName)
                            trackEvent.put("position", position)
                        } catch (e: JSONException) {
                            e.printStackTrace()
                        }
                        SensorsBridge.trackEvent("GameListPageSelected", trackEvent)
                    }
                }
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels)
                if (mIsFromMainWrapper) {
                    // 这里的 selectedPosition 指的是应该被高亮显示的 position
                    val selectedPosition = try {
                        (position + positionOffset).roundToInt()
                    } catch (e: IllegalArgumentException) {
                        // roundToInt() 方法有时候会报 Cannot round NaN value. 错误 positionOffset 的值为 NAN
                        // https://sentry.shanqu.cc/organizations/lightgame/issues/301377/?project=22
                        position
                    }
                    val positionOffsetOnRealSelectedPosition = if (positionOffset >= 0.5) {
                        positionOffset - 1
                    } else {
                        positionOffset
                    }
                    updateTabStyle(selectedPosition, positionOffsetOnRealSelectedPosition)
                }
            }
        })

        val adapter = object : FragmentStatePagerAdapter(childFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
            override fun getItem(position: Int): Fragment {
                return fragments[position]
            }

            override fun getCount(): Int {
                return fragments.size
            }

            override fun getPageTitle(position: Int): CharSequence {
                return tagList[position]
            }

            override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
//                super.destroyItem(container, position, `object`)
            }
        }
        binding.subjectViewpager.adapter = adapter
        binding.subjectTab.setupWithViewPager(binding.subjectViewpager)
        binding.subjectTabIndicator.setupWithTabLayout(binding.subjectTab)
        binding.subjectTabIndicator.setupWithViewPager(binding.subjectViewpager)
        initTabLayout()
    }

    private fun initTabLayout() {
        if (isCustomEnabled && SPUtils.getBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_GUIDE, true)) {
            binding.subjectTab.addOnTabSelectedListener(object : OnTabSelectedListener {
                override fun onTabSelected(tab: TabLayout.Tab?) {
                    showSettingGuideIfNeeded(this)
                }
                override fun onTabUnselected(tab: TabLayout.Tab?) {}
                override fun onTabReselected(tab: TabLayout.Tab?) {
                    showSettingGuideIfNeeded(this)
                }
            })
        }

        if (tabStyle == TabStyle.COLUMN_COLLECTION_NORMAL) {
            binding.subjectTabIndicator.run {
                setIndicatorWidth(12)
                updateLayoutParams<ConstraintLayout.LayoutParams> {
                    bottomMargin = 10F.dip2px()
                }
            }
            for (i in 0 until binding.subjectTab.tabCount) {
                binding.subjectTab.getTabAt(i)?.view?.run {
                    background = null
                    if (i == 0) {
                        updateLayoutParams<MarginLayoutParams> { leftMargin = 4F.dip2px() }
                    }
                }
            }
        } else {
            tabBindingList.clear()

            val tabCount = binding.subjectTab.tabCount
            for (i in 0 until tabCount) {
                val tab = binding.subjectTab.getTabAt(i) ?: continue
                val tabTitle = if (tab.text != null) tab.text.toString() else ""

                tab.view.background = null
                tab.customView = provideTabView(tabTitle)
                if (tabStyle == TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER) {
                    tab.view.setPadding(0, 0, 0, 0)
                    if (i == 0) {
                        tab.view.updateLayoutParams {
                            this as LinearLayout.LayoutParams
                            setMargins(10F.dip2px(), 0, 0, 0)
                        }
                    } else if (i == tabCount - 1) {
                        tab.view.updateLayoutParams {
                            this as LinearLayout.LayoutParams
                            setMargins(0, 0, 10F.dip2px(), 0)
                        }
                    }
                } else {
                    val leftPadding = if (i == 0) 16F.dip2px() else 8F.dip2px()
                    val rightPadding = if (i == binding.subjectTab.tabCount - 1) 16F.dip2px() else 0
                    tab.view.setPadding(leftPadding, 0, rightPadding, 0)
                    tab.view.findViewById<View>(R.id.tab_title)?.let {
                        it.post {
                            tab.view.updateLayoutParams<ViewGroup.LayoutParams> { width = leftPadding + rightPadding + it.width }
                        }
                    }
                }
            }

            binding.subjectTabIndicator.isVisible = mIsFromMainWrapper
            if (tabStyle == TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER) {
                binding.subjectTabIndicator.run {
                    setIndicatorWidth(18)
                    updateIndicatorDrawable(R.drawable.ic_commodity_selected.toDrawable(requireContext()))
                    updateLayoutParams<ConstraintLayout.LayoutParams> {
                        height = 8F.dip2px()
                        bottomMargin = 8F.dip2px()
                    }
                }
                binding.settingGuideIv.updateLayoutParams<ConstraintLayout.LayoutParams> { topMargin = 40F.dip2px() }
                binding.subjectTabContainer.updateLayoutParams<ConstraintLayout.LayoutParams> { height = 56F.dip2px() }
                binding.subjectTab.updateLayoutParams<ConstraintLayout.LayoutParams> {
                    setMargins(0, 8F.dip2px(), 8F.dip2px(), 8F.dip2px())
                }
            } else {
                binding.subjectTab.addOnTabSelectedListener(object : OnTabSelectedListener {
                    override fun onTabReselected(tab: TabLayout.Tab?) {}

                    override fun onTabUnselected(tab: TabLayout.Tab?) {
                        tab?.customView?.findViewById<CheckedTextView>(R.id.tab_title)?.isChecked = false
                    }

                    override fun onTabSelected(tab: TabLayout.Tab?) {
                        tab?.customView?.findViewById<CheckedTextView>(R.id.tab_title)?.isChecked = true
                    }
                })
            }
        }
    }

    private fun provideTabView(title: String): View {
        if (tabStyle == TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER) {
            val tabBinding = TabItemMainBinding.inflate(LayoutInflater.from(requireContext()))
            tabBinding.titleTv.run {
                visibility = View.VISIBLE
                text = title
                textSize = 16F
                setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
            }
            tabBinding.invisibleTitleTv.run {
                visibility = View.INVISIBLE
                text = title
                textSize = 16F
            }
            tabBindingList.add(tabBinding)
            return tabBinding.root
        } else {
            val view = LayoutInflater.from(requireContext()).inflate(R.layout.tab_item_subject_tab, null)
            val tabTitle = view.findViewById<View>(R.id.tab_title)
            if (tabTitle is CheckedTextView) {
                tabTitle.text = title
            }
            view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 32F.dip2px())
            return view
        }
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        when (tabStyle) {
            TabStyle.COLUMN_COLLECTION_NORMAL -> {
                binding.subjectTabIndicator.updateIndicatorColor(com.gh.gamecenter.common.R.color.primary_theme)
                binding.subjectTab.setTabTextColors(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()), com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
            }
            TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER -> updateTabStyle(binding.subjectViewpager.currentItem, 0F)
            TabStyle.COLUMN_COLLECTION_TAB_WRAPPER,
            TabStyle.SUBJECT_NORMAL -> {
                for (i in 0 until binding.subjectTab.tabCount) {
                    val tab = binding.subjectTab.getTabAt(i) ?: continue
                    tab.customView?.findViewById<CheckedTextView>(R.id.tab_title)?.run {
                        background = R.drawable.subject_tab_background_selector.toDrawable(context)
                        setTextColor(ContextCompat.getColorStateList(context, com.gh.gamecenter.common.R.color.text_tabbar_style))
                    }
                }
            }
        }

        settingBinding?.run {
            saveTv.background = com.gh.gamecenter.common.R.drawable.button_blue_oval.toDrawable(requireContext())
            cancelTv.background = com.gh.gamecenter.feature.R.drawable.button_round_gray_light.toDrawable(requireContext())
            cancelTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
            followAdapter.notifyItemRangeChanged(0, followAdapter.itemCount)
            moreAdapter.notifyItemRangeChanged(0, moreAdapter.itemCount)
        }
    }

    private fun updateTabStyle(selectedPosition: Int, positionOffset: Float) {
        if (tabBindingList.isEmpty()) return

        val currentTabDefaultColor = com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext())
        val currentTabSelectedColor = com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext())

        val prePosition = selectedPosition - 1
        val nextPosition = selectedPosition + 1

        // positionOffset 小于零，表示 indicator 当前位置处于选中的 tab 的左边
        val indicatorOnLeft = positionOffset < 0F

        val selectedTabBinding = tabBindingList.safelyGetInRelease(selectedPosition) ?: return

        // 前一个 tab、当前选中的 tab、后一个 tab 的显示比例
        val preScaleRatio = 1 + abs(positionOffset) / 4
        val selectedScaleRatio = 1 + (1 - abs(positionOffset)) / 4
        val nextScaleRatio = 1 + positionOffset / 4

        // 处理前一个 tab
        if (prePosition != -1) {
            tabBindingList[prePosition].run {
                if (indicatorOnLeft) {
                    titleTv.scaleX = preScaleRatio
                    titleTv.scaleY = preScaleRatio
                    titleTv.setTextColor(
                        ColorUtils.blendARGB(
                            currentTabDefaultColor,
                            currentTabSelectedColor,
                            abs(positionOffset)
                        )
                    )
                } else {
                    titleTv.setTextColor(currentTabDefaultColor)
                }
            }
        }

        // 更新当前选中的 tab
        selectedTabBinding.run {
            titleTv.scaleX = selectedScaleRatio
            titleTv.scaleY = selectedScaleRatio
            titleTv.setTextColor(
                ColorUtils.blendARGB(
                    currentTabDefaultColor,
                    currentTabSelectedColor,
                    1 - abs(positionOffset)
                )
            )
        }

        // 处理后一个 tab
        if (nextPosition < tabBindingList.size) {
            tabBindingList[nextPosition].run {
                if (!indicatorOnLeft) {
                    titleTv.scaleX = nextScaleRatio
                    titleTv.scaleY = nextScaleRatio
                    titleTv.setTextColor(
                        ColorUtils.blendARGB(
                            currentTabDefaultColor,
                            currentTabSelectedColor,
                            positionOffset
                        )
                    )
                } else {
                    titleTv.setTextColor(currentTabDefaultColor)
                }
            }
        }

        // 多 tab 切换的时候可能会出现某些 tab 的文字没有回归到原始大小的问题的问题 (positionOffset 不保证连续)
        for ((index, tabBinding) in tabBindingList.withIndex()) {
            if (index != prePosition && index != selectedPosition && index != nextPosition) {
                if (tabBinding.titleTv.scaleX != 1F) {
                    tabBinding.titleTv.scaleX = 1F
                    tabBinding.titleTv.scaleY = 1F
                }
                tabBinding.titleTv.setTextColor(currentTabDefaultColor)
                if (tabBinding.titleIv.scaleX != 1F) {
                    tabBinding.titleIv.scaleX = 1F
                    tabBinding.titleIv.scaleY = 1F
                }
            }

            if (index == selectedPosition) {
                if (positionOffset == 0F) {
                    tabBinding.titleTv.setTextColor(currentTabSelectedColor)
                }

                tabBinding.titleTv.setTypeface(tabBinding.titleTv.typeface, Typeface.BOLD)
            } else {
                if (positionOffset == 0F) {
                    tabBinding.titleTv.setTextColor(currentTabDefaultColor)
                }

                tabBinding.titleTv.setTypeface(null, Typeface.NORMAL)
            }
        }
    }

    private fun showSettingGuideIfNeeded(listener: OnTabSelectedListener) {
        if (isCustomEnabled && SPUtils.getBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_GUIDE, true)) {
            binding.skipView.setOnClickListener {
                dismissSettingGuide()
                SensorsBridge.trackColumnCollectionClick(
                    location = "合集详情",
                    columnCollectionName = collectionName,
                    columnCollectionId = collectionId,
                    text = "新手引导-取消",
                    columnCollectionPattern = CustomPageItem.collectionTypeToComponentName[collectionStyle]
                        ?: collectionStyle
                )
            }
            binding.settingClickView.setOnClickListener {
                dismissSettingGuide()
                showSettingView()
                SensorsBridge.trackColumnCollectionClick(
                    location = "合集详情",
                    columnCollectionName = collectionName,
                    columnCollectionId = collectionId,
                    text = "新手引导-立即设置",
                    columnCollectionPattern = CustomPageItem.collectionTypeToComponentName[collectionStyle]
                        ?: collectionStyle
                )
            }
            binding.settingGuideContainer.setOnClickListener {
                dismissSettingGuide()
                SensorsBridge.trackColumnCollectionClick(
                    location = "合集详情",
                    columnCollectionName = collectionName,
                    columnCollectionId = collectionId,
                    text = "新手引导-关闭引导",
                    columnCollectionPattern = CustomPageItem.collectionTypeToComponentName[collectionStyle]
                        ?: collectionStyle
                )
            }
            mBaseHandler.post {
                binding.settingGuideContainer.isVisible = true
            }
            SPUtils.setBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_GUIDE, false)
            binding.subjectTab.removeOnTabSelectedListener(listener)
        }
    }

    private fun dismissSettingGuide() {
        binding.settingGuideIv.animate()?.alpha(0F)?.setDuration(200L)?.doOnEnd {
            binding.settingGuideContainer.isVisible = false
        }?.start()
    }

    private fun showSettingView() {
        if (isSettingAnimating) return

        binding.background.setOnClickListener {
            showDismissSettingDialogIfNeeded()
        }

        settingBinding = LayoutColumnCollectionSettingBinding.inflate(layoutInflater, null, false).apply {
            followRv.isNestedScrollingEnabled = false
            moreRv.isNestedScrollingEnabled = false
            columnCollectionTabViewModel?.followListLiveData?.value?.let {
                followAdapter.submitList(it) {
                    followRv.adapter = followAdapter
                }
            } ?: run {
                followRv.adapter = followAdapter
            }
            columnCollectionTabViewModel?.moreListLiveData?.value?.let {
                moreAdapter.submitList(it) {
                    moreRv.adapter = moreAdapter
                }
            } ?: run {
                moreRv.adapter = moreAdapter
            }
            followRv.layoutManager = FlexboxLayoutManager(requireContext()).apply { justifyContent = JustifyContent.FLEX_START }
            moreRv.layoutManager = FlexboxLayoutManager(requireContext()).apply { justifyContent = JustifyContent.FLEX_START }
            itemTouchHelper.attachToRecyclerView(followRv)
            moreContainer.isVisible = !columnCollectionTabViewModel?.moreListLiveData?.value.isNullOrEmpty()
            saveTv.setOnClickListener {
                dismissSettingView {
                    saveCustomTab()
                }
            }
            cancelTv.setOnClickListener {
                dismissSettingView()
            }
            root.setOnClickListener {}
        }

        binding.settingContainer.addView(
            settingBinding!!.root,
            FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
        )
        binding.settingContainer.post {
            val height = binding.settingContainer.height
            binding.background.visibility = View.VISIBLE
            AnimatorSet().apply {
                val translateAnimator = ValueAnimator.ofFloat(0F, height.toFloat()).apply {
                    addUpdateListener { va -> binding.settingContainer.translationY = (va.animatedValue as Float) }
                }
                val alphaAnimator = ValueAnimator.ofFloat(0F, 0.2F).apply {
                    addUpdateListener { va -> binding.background.alpha = (va.animatedValue as Float) }
                }
                playTogether(translateAnimator, alphaAnimator)
                duration = ANIMATOR_DURATION
                doOnStart {
                    isSettingAnimating = true
                }
                doOnEnd {
                    ConstraintSet().apply {
                        clone(binding.root)
                        clear(binding.settingContainer.id, ConstraintSet.BOTTOM)
                        connect(binding.settingContainer.id, ConstraintSet.TOP, binding.subjectTabContainer.id, ConstraintSet.TOP)
                    }.applyTo(binding.root)
                    binding.settingContainer.translationY = 0F
                    isSettingAnimating = false
                }
            }.start()
        }
    }

    private fun saveCustomTab() {
        if (followAdapter.currentList.isEmpty()) {
            toast("至少添加1个内容哦~")
            return
        }

        SensorsBridge.trackEvent("ColumnCollectionCustomSetting",
            "column_collection_name", collectionName,
            "column_collection_id", collectionId,
            "original_text", columnCollectionTabViewModel?.followListLiveData?.value?.joinToString("、") { it.subjectName ?: "" } ?: "",
            "save_text", followAdapter.currentList.joinToString("、") { it.subjectName ?: "" },
        )
        columnCollectionTabViewModel?.saveCustomTab(followAdapter.currentList)
    }

    private fun showDismissSettingDialogIfNeeded() {
        if (followAdapter.currentList == columnCollectionTabViewModel?.followListLiveData?.value) {
            dismissSettingView()
        } else {
            DialogHelper.showDialog(
                requireContext(),
                title = "提示",
                content = "是否保存当前自定义设置",
                confirmText = "保存设置",
                cancelText = "退出",
                confirmClickCallback = {
                    dismissSettingView {
                        saveCustomTab()
                    }
                },
                cancelClickCallback = {
                    dismissSettingView()
                },
                extraConfig = Config(centerTitle = true, centerContent = true)
            )
        }
    }

    private fun dismissSettingView(doOnEnd: (() -> Unit)? = null) {
        if (settingBinding == null || isSettingAnimating) return

        val height = binding.settingContainer.height
        AnimatorSet().apply {
            val translateAnimator = ValueAnimator.ofFloat(0F, -height.toFloat()).apply {
                addUpdateListener { va -> binding.settingContainer.translationY = (va.animatedValue as Float) }
            }
            val alphaAnimator = ValueAnimator.ofFloat(0.2F, 0F).apply {
                addUpdateListener { va -> binding.background.alpha = (va.animatedValue as Float) }
            }
            playTogether(translateAnimator, alphaAnimator)
            duration = ANIMATOR_DURATION
            doOnStart {
                isSettingAnimating = true
            }
            doOnEnd {
                binding.background.visibility = View.GONE
                binding.settingContainer.removeAllViews()
                binding.settingContainer.translationY = 0F
                ConstraintSet().apply {
                    clone(binding.root)
                    clear(binding.settingContainer.id, ConstraintSet.TOP)
                    connect(binding.settingContainer.id, ConstraintSet.BOTTOM, binding.subjectTabContainer.id, ConstraintSet.TOP)
                }.applyTo(binding.root)
                settingBinding = null
                isSettingAnimating = false
                doOnEnd?.invoke()
            }
        }.start()
    }

    override fun onBackPressed(): Boolean {
        if (!isAdded) return super.onBackPressed()

        if (binding.settingGuideContainer.isVisible) {
            binding.settingGuideContainer.performClick()
            return true
        }
        if (settingBinding != null) {
            showDismissSettingDialogIfNeeded()
            return true
        }
        return super.onBackPressed()
    }

    enum class TabStyle {
        /**
         * 专题详情样式
         */
        SUBJECT_NORMAL,

        /**
         * 专题合集-关联首页底部Tab样式
         */
        COLUMN_COLLECTION_MAIN_WRAPPER,

        /**
         * 专题合集-二级页面样式
         */
        COLUMN_COLLECTION_NORMAL,

        /**
         * 专题合集-关联多Tab导航栏样式
         */
        COLUMN_COLLECTION_TAB_WRAPPER,
    }

    companion object {
        private const val ANIMATOR_DURATION = 200L
    }
}
