package com.dlc.exam.ui.exam

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.blankj.utilcode.util.LogUtils
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.dlc.exam.R
import com.dlc.exam.common.CommonUtils
import com.dlc.exam.common.ExamType
import com.dlc.exam.common.TopicType
import com.dlc.exam.databinding.FragmentExamBinding
import com.dlc.exam.ui.score.PaperQuViewModel
import com.dlc.exam.ui.score.TopicGroupInfo
import com.rc.core.ui.fragment.RcBaseFragment
import com.rc.httpcore.client.ApiRepository
import com.rc.httpcore.vo.request.PaperQuReq
import com.rc.httpcore.vo.response.ExamTopic

/**
 * info
 *
 * @author ReiChin_
 */
class ExamFragment : RcBaseFragment<FragmentExamBinding>() {

    companion object {
        const val FRAGMENT_TAG = "ExamFragment"

        fun newInstance(examType: String): ExamFragment {
            val args = Bundle()
            args.putString("examType", examType)
            val fragment = ExamFragment()
            fragment.arguments = args
            return fragment
        }
    }

    private val viewModel by lazy {
        ViewModelProvider(requireActivity(), ViewModelProvider.NewInstanceFactory()).get(
            PaperQuViewModel::class.java
        )
    }

    private var mExamFragmentCallback: ExamFragmentCallback? = null

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is ExamFragmentCallback) {
            this.mExamFragmentCallback = context
        }
    }

    override fun onDetach() {
        this.mExamFragmentCallback = null
        super.onDetach()
    }

    override fun createViewBinding(
        inflater: LayoutInflater,
        container: ViewGroup?
    ) = FragmentExamBinding.inflate(inflater, container, false)

    private val mRadioTopicAdapter by lazy { TopicNumberAdapter() }
    private val mMultiTopicAdapter by lazy { TopicNumberAdapter() }
    private val mJudgeTopicAdapter by lazy { TopicNumberAdapter() }

    private lateinit var mExamType: String

    private var mRemainingTimeSecond = 0

    private val mExamCountDownHandler = object : Handler(Looper.getMainLooper()) {

        override fun handleMessage(msg: Message) {
            mRemainingTimeSecond--
            if (mRemainingTimeSecond > 0) {
                viewModel.setRemainingTime(CommonUtils.formatExamTime(mRemainingTimeSecond))
                sendEmptyMessageDelayed(1, 1000)
            } else {
                viewModel.setRemainingTime("0分0秒")
                callExamEndApi()
            }
        }
    }

    override fun initViews(savedInstanceState: Bundle?) {
        val transaction = childFragmentManager.beginTransaction()
        transaction.add(
            R.id.topicContainer,
            ExamTopicFragment.newInstance(),
            ExamTopicFragment.FRAGMENT_TAG
        )
        transaction.commit()

        initRecycleView(mRadioTopicAdapter, viewBinding.radioTopicNumber)
        initRecycleView(mMultiTopicAdapter, viewBinding.multiTopicNumber)
        initRecycleView(mJudgeTopicAdapter, viewBinding.judgeTopicNumber)

        mExamType = requireArguments().getString("examType")!!
        viewBinding.modelName.text = ExamType.decodeDescByType(mExamType)

        viewBinding.radioTopicArrow.setOnClickListener {
            dispatchTopicArrowClicked(it as ImageView, viewBinding.radioTopicNumber)
        }
        viewBinding.multiTopicArrow.setOnClickListener {
            dispatchTopicArrowClicked(it as ImageView, viewBinding.multiTopicNumber)
        }
        viewBinding.judgeTopicArrow.setOnClickListener {
            dispatchTopicArrowClicked(it as ImageView, viewBinding.judgeTopicNumber)
        }
        // 交卷
        viewBinding.submitPaper.setOnClickListener {
            // 判断当前题目是否为多选题，如果是多选题，需要先提交多选题答案，再交卷
            val groupInfo = viewModel.groupInfoData.value
            if (groupInfo?.topicType?.type == TopicType.MULTI.type) {
                // 多选题：
                val fragment =
                    childFragmentManager.findFragmentByTag(ExamTopicFragment.FRAGMENT_TAG)
                            as? ExamTopicFragment
                // 1) 提交答案
                fragment?.onMultiSheetClick { sheetInx, answeredCnt ->
                    if (-1 != sheetInx) {
                        // 2) 更新答题卡
                        updateAnswerSheet(sheetInx, answeredCnt)
                    }
                    // 3) 交卷
                    callExamEndApi()
                }
            } else {
                // 单选/判断题：交卷
                callExamEndApi()
            }
        }

        viewModel.examTopicData.observe(viewLifecycleOwner) { data ->
            LogUtils.json(data)
            mRemainingTimeSecond = data.totalTime * 60
            mExamCountDownHandler.sendEmptyMessageDelayed(1, 1000)
            viewModel.setRemainingTime("${data.totalTime}分")

            updateViews(data)
        }

        viewModel.examExamAnswerData.observe(viewLifecycleOwner) { data ->
            // 用户提交答案后回调
            if (data.answered) {
                updateAnswerSheet(data.sheetInx, data.answeredCnt)
            }
            dispatchNextTopic(data.nextIdx)
        }
    }

    /**
     * 交卷
     */
    private fun callExamEndApi() {
        mExamFragmentCallback?.submitExam(false)
    }

    /**
     * 提交答案后，自动跳转到下一题
     */
    private fun dispatchNextTopic(nextIdx: Int) {
        // 题目总数
        val radioSize = mRadioTopicAdapter.data.size
        val multiSize = mMultiTopicAdapter.data.size
        val judgeSize = mJudgeTopicAdapter.data.size
        val topicTotal = radioSize + multiSize + judgeSize
        if (nextIdx < 0 || nextIdx >= topicTotal) return

        if (nextIdx < radioSize) {
            // 单选题
            val item = mRadioTopicAdapter.data[nextIdx]
            // 切换到下一题
            changeTopic(item, nextIdx, topicTotal)
            viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.RADIO, radioSize, nextIdx + 1))
        } else if (nextIdx < radioSize + multiSize) {
            // 多选题
            val item = mMultiTopicAdapter.data[nextIdx - radioSize]
            // 切换到下一题
            changeTopic(item, nextIdx, topicTotal)
            viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.MULTI, multiSize, nextIdx + 1))
        } else if (nextIdx < topicTotal) {
            // 判断题
            val item = mJudgeTopicAdapter.data[nextIdx - radioSize - multiSize]
            // 切换到下一题
            changeTopic(item, nextIdx, topicTotal)
            viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.JUDGE, judgeSize, nextIdx + 1))
        }
    }

    /**
     * 更新答题卡
     *
     * @param index 当前题目编号，从0开始
     * @param answeredCnt 已答题目数
     */
    private fun updateAnswerSheet(index: Int, answeredCnt: Int) {
        // 题目总数
        val radioSize = mRadioTopicAdapter.data.size
        val multiSize = mMultiTopicAdapter.data.size
        val judgeSize = mJudgeTopicAdapter.data.size
        val topicTotal = radioSize + multiSize + judgeSize
        updateAnsweredProgress(answeredCnt, topicTotal)

        if (index < 0 || index >= topicTotal) return

        if (index < radioSize) {
            // 单选题
            val item = mRadioTopicAdapter.data[index]
            // 当前题目已答
//            item.answered = "1"
            item.answered = true
            mRadioTopicAdapter.notifyDataSetChanged()
        } else if (index < radioSize + multiSize) {
            // 多选题
            val item = mMultiTopicAdapter.data[index - radioSize]
            // 当前题目已答
//            item.answered = "1"
            item.answered = true
            mMultiTopicAdapter.notifyDataSetChanged()
        } else if (index < topicTotal) {
            // 判断题
            val item = mJudgeTopicAdapter.data[index - radioSize - multiSize]
            // 当前题目已答
//            item.answered = "1"
            item.answered = true
            mJudgeTopicAdapter.notifyDataSetChanged()
        }
    }

    private fun changeTopic(item: ExamTopic.ElPaperQu, index: Int, topicTotal: Int) {
        mRadioTopicAdapter.selectItemId = item.id
        mRadioTopicAdapter.notifyDataSetChanged()
        mMultiTopicAdapter.selectItemId = item.id
        mMultiTopicAdapter.notifyDataSetChanged()
        mJudgeTopicAdapter.selectItemId = item.id
        mJudgeTopicAdapter.notifyDataSetChanged()
        queryPaperQuDetail(index + 1, topicTotal, item.paperId, item.quId)
    }

    private fun initRecycleView(numberAdapter: TopicNumberAdapter, recyclerView: RecyclerView) {
        numberAdapter.setOnItemClickListener { adapter, _, position ->
            // 答题卡点击了， 判断点击前的题目是否为多选题
            val groupInfo = viewModel.groupInfoData.value
            if (groupInfo?.topicType?.type == TopicType.MULTI.type) {
                // 多选题：
                val fragment =
                    childFragmentManager.findFragmentByTag(ExamTopicFragment.FRAGMENT_TAG)
                            as? ExamTopicFragment
                // 1) 提交答案
                fragment?.onMultiSheetClick { sheetInx, answeredCnt ->
                    if (-1 != sheetInx) {
                        // 2) 更新答题卡
                        updateAnswerSheet(sheetInx, answeredCnt)
                    }
                    // 3) 处理答题卡点击-切换题目
                    dispatchSheetClicked(position, adapter as TopicNumberAdapter)
                }
            } else {
                // 单选/判断题：处理答题卡点击-切换题目
                dispatchSheetClicked(position, adapter as TopicNumberAdapter)
            }
        }
        recyclerView.layoutManager = GridLayoutManager(requireContext(), 5)
        recyclerView.adapter = numberAdapter
    }

    private fun dispatchSheetClicked(position: Int, adapter: TopicNumberAdapter) {
        val item = adapter.getItem(position)
        mRadioTopicAdapter.selectItemId = item.id
        mRadioTopicAdapter.notifyDataSetChanged()
        mMultiTopicAdapter.selectItemId = item.id
        mMultiTopicAdapter.notifyDataSetChanged()
        mJudgeTopicAdapter.selectItemId = item.id
        mJudgeTopicAdapter.notifyDataSetChanged()

        val topicIdx = adapter.indexOffsite + position + 1
        val radioSize = mRadioTopicAdapter.data.size
        val multiSize = mMultiTopicAdapter.data.size
        val judgeSize = mJudgeTopicAdapter.data.size
        val topicTotal = radioSize + multiSize + judgeSize
        queryPaperQuDetail(topicIdx, topicTotal, item.paperId, item.quId)

        if (adapter == mRadioTopicAdapter) {
            viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.RADIO, radioSize, topicIdx))
        } else if (adapter == mMultiTopicAdapter) {
            viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.MULTI, multiSize, topicIdx))
        } else if (adapter == mJudgeTopicAdapter) {
            viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.JUDGE, judgeSize, topicIdx))
        }
    }

    private fun queryPaperQuDetail(
        currentNum: Int,
        topicTotal: Int,
        paperId: String?,
        quId: String?
    ) {
        showLoading("查询中...")
        val param = PaperQuReq()
        param.paperId = paperId
        param.quId = quId
        val disposable = ApiRepository.paperExamQuDetail(param)
            .subscribe({
                dismissLoading()
                it.currentNum = currentNum
                it.topicTotal = topicTotal
                viewModel.setPaperQu(it)
            }, { throwable ->
                dismissLoading()
                val data = ExamTopic.ElPaperQu()
                data.currentNum = currentNum
                data.topicTotal = topicTotal
                viewModel.setPaperQu(data)
                throwable.printStackTrace()
                showNetError(throwable)
            })
        addDisposable(disposable)
    }

    private fun dispatchTopicArrowClicked(target: ImageView, recyclerView: RecyclerView) {
        // 是否为展开状态
        val isSpread = target.tag as? Boolean ?: true
        if (isSpread) {
            // 展开状态，点击后变为折叠状态
            recyclerView.visibility = View.GONE
            target.setImageResource(R.mipmap.icon_ksxt_zk)
        } else {
            // 折叠状态，点击后变为展开状态
            recyclerView.visibility = View.VISIBLE
            target.setImageResource(R.mipmap.icon_ksxt_sq)
        }
        target.tag = !isSpread
    }

    @SuppressLint("SetTextI18n")
    private fun updateViews(data: ExamTopic) {
        viewBinding.examName.text = data.title

        val topicTotal = data.radioList.size + data.multiList.size + data.judgeList.size
        updateAnsweredProgress(0, topicTotal)

        var firstSelectItem: ExamTopic.ElPaperQu? = null
        if (data.radioList.isNullOrEmpty()) {
            viewBinding.radioTopicGroup.visibility = View.GONE
            viewBinding.radioTopicNumber.visibility = View.GONE
        } else {
            viewBinding.radioTopicGroup.visibility = View.VISIBLE
            viewBinding.radioTopicNumber.visibility = View.VISIBLE
            viewBinding.radioTopicScore.text = "(分值${data.examConfig.radioSumScore})"
            firstSelectItem = data.radioList[0]
            mRadioTopicAdapter.selectItemId = firstSelectItem.id
            mRadioTopicAdapter.setNewInstance(data.radioList)
            viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.RADIO, data.radioList.size))
        }

        if (data.multiList.isNullOrEmpty()) {
            viewBinding.multiTopicGroup.visibility = View.GONE
            viewBinding.multiTopicNumber.visibility = View.GONE
        } else {
            viewBinding.multiTopicGroup.visibility = View.VISIBLE
            viewBinding.multiTopicNumber.visibility = View.VISIBLE
            viewBinding.multiTopicScore.text = "(分值${data.examConfig.multiSumScore})"
            if (null == firstSelectItem) {
                firstSelectItem = data.multiList[0]
                viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.MULTI, data.multiList.size))
            }
            mMultiTopicAdapter.selectItemId = firstSelectItem!!.id
            mMultiTopicAdapter.indexOffsite = data.radioList.size
            mMultiTopicAdapter.setNewInstance(data.multiList)
        }

        if (data.judgeList.isNullOrEmpty()) {
            viewBinding.judgeTopicGroup.visibility = View.GONE
            viewBinding.judgeTopicNumber.visibility = View.GONE
        } else {
            viewBinding.judgeTopicGroup.visibility = View.VISIBLE
            viewBinding.judgeTopicNumber.visibility = View.VISIBLE
            viewBinding.judgeTopicScore.text = "(分值${data.examConfig.judgeSumScore})"
            if (null == firstSelectItem) {
                firstSelectItem = data.judgeList[0]
                viewModel.setTopicGroupInfo(TopicGroupInfo(TopicType.JUDGE, data.multiList.size))
            }
            mJudgeTopicAdapter.selectItemId = firstSelectItem!!.id
            mJudgeTopicAdapter.indexOffsite = data.radioList.size + data.multiList.size
            mJudgeTopicAdapter.setNewInstance(data.judgeList)
        }

        firstSelectItem?.let { firstItem ->
            queryPaperQuDetail(1, topicTotal, firstItem.paperId, firstItem.quId)
        }
    }

    @SuppressLint("SetTextI18n")
    private fun updateAnsweredProgress(answered: Int, topicTotal: Int) {
        viewBinding.currentTopic.text = "${answered}/${topicTotal}"
    }

}

private class TopicNumberAdapter :
    BaseQuickAdapter<ExamTopic.ElPaperQu, BaseViewHolder>(R.layout.item_topic_number) {

    var indexOffsite = 0

    var selectItemId: String? = null

    @SuppressLint("SetTextI18n")
    override fun convert(holder: BaseViewHolder, item: ExamTopic.ElPaperQu) {
        val itemView = holder.itemView as TextView
        itemView.text = "${indexOffsite + holder.adapterPosition + 1}"
        itemView.setBackgroundResource(itemBgResource(item.answered, item.id))
    }

    private fun itemBgResource(answered: Boolean, id: String): Int {
//        return if (answered) {
//            R.drawable.circle_radius_10_blue_20p
//        } else {
//            when (id) {
//                selectItemId ->
//                    R.drawable.circle_radius_10_blue
//                else -> R.drawable.circle_radius_10_a2
//            }
//        }
        return when {
            id == selectItemId ->
                R.drawable.circle_radius_10_blue
//            "1" == answered ->
            answered ->
                R.drawable.circle_radius_10_blue_20p

            else ->
                R.drawable.circle_radius_10_a2
        }
    }

}
