package com.adealink.weparty.im.session.comp.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.graphics.toColorInt
import androidx.fragment.app.activityViewModels
import androidx.viewpager.widget.ViewPager
import com.adealink.frame.base.fastLazy
import com.adealink.frame.mvvm.view.viewBinding
import com.adealink.frame.mvvm.viewmodel.activityViewModels
import com.adealink.frame.router.Router
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.viewpager.RecyclePagerAdapter
import com.adealink.weparty.commonui.widget.BottomDialogFragment
import com.adealink.weparty.im.R
import com.adealink.weparty.im.databinding.FragmentSessionUserOrderTopBarBinding
import com.adealink.weparty.im.databinding.LayoutSessionOrderTopBarContainerBinding
import com.adealink.weparty.im.session.SessionFragment
import com.adealink.weparty.im.session.comp.fragment.data.OrderTopItemData
import com.adealink.weparty.im.session.comp.fragment.data.SkillTopItemData
import com.adealink.weparty.im.session.comp.fragment.data.TopBarData
import com.adealink.weparty.im.session.comp.fragment.data.ViewType
import com.adealink.weparty.im.session.comp.fragment.listener.IGoVoiceCallback
import com.adealink.weparty.im.session.comp.fragment.widget.SkillTopBarView
import com.adealink.weparty.im.session.comp.fragment.widget.UserOrderTopBarView
import com.adealink.weparty.im.session.comp.viewmodel.SessionOrderTopViewModel
import com.adealink.weparty.module.call.CallModule
import com.adealink.weparty.module.im.IM
import com.adealink.weparty.module.order.Order
import com.adealink.weparty.module.order.OrderModule
import com.adealink.weparty.module.order.data.OrderDetailInfo
import com.adealink.weparty.module.profile.ProfileModule
import com.adealink.weparty.module.profile.data.UserPlaymateSkill
import com.adealink.weparty.viewmodel.parentFragmentViewModels

class OrderTopBarFragment : BaseFragment(R.layout.fragment_session_user_order_top_bar),
    IGoVoiceCallback {

    private val binding by viewBinding(FragmentSessionUserOrderTopBarBinding::bind)

    private val orderTopViewModel by activityViewModels<SessionOrderTopViewModel>()

    private val orderViewModel by fastLazy { OrderModule.getOrderViewModel(this) }

    private val viewAdapter by fastLazy { ViewAdapter() }

    override fun initViews() {
        super.initViews()
        binding.vp.pageMargin = 8.dp()
        binding.vp.offscreenPageLimit = 3
        binding.vp.adapter = viewAdapter
        binding.vp.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
                binding.vpIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels)
            }

            override fun onPageSelected(position: Int) {
                binding.vpIndicator.onPageSelected(position)
            }

            override fun onPageScrollStateChanged(state: Int) {
                binding.vpIndicator.onPageScrollStateChanged(state)
            }
        })
        binding.vpIndicator.config.apply {
            setIndicatorSize(5.dp())
            setIndicatorSpace(6.dp())
            setNormalWidth(5.dp())
            setSelectedWidth(5.dp())
            setNormalColor("#9FCD9B".toColorInt())
            setSelectedColor("#3FBFBD".toColorInt())
        }
        binding.vPendingOrder.setGoVoiceCallback(this@OrderTopBarFragment)
    }


    override fun observeViewModel() {
        super.observeViewModel()
        orderTopViewModel.topInfoLD.observe(viewLifecycleOwner) { sessionTopData ->
            if (sessionTopData == null
                || (sessionTopData.pendingOrder == null && sessionTopData.skillList.isNullOrEmpty())
            ) {
                binding.vp.gone()
                binding.vpIndicator.gone()
                binding.vPendingOrder.gone()
                return@observe
            }
            if (sessionTopData.pendingOrder != null && !sessionTopData.pendingOrder.isComplete()) {
                if (sessionTopData.pendingOrder.buyerUserNo == ProfileModule.getMyUid()) {
                    binding.vp.show()
                    binding.vpIndicator.show()
                    binding.vPendingOrder.gone()
                    val itemList = mutableListOf<TopBarData>()
                    itemList.add(OrderTopItemData(sessionTopData.pendingOrder))
                    viewAdapter.setItemList(itemList, commited = { size ->
                        binding.vpIndicator.onPageChanged(size, 0)
                        binding.vpIndicator.show(size > 1)
                    })
                } else {
                    binding.vp.gone()
                    binding.vpIndicator.gone()
                    binding.vPendingOrder.show()
                    binding.vPendingOrder.setOrder(
                        sessionTopData.pendingOrder,
                        { order ->
                            refuse(order)
                        },
                        { order ->
                            accept(order)
                        }
                    )
                    binding.vPendingOrder.onClick {
                        goPlaymateOrderList()
                    }
                }
                return@observe
            }
            if (!sessionTopData.skillList.isNullOrEmpty()) {
                binding.vp.show()
                binding.vpIndicator.show()
                val itemList = mutableListOf<TopBarData>()
                itemList.addAll(sessionTopData.skillList.map {
                    SkillTopItemData(it)
                })
                viewAdapter.setItemList(
                    itemList,
                    firstCommit = {
                        val categoryCode =
                            activity?.intent?.getStringExtra(IM.Session.EXTRA_CHAT_PLAYMATE_ID)
                                ?: return@setItemList
                        val index = itemList.indexOfFirst {
                            it is SkillTopItemData && it.data.id == categoryCode
                        }
                        if (index >= 0) {
                            binding.vp.setCurrentItem(index)
                        }
                    },
                    commited = { size ->
                        binding.vpIndicator.onPageChanged(size, 0)
                        binding.vpIndicator.show(size > 1)
                    }
                )
                return@observe
            }
            //无内容,不展示顶部订单
            binding.vp.gone()
            binding.vpIndicator.gone()
            binding.vPendingOrder.gone()
        }
    }

    private fun refuse(order: OrderDetailInfo) {
        showLoading()
        orderViewModel?.refuse(order)?.observe(viewLifecycleOwner) {
            dismissLoading()
            orderTopViewModel.loadTopInfo()
        }
    }

    private fun accept(order: OrderDetailInfo) {
        showLoading()
        orderViewModel?.accept(order)?.observe(viewLifecycleOwner) {
            dismissLoading()
            orderTopViewModel.loadTopInfo()
        }
    }

    internal inner class PreviewViewHolder(val binding: LayoutSessionOrderTopBarContainerBinding) :
        RecyclePagerAdapter.PagerViewHolder(binding.root)

    internal inner class ViewAdapter : RecyclePagerAdapter<PreviewViewHolder>() {

        private val itemList = mutableListOf<TopBarData>()

        fun setItemList(
            list: List<TopBarData>,
            firstCommit: (() -> Unit)? = null,
            commited: ((itemSize: Int) -> Unit)? = null
        ) {
            val isFirstCommit = itemList.isEmpty()
            itemList.clear()
            itemList.addAll(list)
            notifyDataSetChanged()
            if (isFirstCommit) {
                firstCommit?.invoke()
            }
            commited?.invoke(list.size)
        }

        override fun getItemViewType(position: Int): Int {
            return itemList.getOrNull(position)?.viewType ?: INVALID_TYPE
        }

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

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PreviewViewHolder {
            val binding = LayoutSessionOrderTopBarContainerBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
            inflateContentView(binding.root, viewType)
            return PreviewViewHolder(binding)
        }

        private fun inflateContentView(parent: FrameLayout, viewType: Int) {
            parent.removeAllViews()
            val context = binding.root.context
            when (ViewType.map(viewType)) {
                ViewType.PLAYMATE_SKILL -> {
                    val view = SkillTopBarView(context)
                    view.id = R.id.id_session_order_top_bar_playmate_category
                    parent.addView(
                        view, FrameLayout.LayoutParams(
                            FrameLayout.LayoutParams.MATCH_PARENT,
                            FrameLayout.LayoutParams.MATCH_PARENT
                        )
                    )
                }

                ViewType.USER_ORDER -> {
                    val view = UserOrderTopBarView(context)
                    view.id = R.id.id_session_order_top_bar_user_order
                    view.setGoVoiceCallback(this@OrderTopBarFragment)
                    parent.addView(
                        view, FrameLayout.LayoutParams(
                            FrameLayout.LayoutParams.MATCH_PARENT,
                            FrameLayout.LayoutParams.MATCH_PARENT
                        )
                    )
                }
            }
        }

        override fun onBindViewHolder(holder: PreviewViewHolder, position: Int) {
            val data = itemList.getOrNull(position) ?: return
            when (ViewType.map(data.viewType)) {
                ViewType.PLAYMATE_SKILL -> {
                    holder.itemView.findViewById<SkillTopBarView>(R.id.id_session_order_top_bar_playmate_category)
                        .apply {
                            setPlaymateCategory((data as SkillTopItemData).data)
                            setOnOrderClick {
                                createOrder(it)
                            }
                        }
                }

                ViewType.USER_ORDER -> {
                    holder.itemView.findViewById<UserOrderTopBarView>(R.id.id_session_order_top_bar_user_order)
                        .apply {
                            setOrder((data as OrderTopItemData).data)
                            onClick {
                                goUserOrderList()
                            }
                        }
                }
            }
        }
    }

    private fun createOrder(data: UserPlaymateSkill) {
        val act = activity ?: return
        Router.getRouterInstance<BottomDialogFragment>(Order.CreateDialog.PATH)?.let {
            it.arguments = Bundle().apply {
                putString(Order.CreateDialog.EXTRA_PLAYMATE_ID, data.id)
                putBoolean(Order.CreateDialog.EXTRA_MODIFY, true)
                putBoolean(Order.CreateDialog.EXTRA_SHOW_REMARK, true)
            }
            it.show(act.supportFragmentManager)
        }
    }

    private fun goPlaymateOrderList() {
        val activity = activity ?: return
        Router.build(activity, Order.PlaymateList.PATH)
            .start()
    }

    private fun goUserOrderList() {
        val activity = activity ?: return
        Router.build(activity, Order.List.PATH)
            .start()
    }

    override fun goVoice() {
        val chatInfo = orderTopViewModel.getChatInfo() ?: return
        CallModule.call(chatInfo.id)
    }
}