package com.adealink.weparty.profile.search

import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import android.widget.TextView.OnEditorActionListener
import androidx.activity.viewModels
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import com.adealink.frame.aab.util.getCompatColor
import com.adealink.frame.base.fastLazy
import com.adealink.frame.mvvm.view.viewBinding
import com.adealink.frame.router.Router
import com.adealink.frame.router.annotation.RouterUri
import com.adealink.frame.util.onClick
import com.adealink.weparty.commonui.BaseActivity
import com.adealink.weparty.commonui.ext.dp
import com.adealink.weparty.commonui.ext.fitSystemWindows
import com.adealink.weparty.commonui.ext.gone
import com.adealink.weparty.commonui.ext.hide
import com.adealink.weparty.commonui.ext.onWindowInsets
import com.adealink.weparty.commonui.ext.show
import com.adealink.weparty.commonui.recycleview.adapter.BaseActivityTabFragmentStateAdapter
import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
import com.adealink.weparty.commonui.recycleview.layoutmanager.FlowLayoutManager
import com.adealink.weparty.commonui.widget.EmptyFragment
import com.adealink.weparty.module.profile.Profile
import com.adealink.weparty.profile.R
import com.adealink.weparty.profile.databinding.ActivityUserSearchBinding
import com.adealink.weparty.profile.databinding.LayoutSearchTabBinding
import com.adealink.weparty.profile.datasource.local.SearchLocalService
import com.adealink.weparty.profile.search.adapter.SearchHistoryViewBinder
import com.adealink.weparty.profile.search.data.SearchHistoryItemData
import com.adealink.weparty.profile.search.viewmodel.SearchViewModel
import com.adealink.weparty.util.QMUIKeyboardHelper
import com.adealink.weparty.util.QMUIStatusBarHelper
import com.adealink.weparty.util.applyImmersive
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator

@RouterUri(
    path = [Profile.Search.PATH],
    desc = "搜索"
)
class SearchActivity : BaseActivity(),
    SearchHistoryViewBinder.OnHistoryClickListener {

    private val binding by viewBinding(ActivityUserSearchBinding::inflate)

    private val historyAdapter by fastLazy { MultiTypeListAdapter<SearchHistoryItemData>() }
    private var historyList = mutableListOf<String>()

    private val searchViewModel by viewModels<SearchViewModel>()
    private lateinit var pageAdapter: PageAdapter

    override fun onBeforeCreate() {
        super.onBeforeCreate()
        Router.bind(this)
    }

    override fun initViews() {
        super.initViews()
        QMUIStatusBarHelper.setStatusBarLightMode(this)
        setContentView(binding.root)
        applyImmersive { top ->
            binding.clTop.root.updateLayoutParams<ConstraintLayout.LayoutParams> {
                topMargin = top
            }
        }
        binding.clTop.ivBack.onClick {
            finish()
        }
        binding.clTop.ivClearInput.onClick {
            binding.clTop.etSearchInput.setText(null)
        }

        historyAdapter.register(SearchHistoryViewBinder(this))
        binding.clHistory.rvHistory.layoutManager = FlowLayoutManager(
            FlowLayoutManager.VERTICAL,
            8.dp(),
            10.dp()
        )
        binding.clHistory.rvHistory.adapter = historyAdapter

        binding.clTop.etSearchInput.isClickable = true
        binding.clTop.etSearchInput.setOnEditorActionListener(object : OnEditorActionListener {
            override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
                if (actionId == EditorInfo.IME_ACTION_SEARCH
                    || (actionId == EditorInfo.IME_ACTION_UNSPECIFIED && event != null && event.keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN)
                ) {
                    search(binding.clTop.etSearchInput.text?.toString(), false)
                }
                return true
            }
        })
        binding.clTop.etSearchInput.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(
                s: CharSequence?,
                start: Int,
                count: Int,
                after: Int
            ) {
            }

            override fun onTextChanged(
                s: CharSequence?,
                start: Int,
                before: Int,
                count: Int
            ) {
            }

            override fun afterTextChanged(s: Editable?) {
                val input = s?.trim()?.toString()
                searchViewModel.setInput(input)
            }
        })
        binding.clTop.tvSearch.onClick {
            search(binding.clTop.etSearchInput.text?.toString(), false)
        }

        fitWindow()
        QMUIKeyboardHelper.showKeyboard(binding.clTop.etSearchInput, 200)
        binding.clTop.etSearchInput.requestFocus()

        initSearchTab()
    }

    private fun fitWindow() {
        // 关键：只在需要的时候设置
        window?.fitSystemWindows(false)
        // 内容布局处理键盘
        binding.root.onWindowInsets { view, insets ->
            val ime = insets.getInsets(WindowInsetsCompat.Type.ime())
            val nav = insets.getInsets(WindowInsetsCompat.Type.navigationBars())

            // 键盘显示时使用键盘高度，否则使用导航栏高度
            val bottomInset = if (ime.bottom > 0) ime.bottom else nav.bottom
            view.updatePadding(bottom = bottomInset)
            insets
        }
    }

    private fun initSearchTab() {
        pageAdapter = PageAdapter()
        binding.clResult.vpContent.offscreenPageLimit = 1
        binding.clResult.vpContent.adapter = pageAdapter
        binding.clResult.vpContent.isSaveEnabled = false
        TabLayoutMediator(
            binding.clResult.tlTab,
            binding.clResult.vpContent,
            true,
            true
        ) { tabLayout, position ->
            tabLayout.setCustomView(R.layout.layout_search_tab)
            tabLayout.customView?.let { tabView ->
                val tabViewBinding = LayoutSearchTabBinding.bind(tabView)
                onConfigureTab(tabViewBinding, position)
                updateTabView(
                    tabLayout,
                    0 == position
                )
            }
        }.attach()
        binding.clResult.tlTab.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?) {
            }

        })
    }

    private fun onConfigureTab(binding: LayoutSearchTabBinding, position: Int) {
        binding.tvTab.text = pageAdapter.getTabName(position)
    }

    private fun updateTabView(
        tabView: TabLayout.Tab?,
        isSelected: Boolean
    ) {
        tabView?.customView?.let { tabView ->
            val tabViewBinding = LayoutSearchTabBinding.bind(tabView)
            if (isSelected) {
                tabViewBinding.vSelected.show()
                tabViewBinding.tvTab.setTextColor(getCompatColor(com.adealink.weparty.R.color.color_FF1D2129))
            } else {
                tabViewBinding.vSelected.hide()
                tabViewBinding.tvTab.setTextColor(getCompatColor(com.adealink.weparty.R.color.color_FFC9CDD4))
            }
        }
    }

    override fun loadData() {
        super.loadData()
        updateHistoryList(SearchLocalService.getSearchHistory()) { list ->
            if (list.isEmpty()) {
                binding.clHistory.root.gone()
                return@updateHistoryList
            }
            binding.clHistory.root.show()
            historyAdapter.submitList(list.map { SearchHistoryItemData(it) })
        }
    }

    private fun search(input: String?, fromHistory: Boolean) {
        val keyword = input?.trim()
        if (keyword.isNullOrEmpty()) {
            return
        }
        binding.clTop.etSearchInput.clearFocus()
        QMUIKeyboardHelper.hideKeyboard(binding.clTop.etSearchInput)
        hideHistoryList()

        //校验非法字符
        searchViewModel.search(keyword)
        binding.clResult.root.show()

        if (!fromHistory) {
            addHistoryList(input) { list ->
                historyAdapter.submitList(list.map { SearchHistoryItemData(it) })
            }
        }
    }

    private fun addHistoryList(
        keyword: String?,
        commit: ((historyList: List<String>) -> Unit)?
    ) {
        if (keyword.isNullOrEmpty()) {
            return
        }
        historyList.remove(keyword)
        historyList.add(0, keyword)
        updateHistoryList(historyList, commit)
    }

    private fun updateHistoryList(
        historyList: List<String>,
        commit: ((historyList: List<String>) -> Unit)?
    ) {
        this.historyList = historyList.take(SearchLocalService.MAX_HISTORY_COUNT).toMutableList()
        SearchLocalService.saveSearchHistory(this.historyList)
        commit?.invoke(this.historyList)
    }

    override fun observeViewModel() {
        super.observeViewModel()
        searchViewModel.isInputEmpty.observe(this) {
            binding.clTop.ivClearInput.show(!it)
            binding.clTop.tvSearch.isEnabled = !it
            if (it) {
                binding.clResult.root.gone()
                if (historyList.isEmpty()) {
                    binding.clHistory.root.gone()
                } else {
                    binding.clHistory.root.show()
                }
            }
        }
        searchViewModel.moreUserClickLD.observeWithoutCache(this) {
            binding.clResult.vpContent.setCurrentItem(1, true)
        }
        searchViewModel.moreRoomClickLD.observeWithoutCache(this) {
            binding.clResult.vpContent.setCurrentItem(2, true)
        }
    }

    private fun hideHistoryList() {
        binding.clHistory.root.gone()
    }

    override fun onDestroy() {
        super.onDestroy()
        binding.clTop.etSearchInput.clearFocus()
        QMUIKeyboardHelper.hideKeyboard(binding.clTop.etSearchInput)
    }

    override fun onClick(
        item: SearchHistoryItemData,
        pos: Int
    ) {
        binding.clTop.etSearchInput.setText(item.keyword)
        search(item.keyword, true)
    }

    internal inner class PageAdapter : BaseActivityTabFragmentStateAdapter(this) {
        override fun getTabName(pos: Int): String {
            return SEARCH_TABS.getOrNull(pos)?.name?.invoke() ?: ""
        }

        override fun getItemCount(): Int {
            return SEARCH_TABS.size
        }

        override fun createFragment(position: Int): Fragment {
            val tab = SEARCH_TABS.getOrNull(position) ?: return EmptyFragment()
            return tab.fragmentBuilder.invoke()
        }

    }

}