package com.adealink.weparty.playmate.list

import android.content.Intent
import android.os.Bundle
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.ext.isViewBindingValid
import com.adealink.frame.log.Log
import com.adealink.frame.mvvm.view.viewBinding
import com.adealink.frame.router.Router
import com.adealink.frame.router.annotation.BindExtra
import com.adealink.frame.statistics.BaseStatEvent
import com.adealink.frame.util.onClick
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.show
import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
import com.adealink.weparty.commonui.recycleview.diffutil.BaseListDiffUtil
import com.adealink.weparty.commonui.recycleview.itemdecoration.VerticalSpaceItemDecoration
import com.adealink.weparty.commonui.toast.util.showFailedToast
import com.adealink.weparty.module.playmate.Playmate
import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
import com.adealink.weparty.module.playmate.data.TAG_PLAYMATE_LIST
import com.adealink.weparty.module.playmate.event.PlaymateListEventReporter
import com.adealink.weparty.module.playmate.event.PlaymateStatEvent
import com.adealink.weparty.network.data.NoMoreDataError
import com.adealink.weparty.playmate.R
import com.adealink.weparty.playmate.data.GenderOption
import com.adealink.weparty.playmate.data.PlaymateListData
import com.adealink.weparty.playmate.data.PlaymateListItemData
import com.adealink.weparty.playmate.data.PriceRangeOption
import com.adealink.weparty.playmate.data.PriceSort
import com.adealink.weparty.playmate.data.StarOption
import com.adealink.weparty.playmate.databinding.FragmentPlaymateListBinding
import com.adealink.weparty.playmate.findpartner.FindPartnerFragment
import com.adealink.weparty.playmate.findpartner.data.OptionData
import com.adealink.weparty.playmate.list.adapter.PlaymateListItemViewBinder
import com.adealink.weparty.playmate.list.comp.PlaymateListFilterComp
import com.adealink.weparty.playmate.list.viewmodel.PlaymateListViewModel
import com.adealink.weparty.playmate.viewmodel.PlaymateViewModelFactory
import com.adealink.weparty.util.parcelableExtra
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener
import com.tencent.qcloud.tuikit.tuichat.component.audio.AudioPlayer
import com.adealink.weparty.R as APP_R

class PlaymateListFragment : BaseFragment(R.layout.fragment_playmate_list),
    PlaymateListItemViewBinder.OnPlaymateListListener {

    @BindExtra(Playmate.Common.EXTRA_FIRST_CATEGORY_CODE)
    var firstCategoryCode: String? = null

    @BindExtra(Playmate.Common.EXTRA_CATEGORY)
    var category: PlaymateCategoryData? = null

    @BindExtra(Playmate.Common.EXTRA_LAST_ITEM_BOTTOM)
    var lastItemBottom: Int? = null

    @BindExtra(Playmate.List.EXTRA_OPTION_GENDER)
    var optionGender: Int? = GenderOption.UNLIMITED.value

//    @BindExtra(Playmate.List.EXTRA_OPTION_AGE)
//    var optionAge: Int? = AgeOption.UNLIMITED.value

    @BindExtra(Playmate.List.EXTRA_OPTION_STAR)
    var optionStar: Int? = StarOption.DEFAULT.value

    @BindExtra(Playmate.List.EXTRA_OPTION_PRICE_RANGE)
    var optionPriceRange: Int? = PriceRangeOption.UNLIMITED.value

    @BindExtra(Playmate.List.EXTRA_OPTION_OTHER)
    var otherOptions: List<OptionData>? = null


    private val binding by viewBinding(FragmentPlaymateListBinding::bind)
    private val listAdapter by fastLazy { MultiTypeListAdapter<PlaymateListItemData>() }
    private val playmateListViewModel by viewModels<PlaymateListViewModel> { PlaymateViewModelFactory() }

    private var exposureReport = object : PlaymateListEventReporter() {
        override fun getReportEvent(
            viewHolder: RecyclerView.ViewHolder,
            position: Int
        ): BaseStatEvent? {
            val item = listAdapter.getItem(position) as? PlaymateListItemData ?: 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 onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Router.bind(this)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        if (!isViewBindingValid()) {
            return
        }
        firstCategoryCode = intent?.getStringExtra(Playmate.Common.EXTRA_FIRST_CATEGORY_CODE)
        category =
            intent?.parcelableExtra(
                Playmate.Common.EXTRA_CATEGORY,
                PlaymateCategoryData::class.java
            )
        optionGender =
            intent?.getIntExtra(Playmate.List.EXTRA_OPTION_GENDER, GenderOption.UNLIMITED.value)
//        optionAge = intent?.getIntExtra(Playmate.List.EXTRA_OPTION_AGE, AgeOption.UNLIMITED.value)
        optionStar = intent?.getIntExtra(Playmate.List.EXTRA_OPTION_STAR, StarOption.DEFAULT.value)
        optionPriceRange =
            intent?.getIntExtra(
                Playmate.List.EXTRA_OPTION_PRICE_RANGE,
                PriceRangeOption.UNLIMITED.value
            )
        otherOptions = intent?.getParcelableArrayListExtra(Playmate.List.EXTRA_OPTION_OTHER)
        loadData()
    }

    override fun onPause() {
        super.onPause()
        AudioPlayer.getInstance().stopPlay()
    }

    override fun initViews() {
        super.initViews()
        if (category == null) {
            Log.i(TAG_PLAYMATE_LIST, "PlaymateListFragment init fail, for categoryCode is null")
        }
        binding.vListFilter.clFindPartner.onClick {
            findPartner()
        }

        binding.refreshLayout.setEnableRefresh(true)
        binding.refreshLayout.setEnableLoadMore(true)
        binding.refreshLayout.setEnableAutoLoadMore(true)
        binding.refreshLayout.setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener {
            override fun onRefresh(refreshLayout: RefreshLayout) {
                refreshPlaymateList()
            }


            override fun onLoadMore(refreshLayout: RefreshLayout) {
                loadMorePlaymateList()
            }
        })

        listAdapter.register(PlaymateListItemViewBinder(this, this))
        binding.vList.adapter = listAdapter
        binding.vList.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
        binding.vList.addItemDecoration(
            VerticalSpaceItemDecoration(
                10.dp(),
                lastSpaceHeight = lastItemBottom ?: 0
            )
        )
        exposureReport.register(binding.vList)
    }

    override fun initComponents() {
        super.initComponents()
        PlaymateListFilterComp(
            this,
            binding.vListFilter,
            playmateListViewModel.starRankLD.value ?: StarOption.DEFAULT,
            playmateListViewModel.priceRankLD.value ?: PriceSort.DEFAULT,
            {
                playmateListViewModel.changeStarSort()
            },
            {
                playmateListViewModel.changePriceSort()
            }
        ).attach()
    }

    private fun findPartner() {
        FindPartnerFragment().show(childFragmentManager, Playmate.FindPartner.PATH)
    }

    fun updateCategory(firstCategoryCode: String?, category: PlaymateCategoryData?) {
        if (!isViewBindingValid()) {
            return
        }
        this@PlaymateListFragment.firstCategoryCode = firstCategoryCode
        this@PlaymateListFragment.category = category
        playmateListViewModel.setCategoryCode(firstCategoryCode, category?.code)
        refreshPlaymateList()
    }

    override fun loadData() {
        super.loadData()
        playmateListViewModel.setCategoryCode(
            firstCategoryCode = firstCategoryCode,
            code = category?.code,
            optionGender = optionGender,
            optionAge = null,
            optionStar = optionStar,
            optionPriceRange = optionPriceRange,
            otherOptions = otherOptions
        )
        refreshPlaymateList()
    }

    private fun refreshPlaymateList() {
        playmateListViewModel.refreshList()
    }

    private fun loadMorePlaymateList() {
        playmateListViewModel.loadMoreList()
    }

    override fun observeViewModel() {
        super.observeViewModel()
        playmateListViewModel.starRankLD.observeWithoutCache(viewLifecycleOwner) {
            binding.refreshLayout.autoRefresh()
        }
        playmateListViewModel.priceRankLD.observeWithoutCache(viewLifecycleOwner) {
            binding.refreshLayout.autoRefresh()
        }
        playmateListViewModel.listRltLD.observe(viewLifecycleOwner) { rlt ->
            binding.refreshLayout.finishRefresh()
            binding.refreshLayout.finishLoadMore()
            binding.refreshLayout.setEnableLoadMore(playmateListViewModel.hasMoreData())
            if (rlt is Rlt.Failed) {
                if (rlt.error is NoMoreDataError) {
                    return@observe
                }
                showFailedToast(rlt)
            }
        }
        playmateListViewModel.listLD.observe(viewLifecycleOwner) { list ->
            if (list.isNullOrEmpty()) {
                binding.vList.gone()
                binding.vErrorView.show(
                    errorEmptyResId = APP_R.drawable.common_list_empty_ic,
                    title = APP_R.string.commonui_list_empty
                )
            } else {
                binding.vList.show()
                binding.vErrorView.gone()
            }
            listAdapter.submitList(list.map { data ->
                PlaymateListItemData(data)
            })
        }
    }

    override fun goCategoryDetail(data: PlaymateListData) {
        activity?.let { act ->
            Router.build(act, Playmate.Detail.PATH)
                .putExtra(Playmate.Detail.EXTRA_PLAYMATE_ID, data.id)
                .putExtra(Playmate.Detail.EXTRA_PLAYMATE_NAME, data.categoryName)
                .start()
        }
    }


}