package com.gh.gamecenter.search

import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Shader
import android.graphics.Typeface
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.CheckedTextView
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseFragment
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.DrawableView
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.PageSwitchDataHelper
import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.databinding.FragmentSearchDefaultBinding
import com.gh.gamecenter.databinding.TabItemSearchDefaultRankBinding
import com.gh.gamecenter.db.SearchHistoryDao
import com.gh.gamecenter.eventbus.EBSearch
import com.gh.gamecenter.feature.entity.HotTagEntity
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.ExposureSource
import com.google.android.flexbox.FlexboxLayout
import com.google.android.material.tabs.TabLayout
import com.lightgame.utils.Util_System_Keyboard
import org.greenrobot.eventbus.EventBus
import org.json.JSONException
import org.json.JSONObject

open class SearchDefaultFragment : BaseFragment<Any>() {

    private var mHotTagList: List<HotTagEntity>? = null
    protected var mHistoryList: List<String>? = null
    protected var mRankList: List<SettingsEntity.Search.RankList>? = null

    protected lateinit var mBinding: FragmentSearchDefaultBinding

    private var mSearchHistoryDao: SearchHistoryDao? = null

    private var mViewModel: SearchDefaultViewModel? = null

    private var mIsGameSearch = false // 是否为游戏搜索

    val defaultViewModel: SearchDefaultViewModel?
        get() = mViewModel

    // FlexboxLayout:maxLine 不符合需求
    protected val mFlexMaxHeight = DisplayUtils.dip2px(57F)

    override fun getLayoutId(): Int {
        return R.layout.fragment_search_default
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mViewModel = viewModelProvider()

        mIsGameSearch = arguments?.getBoolean(KEY_IS_GAME_SEARCH) ?: false

        initDao()
        initView()
    }

    open fun initDao() {
        mSearchHistoryDao = SearchHistoryDao(context)
    }

    open fun initView() {
        mBinding = FragmentSearchDefaultBinding.bind(mCachedView)
        mRankList = Config.getSettings()?.search?.rankList?.apply {
            forEachIndexed { outIndex, rankList ->
                rankList.isShowIcon = !rankList.content.any { it.icon.isBlank() }
                var i = 0
                while (i < rankList.content.size) {
                    if (RegionSettingHelper.shouldThisGameBeFiltered(rankList.content[i].linkGame?.id)) {
                        rankList.content.removeAt(i)
                        i--
                    }
                    i++
                }
                rankList.content.forEachIndexed { index, rank ->
                    val source = listOf(ExposureSource("首页搜索 -> 搜索榜单", "${rankList.title}-${rank.name}"))
                    if (rank.link.type == "game") {
                        rank.exposureEvent = ExposureEvent.createEvent(
                            rank.linkGame?.toGameEntity()?.apply {
                                outerSequence = outIndex
                                sequence = index
                            },
                            source
                        )
                    } else {
                        rank.exposureEvent = ExposureEvent.createEvent(null, source)
                    }
                }
            }
        }
        mViewModel?.isExistRankList = mRankList?.isNotEmpty() == true

        mHotTagList = Config.getSettings()?.search?.hotTag
        mViewModel?.isExistHotTag = mHotTagList?.isNotEmpty() == true

        updateHistorySearchView(null)
        mViewModel?.historySearchLiveData?.observe(this) {
            updateHistorySearchView(it)
        }

        mBinding.hotTagFlexContainer.setLimitHeight(mFlexMaxHeight)
        createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = {
            val tag = mHotTagList!![it]
            NewFlatLogUtils.logSearchHotTagClick(
                tag.name ?: "",
                tag.type ?: "",
                tag.link ?: "",
                tag.text ?: ""
            )
            DataLogUtils.uploadHotTagLog(context, tag.name)
            PageSwitchDataHelper.pushCurrentPageData(
                hashMapOf(
                    Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "游戏搜索-热门标签"),
                    Pair(PageSwitchDataHelper.PAGE_BUSINESS_ID, tag.id ?: ""),
                    Pair(PageSwitchDataHelper.PAGE_BUSINESS_NAME, tag.name ?: " ")
                )
            )
            SensorsBridge.trackEvent("SearchLabelClick", "label_name", tag.name ?: "", "label_id", tag.id ?: "")
            DirectUtils.directToLinkPage(requireContext(), tag, "(搜索-${tag.name})", "") // 不需要path
        })
        initHeadView()
        initRankViewPager()
    }

    private fun initHeadView() {
        mBinding.historyHeadContainer.run {
            headTitle.text = getString(R.string.search_history)
            headTitle.textSize = 16F
            headActionTv.text = "清空"
            headActionTv.setTextColor(R.color.text_subtitleDesc.toColor(requireContext()))
            headActionTv.setDrawableStart(
                AppCompatResources.getDrawable(
                    requireContext(),
                    R.drawable.search_history_delete
                )
            )
            headActionTv.setOnClickListener {
                DialogHelper.showCenterWarningDialog(requireContext(), "清空记录", "确定清空历史搜索记录？", confirmClickCallback = {
                    mSearchHistoryDao?.deleteAll()
                    mViewModel?.isExistHistory = false
                    updateView()
                })
            }
        }
        mBinding.hotHeadContainer.headTitle.text = getString(R.string.search_hot)
        mBinding.hotHeadContainer.headTitle.textSize = 16F
        mBinding.hotHeadContainer.headActionTv.visibility = View.GONE
        mBinding.hotTagHeadContainer.headTitle.text = getString(R.string.search_hot_tag)
        mBinding.hotTagHeadContainer.headTitle.textSize = 16F
        mBinding.hotTagHeadContainer.headActionTv.visibility = View.GONE
    }

    fun initRankViewPager() {
        mRankList = mRankList?.filter { it.content.isNotEmpty() }?.take(6)
        if (mRankList.isNullOrEmpty()) return

        mBinding.run {
            val screenWidth = resources.displayMetrics.widthPixels
            val viewPagerWidth = screenWidth - 16F.dip2px() - 16F.dip2px()
            val pageWidth = screenWidth - 16F.dip2px() - 64F.dip2px()
            val pageRatio = pageWidth.toFloat() / viewPagerWidth
            val normalPageOffset = pageWidth + 12F.dip2px()
            val lastPageOffset = pageWidth - (64F.dip2px() - 12F.dip2px()) + 16F.dip2px()
            val lastPositionRatio = lastPageOffset.toFloat() / normalPageOffset

            rankTabIndicator.run {
                setupWithTabLayout(rankTabLayout)
                setupWithViewPager(rankViewPager)
                setIndicatorWidth(20)
                setIndicatorLastPositionRatio(lastPositionRatio)
            }
            rankViewPager.run {
                visibility = View.VISIBLE
                offscreenPageLimit = mRankList!!.size
                pageMargin = 12F.dip2px()
                adapter = SearchDefaultRankListAdapter(requireContext(), mRankList!!, pageRatio, mIsGameSearch)
                postExposureEvent(0)
                doOnPageSelected {
                    postExposureEvent(it)

                    val title = mRankList?.safelyGetInRelease(it)?.title ?: ""

                    val trackEvent = JSONObject()
                    try {
                        trackEvent.put("list_name", title)
                        trackEvent.put("position", it + 1)
                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }

                    if (mIsGameSearch) {
                        NewFlatLogUtils.logSearchClickRank(title, (it + 1).toString())
                    }

                    SensorsBridge.trackEvent("GameListPageSelected", trackEvent)
                }
            }

            rankTabLayout.run {
                setupWithViewPager(rankViewPager)
                for (i in 0 until tabCount) {
                    val tab = getTabAt(i) ?: continue
                    val tabTitle = if (tab.text != null) tab.text.toString() else ""
                    val tabView = getTabView(tabTitle)
                    tab.customView = tabView
                }
                getTabAt(0)?.run { updateTabStyle(this, true) }
                addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
                    override fun onTabSelected(tab: TabLayout.Tab?) {
                        updateTabStyle(tab, true)
                    }

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

                    override fun onTabReselected(tab: TabLayout.Tab?) {
                        updateTabStyle(tab, true)
                    }
                })
                handleTabLayoutBorder()
            }
        }
    }

    private fun handleTabLayoutBorder() {
        mBinding.rankTabLayout.run {
            post {
                val screenWidth = resources.displayMetrics.widthPixels
                val tabLayoutWidth = getTabLayoutWidth()
                if (screenWidth >= tabLayoutWidth) {
                    (layoutParams as ViewGroup.MarginLayoutParams).apply {
                        leftMargin = 8F.dip2px()
                        rightMargin = 8F.dip2px()
                        layoutParams = this
                    }
                    clipToPadding = true
                } else {
                    val paddingOffset = (tabLayoutWidth - screenWidth) / 2
                    if (paddingOffset < 8F.dip2px()) {
                        (layoutParams as ViewGroup.MarginLayoutParams).apply {
                            leftMargin = 8F.dip2px() - paddingOffset
                            rightMargin = 8F.dip2px() - paddingOffset
                            layoutParams = this
                        }
                        setPadding(paddingOffset, 16F.dip2px(), paddingOffset, 0)
                    } else {
                        setPadding(8F.dip2px(), 16F.dip2px(), 8F.dip2px(), 0)
                    }
                    clipToPadding = false
                }

                mBinding.rankTabIndicator.generatePath(mBinding.rankViewPager.currentItem, 0F)
            }
        }
    }

    private fun getTabLayoutWidth(): Int {
        mBinding.rankTabLayout.run {
            var tabLayoutWidth = 8F.dip2px() + 8F.dip2px()
            if (childCount > 0) {
                val viewGroup = getChildAt(0) as ViewGroup
                for (i in 0 until viewGroup.childCount) {
                    val tab = viewGroup.getChildAt(i) ?: continue
                    tabLayoutWidth += tab.width
                }
            }
            return tabLayoutWidth
        }
    }

    fun updateTabStyle(tab: TabLayout.Tab?, isChecked: Boolean) {
        tab?.customView?.findViewById<CheckedTextView>(R.id.tabTitle)?.isChecked = isChecked
    }

    private fun getTabView(title: String) =
        TabItemSearchDefaultRankBinding.inflate(layoutInflater).apply {
            tabTitle.text = title
        }.root

    fun updateView() {
        mBinding.historyHeadContainer.root.visibility =
            if (mViewModel?.isExistHistory == true) View.VISIBLE else View.GONE
        mBinding.historyFlex.visibility = if (mViewModel?.isExistHistory == true) View.VISIBLE else View.GONE
        mBinding.hotTagHeadContainer.root.layoutParams =
            (mBinding.hotTagHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
                setMargins(
                    0,
                    if (mViewModel?.isExistHistory == true) 16F.dip2px() else 0,
                    0,
                    0
                )
            }
        mBinding.hotHeadContainer.root.layoutParams =
            (mBinding.hotHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
                setMargins(
                    0,
                    if (mViewModel?.isExistHistory == false && mViewModel?.isExistHotTag == false) 16F.dip2px() else 0,
                    0,
                    0
                )
            }
        mBinding.hotTagHeadContainer.root.visibility =
            if (mViewModel?.isExistHotTag == true) View.VISIBLE else View.GONE
        mBinding.hotTagFlex.visibility = if (mViewModel?.isExistHotTag == true) View.VISIBLE else View.GONE
        mBinding.hotHeadContainer.root.visibility =
            if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
        mBinding.hotList.visibility = if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
        mBinding.rankTabLayout.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
        mBinding.rankTabIndicator.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
        mBinding.rankViewPager.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
    }

    private fun updateHistorySearchView(historyList: List<String>?) {
        mViewModel?.isExistHistory = historyList?.isNotEmpty() == true
        updateView()
        if (historyList != null) {
            mBinding.historyFlexContainer.setLimitHeight(DisplayUtils.dip2px(88F))
            createFlexContent(mBinding.historyFlex, historyList, clickListener = {
                val key = historyList[it]
                mSearchHistoryDao?.add(key)
                EventBus.getDefault().post(EBSearch("history", key))
                Util_System_Keyboard.hideSoftKeyboardByIBinder(context, mBinding.historyFlex.windowToken)
            })
        }
    }

    private fun getTagListString(): List<String> {
        val list = ArrayList<String>()
        if (mHotTagList != null) {
            for (entity in mHotTagList!!) {
                entity.name?.let { list.add(it) }
            }
        }
        return list
    }

    fun createFlexContent(
        flexView: FlexboxLayout,
        contentList: List<String>?,
        isHotTag: Boolean = false,
        clickListener: (Int) -> Unit
    ) {

        if (contentList.isNullOrEmpty()) return
        flexView.removeAllViews()

        for (index in 0 until contentList.count()) {
            val flexCell = TextView(context)
            flexView.addView(flexCell)

            val params = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 24F.dip2px())
            flexCell.layoutParams = params

            if (isHotTag && !mHotTagList.isNullOrEmpty() && mHotTagList!![index].id == SMART_TAG_ID) {
                createSmartHotTagStyle(flexCell, contentList[index])
            } else {
                flexCell.setSingleLine()
                flexCell.ellipsize = TextUtils.TruncateAt.END
                flexCell.gravity = Gravity.CENTER
                flexCell.textSize = 12F
                flexCell.text = StringUtils.shrinkStringWithDot(contentList[index], 6)
                flexCell.setTextColor(R.color.text_subtitle.toColor(requireContext()))
            }
            flexCell.setPadding(8F.dip2px(), 0, 8F.dip2px(), 0)
            flexCell.background = if (mIsDarkModeOn) GradientDrawable().apply {
                setStroke(0.5F.dip2px(), Color.parseColor("#21FFFFFF"))
                cornerRadius = 999F
            } else DrawableView.getStrokeDrawable(R.color.text_dddddd, 0.5F)
            flexCell.setOnClickListener {
                clickListener.invoke(index)
            }
        }
    }

    private fun createSmartHotTagStyle(flexCell: TextView, name: String) {
        flexCell.setDrawableStart(R.drawable.ic_smart_search)
        flexCell.compoundDrawablePadding = 4F.dip2px()
        flexCell.gravity = Gravity.CENTER_VERTICAL
        flexCell.typeface = Typeface.DEFAULT_BOLD
        flexCell.textSize = 12F
        flexCell.text = StringUtils.shrinkStringWithDot(name, 6)
        flexCell.setTextColor(Color.WHITE)
        val colors =
            intArrayOf(R.color.text_FFB749.toColor(requireContext()), R.color.text_FF6D3C.toColor(requireContext()))
        val position = floatArrayOf(0F, 1F)
        val linearGradient = LinearGradient(
            0F,
            0F,
            flexCell.paint.textSize * flexCell.text.length,
            0F,
            colors,
            position,
            Shader.TileMode.CLAMP
        )
        flexCell.paint.shader = linearGradient
        flexCell.invalidate()
    }

    private fun postExposureEvent(index: Int) {
        mRankList?.safelyGetInRelease(index)?.content?.forEach {
            if (it.link.type == "game") {
                it.exposureEvent?.run {
                    ExposureManager.log(this)
                }
            }
        }
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        initHeadView()
        mBinding.rootContainer.setBackgroundColor(R.color.background_white.toColor(requireContext()))
        mBinding.hotList.adapter?.run {
            notifyItemRangeChanged(0, itemCount)
        }
        mViewModel?.historySearchLiveData?.value?.let { updateHistorySearchView(it) }
        createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = {
            val tag = mHotTagList!![it]
            DataLogUtils.uploadHotTagLog(context, tag.name)
            PageSwitchDataHelper.pushCurrentPageData(
                hashMapOf(
                    Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "游戏搜索-热门标签"),
                    Pair(PageSwitchDataHelper.PAGE_BUSINESS_ID, tag.id ?: ""),
                    Pair(PageSwitchDataHelper.PAGE_BUSINESS_NAME, tag.name ?: " ")
                )
            )
            DirectUtils.directToLinkPage(requireContext(), tag, "(搜索-${tag.name})", "") // 不需要path
        })
    }

    companion object {
        private const val SMART_TAG_ID = "64191b9a12fccdb7290db082"

        const val KEY_IS_GAME_SEARCH = "key_is_game_search"
    }
}