package com.adealink.weparty.profile.search.page

import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.adealink.frame.base.Rlt
import com.adealink.frame.base.fastLazy
import com.adealink.frame.mvvm.view.viewBinding
import com.adealink.frame.router.Router
import com.adealink.frame.statistics.BaseStatEvent
import com.adealink.weparty.commonui.BaseFragment
import com.adealink.weparty.commonui.ext.dp
import com.adealink.weparty.commonui.ext.gone
import com.adealink.weparty.commonui.ext.isSuccess
import com.adealink.weparty.commonui.ext.show
import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
import com.adealink.weparty.commonui.recycleview.itemdecoration.VerticalSpaceItemDecoration
import com.adealink.weparty.commonui.toast.util.showFailedToast
import com.adealink.weparty.module.playmate.event.PlaymateListEventReporter
import com.adealink.weparty.module.playmate.event.PlaymateStatEvent
import com.adealink.weparty.module.profile.Profile
import com.adealink.weparty.network.data.NoMoreDataError
import com.adealink.weparty.profile.R
import com.adealink.weparty.profile.databinding.FragmentSearchUserBinding
import com.adealink.weparty.profile.relation.viewmodel.FollowViewModel
import com.adealink.weparty.profile.search.adapter.SearchUserItemViewBinder
import com.adealink.weparty.profile.search.data.SearchUserResultItemData
import com.adealink.weparty.profile.search.viewmodel.SearchUserViewModel
import com.adealink.weparty.profile.search.viewmodel.SearchViewModel
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener
import com.adealink.weparty.R as APP_R

class SearchUserFragment : BaseFragment(R.layout.fragment_search_user),
    SearchUserItemViewBinder.OnUserResultClickListener {

    private val binding by viewBinding(FragmentSearchUserBinding::bind)

    private val resultAdapter by fastLazy { MultiTypeListAdapter<SearchUserResultItemData>() }
    private val searchViewModel by activityViewModels<SearchViewModel>()
    private val searchUserViewModel by viewModels<SearchUserViewModel>()
    private val followViewModel by activityViewModels<FollowViewModel>()
    private var exposureReport = object : PlaymateListEventReporter() {
        override fun getReportEvent(
            viewHolder: RecyclerView.ViewHolder,
            position: Int
        ): BaseStatEvent? {
            val item = resultAdapter.getItem(position) ?: return null
            return PlaymateStatEvent(PlaymateStatEvent.Action.EXPOSURE).apply {
                id to item.data.uid
            }
        }

        override fun reportEvent(events: List<BaseStatEvent>) {
            val reportIds = mutableListOf<String>()
            for (event in events) {
                val playmateEvent = (event as? PlaymateStatEvent) ?: continue
                val idValue = (playmateEvent.id.value as? String) ?: continue
                reportIds.add(idValue)
            }
            if (reportIds.isNotEmpty()) {
                PlaymateStatEvent(PlaymateStatEvent.Action.EXPOSURE).apply {
                    ids to reportIds
                }.send()
            }
        }
    }

    override fun initViews() {
        super.initViews()
        binding.vRefresh.setEnableRefresh(true)
        binding.vRefresh.setEnableLoadMore(false)
        binding.vRefresh.setEnableAutoLoadMore(true)
        binding.vRefresh.setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener {
            override fun onRefresh(refreshLayout: RefreshLayout) {
                searchUserViewModel.reSearch()
            }


            override fun onLoadMore(refreshLayout: RefreshLayout) {
                searchUserViewModel.searchMore()
            }
        })

        resultAdapter.register(SearchUserItemViewBinder(this))
        binding.rvResult.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
        binding.rvResult.adapter = resultAdapter
        binding.rvResult.addItemDecoration(
            VerticalSpaceItemDecoration(20.dp())
        )
        exposureReport.register(binding.rvResult)
    }

    override fun observeViewModel() {
        super.observeViewModel()
        searchViewModel.keywordLD.observe(viewLifecycleOwner) {
            searchUserViewModel.search(it)
        }
        searchViewModel.followChangedLD.observeWithoutCache(viewLifecycleOwner) {
            searchUserViewModel.notifyFollowChanged(it.first, it.second)
        }
        searchUserViewModel.searchRltLD.observeWithoutCache(this) { rlt ->
            binding.vRefresh.finishRefresh()
            binding.vRefresh.finishLoadMore()
            binding.vRefresh.setEnableLoadMore(searchUserViewModel.hasMoreData())
            if (rlt is Rlt.Failed) {
                if (rlt.error is NoMoreDataError) {
                    return@observeWithoutCache
                }
                showFailedToast(rlt)
            }
        }
        searchUserViewModel.searchResultLD.observeWithoutCache(this) { list ->
            if (list.isEmpty()) {
                binding.rvResult.gone()
                binding.vErrorView.show(
                    errorEmptyResId = APP_R.drawable.common_list_empty_ic,
                    title = APP_R.string.commonui_list_empty
                )
            } else {
                binding.rvResult.show()
                binding.vErrorView.gone()
            }
            resultAdapter.submitList(list, true)
        }
    }

    override fun goProfile(uid: String) {
        val act = activity ?: return
        Router.build(act, Profile.UserProfile.PATH)
            .putExtra(Profile.Common.EXTRA_UID, uid)
            .start()
    }

    override fun follow(uid: String) {
        followViewModel.follow(uid).observe(this) {
            if (it.isSuccess) {
                searchViewModel.notifyFollowChanged(uid, true)
            } else {
                showFailedToast(it)
            }
        }
    }

    override fun unFollow(uid: String) {
        followViewModel.unFollow(uid).observe(this) {
            if (it.isSuccess) {
                searchViewModel.notifyFollowChanged(uid, false)
            } else {
                showFailedToast(it)
            }
        }
    }

}