package com.adealink.weparty.commonui.widget

import android.content.Context
import android.content.res.TypedArray
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.TypedValue
import android.view.GestureDetector
import android.view.LayoutInflater
import android.view.MotionEvent
import android.widget.LinearLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.withStyledAttributes
import androidx.core.view.updateLayoutParams
import androidx.viewpager2.widget.ViewPager2
import com.adealink.frame.aab.util.getCompatColor
import com.adealink.frame.util.DisplayUtil
import com.adealink.weparty.R
import com.adealink.weparty.commonui.drawabletoolbox.DrawableBuilder
import com.adealink.weparty.commonui.ext.dp
import com.adealink.weparty.commonui.ext.dpf
import com.adealink.weparty.commonui.recycleview.adapter.BaseActivityTabFragmentStateAdapter
import com.adealink.weparty.commonui.recycleview.adapter.BaseTabFragmentStateAdapter
import com.adealink.weparty.databinding.LayoutCommonTabItemBinding
import com.adealink.weparty.databinding.LayoutCommonTabItemMatchParentBinding
import com.adealink.weparty.databinding.LayoutCommonTabLayoutBinding
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator

class CommonTabLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : ConstraintLayout(context, attrs, defStyleAttr) {
    companion object {
        private const val MODE_SCROLLABLE = 0
        private const val MODE_FIXED = 1
        private const val MODE_AUTO = 2
        private const val TYPE_WRAP_CONTENT = 0
        private const val TYPE_MATCH_PARENT = 1


        private const val INDICATOR_WIDTH_MATCH_PARENT = 0 //铺满整个tab
        private const val INDICATOR_WIDTH_WRAP_TEXT = 1 //包裹文字
        private const val INDICATOR_WIDTH_FIXED = 2 //固定大小
    }

    private var binding: LayoutCommonTabLayoutBinding =
        LayoutCommonTabLayoutBinding.inflate(LayoutInflater.from(getContext()), this, true)
    private var viewPager2: ViewPager2? = null
    private var tabFragmentStateAdapter: BaseTabFragmentStateAdapter? = null
    var tabLayout = binding.commonTabLayout
    private var tabType = TYPE_WRAP_CONTENT
    private var normalTabTextSize = 16f.dpf()
    private var selectedTabTextSize = 16f.dpf()
    private var indicatorColor: Int = 0
    private var indicatorDrawable: Drawable? = null

    private var indicatorWidthMode: Int = INDICATOR_WIDTH_MATCH_PARENT

    private var indicatorWidth: Float? = null //仅INDICATOR_WIDTH_FIXED生效

    private var indicatorHeight: Float = 2.dpf()
    private var selectedTabColor: Int = 0
    private var selectedTabBg: Drawable? = null
    private var normalTabColor: Int = 0
    private var normalTabBg: Drawable? = null
    private var tabPaddingHorizontal: Int = 4.dp()
    private var tabPaddingVertical: Int = 0
    private var fixedTabScrollableMode: Boolean = false
    private var scrollToTop: (() -> Unit)? = null
    private val gestureDetector: GestureDetector by lazy {
        GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
            override fun onDoubleTap(e: MotionEvent): Boolean {
                scrollToTop?.invoke()
                return true
            }
        })
    }

    init {
        context.withStyledAttributes(
            attrs,
            R.styleable.CommonTabLayout
        ) {
            initTypedArray(this)
        }
    }

    private fun initTypedArray(typedArray: TypedArray) {
        fixedTabScrollableMode =
            typedArray.getBoolean(R.styleable.CommonTabLayout_fixed_tab_scrollable_mode, false)
        setTabMode(typedArray.getInt(R.styleable.CommonTabLayout_tab_mode, MODE_SCROLLABLE))
        tabType = typedArray.getInt(R.styleable.CommonTabLayout_tab_type, TYPE_WRAP_CONTENT)
        normalTabTextSize = typedArray.getDimension(
            R.styleable.CommonTabLayout_normal_text_size,
            DisplayUtil.sp2px(16f).toFloat()
        )
        selectedTabTextSize =
            typedArray.getDimension(
                R.styleable.CommonTabLayout_selected_text_size,
                DisplayUtil.sp2px(16f).toFloat()
            )
        indicatorColor = typedArray.getColor(
            R.styleable.CommonTabLayout_indicator_color,
            getCompatColor(R.color.color_222222)
        )
        indicatorDrawable = typedArray.getDrawable(
            R.styleable.CommonTabLayout_indicator_drawable
        )
        indicatorWidthMode = typedArray.getInt(
            R.styleable.CommonTabLayout_indicator_width_mode,
            INDICATOR_WIDTH_MATCH_PARENT
        )
        indicatorWidth = typedArray.getDimension(
            R.styleable.CommonTabLayout_indicator_width,
            0f,
        )
        indicatorHeight = typedArray.getDimension(
            R.styleable.CommonTabLayout_indicator_height,
            1.dpf(),
        )
        normalTabColor = typedArray.getColor(
            R.styleable.CommonTabLayout_normal_tab_color,
            getCompatColor(R.color.color_tab_normal_match_parent)
        )
        normalTabBg = typedArray.getDrawable(
            R.styleable.CommonTabLayout_normal_tab_bg
        )
        selectedTabColor = typedArray.getColor(
            R.styleable.CommonTabLayout_selected_tab_color,
            getCompatColor(R.color.color_tab_selected)
        )
        selectedTabBg = typedArray.getDrawable(
            R.styleable.CommonTabLayout_selected_tab_bg
        )
        tabPaddingHorizontal = typedArray.getDimension(
            R.styleable.CommonTabLayout_tab_padding_horizontal,
            4.dpf()
        ).toInt()
        tabPaddingVertical = typedArray.getDimension(
            R.styleable.CommonTabLayout_tab_padding_vertical,
            0f
        ).toInt()
        setRootWidthWithTabType(tabType)
    }

    fun setTabMode(mode: Int) {
        when (mode) {
            MODE_FIXED -> {
                if (fixedTabScrollableMode) {
                    isTabContentOverflow()
                } else {
                    tabLayout.tabMode = TabLayout.MODE_FIXED
                }
            }

            MODE_SCROLLABLE -> {
                tabLayout.tabMode = TabLayout.MODE_SCROLLABLE
            }

            MODE_AUTO -> {
                tabLayout.tabMode = TabLayout.MODE_AUTO
            }
        }
    }

    private fun isTabContentOverflow(spacing: Int = 28) {
        tabLayout.post {
            val tabLayoutWidth = tabLayout.width
            var totalTabWidth = 0
            for (i in 0 until tabLayout.tabCount) {
                val tab = tabLayout.getTabAt(i)
                tab?.view?.let {
                    totalTabWidth += it.width

                    // 为每个 TabItem 设置固定间距
                    val layoutParams = it.layoutParams as MarginLayoutParams
                    layoutParams.setMargins(0, 0, spacing, 0)
                    it.layoutParams = layoutParams
                }
            }

            // 根据总宽度是否超出父容器，来决定是否设置为可滑动模式
            if (totalTabWidth + spacing * (tabLayout.tabCount - 1) > tabLayoutWidth) {
                setTabMode(MODE_SCROLLABLE)
            } else {
                setTabMode(MODE_FIXED)
                // 设置每个 Tab 项的宽度均匀分配
                for (i in 0 until tabLayout.tabCount) {
                    val tab = tabLayout.getTabAt(i)
                    tab?.view?.layoutParams =
                        LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
                }
            }
        }
    }

    fun updateColor(normalTabColor: Int, selectedTabColor: Int, indicatorColor: Int) {
        this.normalTabColor = normalTabColor
        this.selectedTabColor = selectedTabColor
        this.indicatorColor = indicatorColor
        for (i in 0 until tabLayout.tabCount) {
            tabLayout.getTabAt(i)?.let {
                updateTabView(
                    it,
                    viewPager2?.currentItem == i,
                    tabFragmentStateAdapter?.getTabName(i)
                )
            }
        }
    }

    fun createMediatorAndAttach(
        viewPager2: ViewPager2?,
        tabFragmentStateAdapter: BaseTabFragmentStateAdapter?,
        currentItem: Int,
        showIndicator: Boolean = true,
        scrollToTop: (() -> Unit)? = null,
        smoothScroll: Boolean = true
    ) {
        this.viewPager2 = viewPager2
        this.tabFragmentStateAdapter = tabFragmentStateAdapter
        this.scrollToTop = scrollToTop
        viewPager2?.let {
            TabLayoutMediator(
                tabLayout, it, true, smoothScroll
            ) { tab: TabLayout.Tab, position: Int ->
                run {
                    if (tabType == TYPE_WRAP_CONTENT) {
                        tab.setCustomView(R.layout.layout_common_tab_item)
                    } else {
                        tab.setCustomView(R.layout.layout_common_tab_item_match_parent)
                    }
                    tab.view.setOnTouchListener { v, event ->
                        gestureDetector.onTouchEvent(event)
                        false
                    }
                    updateTabView(
                        tab,
                        currentItem == position,
                        tabFragmentStateAdapter?.getTabName(position),
                        showIndicator
                    )
                }
            }.attach()
        }
        tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab?) {
                updateTabView(tab, true, null, showIndicator)
            }

            override fun onTabUnselected(tab: TabLayout.Tab?) {
                updateTabView(tab, false, null, showIndicator)
            }

            override fun onTabReselected(tab: TabLayout.Tab?) {
            }
        })
    }

    private fun setRootWidthWithTabType(type: Int) {
        val lp = binding.root.layoutParams
        if (type == TYPE_WRAP_CONTENT) {
            lp.width = LayoutParams.WRAP_CONTENT
        } else {
            lp.width = LayoutParams.MATCH_PARENT
        }
        binding.root.layoutParams = lp
    }

    fun createMediatorAndAttach(
        viewPager2: ViewPager2?,
        tabFragmentStateAdapter: BaseActivityTabFragmentStateAdapter?,
        currentItem: Int,
        showIndicator: Boolean = true,
        scrollToTop: (() -> Unit)? = null
    ) {
        this.viewPager2 = viewPager2
        this.scrollToTop = scrollToTop
        viewPager2?.let {
            TabLayoutMediator(
                tabLayout, it
            ) { tab: TabLayout.Tab, position: Int ->
                run {
                    if (tabType == TYPE_WRAP_CONTENT) {
                        tab.setCustomView(R.layout.layout_common_tab_item)
                    } else {
                        tab.setCustomView(R.layout.layout_common_tab_item_match_parent)
                    }
                    tab.view.setOnTouchListener { v, event ->
                        gestureDetector.onTouchEvent(event)
                        false
                    }
                    updateTabView(
                        tab,
                        currentItem == position,
                        tabFragmentStateAdapter?.getTabName(position),
                        showIndicator
                    )
                }
            }.attach()
        }
        tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {

            override fun onTabSelected(tab: TabLayout.Tab?) {
                updateTabView(tab, true)
            }

            override fun onTabUnselected(tab: TabLayout.Tab?) {
                updateTabView(tab, false)
            }

            override fun onTabReselected(tab: TabLayout.Tab?) {
            }
        })
    }


    fun updateTabView(
        tab: TabLayout.Tab?,
        isSelected: Boolean,
        name: String? = null,
        showIndicator: Boolean = true,
    ) {
        val indicatorBackground = indicatorDrawable ?: DrawableBuilder()
            .rectangle()
            .solidColor(indicatorColor)
            .cornerRadius(DisplayUtil.dp2px(5f))
            .build()
        if (tabType == TYPE_WRAP_CONTENT) {
            tab?.customView?.let {
                val customViewBinding = LayoutCommonTabItemBinding.bind(it)
                customViewBinding.tabTitle.setPadding(
                    tabPaddingHorizontal,
                    tabPaddingVertical,
                    tabPaddingHorizontal,
                    tabPaddingVertical
                )
                when (indicatorWidthMode) {
                    INDICATOR_WIDTH_MATCH_PARENT -> {
                        customViewBinding.vLine.updateLayoutParams<LayoutParams> {
                            width = 0
                            height = indicatorHeight.toInt()
                            startToStart = LayoutParams.PARENT_ID
                            endToEnd = LayoutParams.PARENT_ID
                        }
                    }

                    INDICATOR_WIDTH_WRAP_TEXT -> {
                        customViewBinding.vLine.updateLayoutParams<LayoutParams> {
                            width = 0
                            height = indicatorHeight.toInt()
                            startToStart = customViewBinding.tabTitle.id
                            endToEnd = customViewBinding.tabTitle.id
                        }
                    }

                    INDICATOR_WIDTH_FIXED -> {
                        customViewBinding.vLine.updateLayoutParams<LayoutParams> {
                            width = indicatorWidth?.toInt() ?: 10.dp()
                            height = indicatorHeight.toInt()
                            startToStart = LayoutParams.PARENT_ID
                            endToEnd = LayoutParams.PARENT_ID
                        }
                    }
                }
                customViewBinding.vLine.background = indicatorBackground
                name?.let {
                    customViewBinding.tabTitle.text = name
                }
                if (isSelected) {
                    customViewBinding.tabTitle.background = selectedTabBg
                    customViewBinding.tabTitle.setTextSize(
                        TypedValue.COMPLEX_UNIT_PX,
                        selectedTabTextSize
                    )
                    customViewBinding.tabTitle.setTextColor(selectedTabColor)
                    if (showIndicator) {
                        customViewBinding.vLine.visibility = VISIBLE
                    } else {
                        customViewBinding.vLine.visibility = GONE
                    }
                } else {
                    customViewBinding.tabTitle.background = normalTabBg
                    customViewBinding.tabTitle.setTextSize(
                        TypedValue.COMPLEX_UNIT_PX,
                        normalTabTextSize
                    )
                    customViewBinding.tabTitle.setTextColor(normalTabColor)
                    customViewBinding.vLine.visibility = GONE
                }
            }
        } else {
            tab?.customView?.let {
                val customViewBinding = LayoutCommonTabItemMatchParentBinding.bind(it)
                customViewBinding.tabTitle.setPadding(
                    tabPaddingHorizontal,
                    tabPaddingVertical,
                    tabPaddingHorizontal,
                    tabPaddingVertical
                )
                when (indicatorWidthMode) {
                    INDICATOR_WIDTH_MATCH_PARENT -> {
                        customViewBinding.vLine.updateLayoutParams<LayoutParams> {
                            width = 0
                            height = indicatorHeight.toInt()
                            startToStart = LayoutParams.PARENT_ID
                            endToEnd = LayoutParams.PARENT_ID
                        }
                    }

                    INDICATOR_WIDTH_WRAP_TEXT -> {
                        customViewBinding.vLine.updateLayoutParams<LayoutParams> {
                            width = 0
                            height = indicatorHeight.toInt()
                            startToStart = customViewBinding.tabTitle.id
                            endToEnd = customViewBinding.tabTitle.id
                        }
                    }

                    INDICATOR_WIDTH_FIXED -> {
                        customViewBinding.vLine.updateLayoutParams<LayoutParams> {
                            width = indicatorWidth?.toInt() ?: 10.dp()
                            height = indicatorHeight.toInt()
                            startToStart = LayoutParams.PARENT_ID
                            endToEnd = LayoutParams.PARENT_ID
                        }
                    }
                }
                customViewBinding.vLine.background = indicatorBackground
                name?.let {
                    customViewBinding.tabTitle.text = name
                }
                if (isSelected) {
                    customViewBinding.tabTitle.background = selectedTabBg
                    customViewBinding.tabTitle.setTextColor(selectedTabColor)
                    customViewBinding.tabTitle.setTextSize(
                        TypedValue.COMPLEX_UNIT_PX,
                        selectedTabTextSize
                    )
                    if (showIndicator) {
                        customViewBinding.vLine.visibility = VISIBLE
                    } else {
                        customViewBinding.vLine.visibility = GONE
                    }
                } else {
                    customViewBinding.tabTitle.background = normalTabBg
                    customViewBinding.tabTitle.setTextColor(normalTabColor)
                    customViewBinding.vLine.visibility = GONE
                    customViewBinding.tabTitle.setTextSize(
                        TypedValue.COMPLEX_UNIT_PX,
                        normalTabTextSize
                    )
                }
            }
        }
    }
}