package com.gh.gamecenter.feedback.view.suggest

import android.content.Intent
import android.database.Cursor
import android.os.Bundle
import android.provider.MediaStore
import android.text.Html
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.PopupWindow
import android.widget.TextView
import androidx.core.widget.doOnTextChanged
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.callback.OnListClickListener
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.databinding.ItemIconTabBinding
import com.gh.gamecenter.common.databinding.LayoutPopupContainerBinding
import com.gh.gamecenter.common.entity.NotificationUgc
import com.gh.gamecenter.common.entity.SuggestType
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.ImageUtils.getUploadFileMaxSize
import com.gh.gamecenter.common.utils.NotificationHelper.showNotificationHintDialog
import com.gh.gamecenter.common.view.BugFixedPopupWindow
import com.gh.gamecenter.common.view.choosepic.ChoosePicAdapter
import com.gh.gamecenter.core.AppExecutor.uiExecutor
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.feedback.R
import com.gh.gamecenter.feedback.databinding.FragmentSuggestAppBinding
import com.gh.gamecenter.feedback.databinding.LayoutOptionPopupBinding
import com.gh.gamecenter.feedback.entity.ContactType
import com.gh.gamecenter.feedback.entity.SuggestionProblem
import com.gh.gamecenter.feedback.utils.NewFlatLogUtils
import com.lightgame.utils.Utils
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.internal.utils.PathUtils
import java.io.File

/***
 * 意见反馈-App问题
 */
open class SuggestAppFragment : ToolbarFragment() {
    protected var mPicAdapter: ChoosePicAdapter? = null
    protected var mPopupWindow: PopupWindow? = null
    private lateinit var mBinding: FragmentSuggestAppBinding
    protected lateinit var mViewModel: SuggestViewModel
    protected var mPostDialog: WaitingDialogFragment? = null
    protected val mProblemTypeItemViewList = arrayListOf<View>()
    protected var mProblemTypeCheckedIndex = -1

    protected var mForceLogin = true
    protected var mSuggestContent = ""
    protected var mHiddenHint = ""
    protected var mSuggestHintType = ""
    protected var mDiagnosisResult = ""
    protected var mIsQaFeedback = false
    protected var mQaContentId = ""
    protected var mIsFromRating = false

    protected var mIsProblemTypeExpand = false
    protected var mIsSelectProblemExpand = false
    protected var mAgreePostPic = false
    protected var mIsBackConfirm = false

    protected val mUploadPicLayoutManager by lazy {
        object : LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false) {
            override fun canScrollHorizontally(): Boolean {
                return false
            }
        }
    }
    protected val mUploadPicListClickListener = object : OnListClickListener {
        override fun <T : Any?> onListClick(view: View?, position: Int, data: T) {
            if (!mAgreePostPic && !NetworkUtils.isWifiConnected(requireContext())) {
                mAgreePostPic = true
                DialogHelper.showDialog(
                    requireContext(),
                    "警告",
                    "当前使用移动网络，上传图片会消耗手机流量",
                    "我知道了", "", {
                        val picList = data as List<String>
                        if (position == mPicAdapter!!.itemCount - 1 && picList.size < 5) {
                            PermissionHelper.checkStoragePermissionBeforeAction(requireContext()) {
                                val intent = LocalMediaActivity.getIntent(
                                    requireContext(),
                                    ChooseType.IMAGE,
                                    1,
                                    "意见反馈-${getSuggestType()}"
                                )
                                startActivityForResult(
                                    intent,
                                    MEDIA_STORE_REQUEST
                                )
                            }
                        }
                    }, extraConfig = DialogHelper.Config(centerContent = true, centerTitle = true)
                )
                return
            }
            val picList = data as List<*>
            if (position == mPicAdapter!!.itemCount - 1 && picList.size < 5) {
                PermissionHelper.checkStoragePermissionBeforeAction(requireContext()) {
                    val intent = LocalMediaActivity.getIntent(
                        requireContext(),
                        ChooseType.IMAGE,
                        1,
                        "意见反馈-${getSuggestType()}"
                    )
                    startActivityForResult(intent, MEDIA_STORE_REQUEST)
                }
            }
        }
    }

    override fun getLayoutId(): Int = 0

    override fun getInflatedLayout(): View =
        FragmentSuggestAppBinding.inflate(layoutInflater, null, false).apply { mBinding = this }.root

    open fun getSuggestType(): String = SuggestType.APP.type

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mForceLogin = arguments?.getBoolean(EntranceConsts.KEY_FORCE_LOGIN, true) ?: true
        mSuggestContent = arguments?.getString(EntranceConsts.KEY_CONTENT) ?: ""
        mSuggestHintType = arguments?.getString(EntranceConsts.KEY_SUGGEST_HINT_TYPE) ?: ""
        mHiddenHint = arguments?.getString(EntranceConsts.KEY_HIDE_SUGGEST_HINT) ?: ""
        mDiagnosisResult = arguments?.getString(EntranceConsts.KEY_DIAGNOSIS) ?: ""
        mIsQaFeedback = arguments?.getBoolean(EntranceConsts.KEY_IS_QA_FEEDBACK, false) ?: false
        mQaContentId = arguments?.getString(EntranceConsts.KEY_QA_CONTENT_ID) ?: ""
        mIsFromRating = arguments?.getBoolean(KEY_FROM_RATING, false) ?: false

        (requireActivity() as ToolBarActivity).updateTargetFragment(this)
        mViewModel =
            viewModelProvider(
                SuggestViewModel.Factory(
                    getSuggestType(),
                    mHiddenHint,
                    mIsQaFeedback,
                    mQaContentId,
                    mIsFromRating
                )
            )
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        requireActivity().updateStatusBarColor(com.gh.gamecenter.common.R.color.ui_surface, com.gh.gamecenter.common.R.color.ui_surface)
        setNavigationTitle("意见反馈-${getSuggestType()}")
        initView()
        observerData()

        mViewModel.postSuccessLiveData.observeNonNull(this) {
            mPostDialog?.dismissAllowingStateLoss()
            if (it) {
                toast("感谢您的反馈！")
                requireActivity().finish()
                uiExecutor.executeWithDelay({
                    showNotificationHintDialog(
                        NotificationUgc.FEEDBACK,
                        null
                    )
                }, 1000)
            }
        }

        mViewModel.errorLiveData.observeNonNull(this) { error ->
            when (error.code) {
                403052 -> {
                    DialogHelper.showDialog(
                        requireContext(),
                        "提醒",
                        "你已经提交过相同的反馈了",
                        "关闭提交",
                        "返回修改",
                        confirmClickCallback = {
                            requireActivity().finish()
                        },
                        extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
                    )
                }

                403208 -> {
                    toast("您已经提交过反馈信息，我们将尽快处理~")
                    requireActivity().finish()
                }

                else -> {
                    toast("提交失败，请检查网络状态")
                }
            }
        }
    }

    protected open fun initView() {
        mBinding.run {
            problemType.titleTv.text = Html.fromHtml(getString(R.string.suggestion_problem_type))
            selectProblem.titleTv.text = "选择问题"
            problemDes.titleTv.text = Html.fromHtml(getString(R.string.suggestion_problem_des))

            problemType.expandIv.setOnClickListener {
                problemType.root.layoutParams = problemType.root.layoutParams.apply {
                    height = if (mIsProblemTypeExpand) 48F.dip2px() else LinearLayout.LayoutParams.WRAP_CONTENT
                }
                problemType.expandIv.rotation = if (mIsProblemTypeExpand) 0F else 180F
                mIsProblemTypeExpand = !mIsProblemTypeExpand
            }

            selectProblem.expandIv.setOnClickListener {
                selectProblem.root.layoutParams = selectProblem.root.layoutParams.apply {
                    height = if (mIsSelectProblemExpand) 48F.dip2px() else LinearLayout.LayoutParams.WRAP_CONTENT
                }
                selectProblem.expandIv.rotation = if (mIsSelectProblemExpand) 0F else 180F
                mIsSelectProblemExpand = !mIsSelectProblemExpand
            }

            problemDes.run {
                editText.doOnTextChanged { text, _, _, _ ->
                    val count = text?.count { !it.isWhitespace() } ?: 0
                    problemDes.countTv.text = "${count}/300"
                }
                if (mSuggestContent.isNotEmpty()) {
                    editText.setText(mSuggestContent)
                    editText.setSelection(editText.text.length)
                }
            }

            uploadPic.run {
                picRv.layoutManager = mUploadPicLayoutManager
                mPicAdapter = ChoosePicAdapter(requireContext(), mUploadPicListClickListener)
                picRv.adapter = mPicAdapter
            }

            contact.contactTv.setOnClickListener {
                showContactOptionPopup(it) { name ->
                    mViewModel.contactType = ContactType.getContactTypeByName(name)
                    contact.contactTv.text = name
                }
            }

            suggestPostBtn.setOnClickListener {
                val isSelectedProblemType = mViewModel.selectedProblemType != null
                val isProblemDesNotEmpty = problemDes.editText.text.trim().isNotEmpty()

                if (problemType.root.visibility == View.VISIBLE && !isSelectedProblemType) {
                    toast("请选择问题类型")
                    return@setOnClickListener
                }

                if (!isProblemDesNotEmpty) {
                    toast("请填写问题描述")
                    return@setOnClickListener
                }

                val postAction = {
                    var selectedProblem = ""
                    mViewModel.selectedProblemSet.forEachIndexed { index, problem ->
                        if (index == 0) {
                            selectedProblem = problem
                        } else {
                            selectedProblem += "+$problem"
                        }
                    }
                    NewFlatLogUtils.logFeedbackCommit(
                        getSuggestType(),
                        mViewModel.selectedProblemType?.name ?: "",
                        selectedProblem
                    )

                    mPostDialog = WaitingDialogFragment.newInstance(getString(R.string.dialog_feedback_doing))
                    mPostDialog?.show(childFragmentManager, null)

                    val fileList = mPicAdapter?.fileList
                    if (fileList.isNullOrEmpty()) {
                        mViewModel.postNormalSuggestion(
                            contact.contactEt.text.toString().trim(),
                            problemDes.editText.text.toString().trim(),
                            diagnosisResult = mDiagnosisResult
                        )
                    } else {
                        mViewModel.uploadPicAndPostNormalSuggestion(
                            fileList,
                            mPostDialog,
                            contact.contactEt.text.toString().trim(),
                            problemDes.editText.text.toString().trim(),
                            diagnosisResult = mDiagnosisResult
                        )
                    }
                }
                if (mForceLogin) {
                    ifLogin("意见反馈-${getSuggestType()}") {
                        postAction()
                    }
                } else {
                    postAction()
                }
            }
        }
    }

    protected open fun observerData() {
        mViewModel.problemTypeLiveData.observeNonNull(this) {
            mBinding.problemType.flexbox.removeAllViews()
            mProblemTypeItemViewList.clear()
            mBinding.problemType.root.goneIf(it.size < 2)
            it.forEachIndexed { index, problemType ->
                val item = getProblemTypeItemView(problemType)
                mProblemTypeItemViewList.add(item)
                mBinding.problemType.flexbox.addView(item)
                item.tag = problemType.name
                toggleHighlightedView(item, mViewModel.selectedProblemType?.id == problemType.id)
                item.setOnClickListener {
                    mProblemTypeCheckedIndex = if (mViewModel.selectedProblemType?.id == problemType.id) -1 else index
                    mViewModel.selectedProblemType =
                        if (mViewModel.selectedProblemType?.id == problemType.id) null else problemType
                    mViewModel.selectedProblemSet.clear()
                    toggleHighlightedView(item, mViewModel.selectedProblemType?.id == problemType.id)
                    for (view in mProblemTypeItemViewList) {
                        if (view != item) toggleHighlightedView(view, false)
                    }
                    mBinding.selectProblem.descTv.visibility = View.GONE
                    mViewModel.getProblemList()
                }
            }
            mBinding.problemType.flexbox.post {
                mBinding.problemType.expandIv.goneIf(mBinding.problemType.flexbox.flexLines.size < 2)
            }
        }

        mViewModel.problemLiveData.observeNonNull(this) {
            mBinding.selectProblem.flexbox.removeAllViews()
            it.forEach { problem ->
                val item = getProblemTypeItemView(problem)
                mBinding.selectProblem.flexbox.addView(item)
                item.tag = problem.name
                toggleHighlightedView(item, mViewModel.selectedProblemSet.contains(problem.id))
                item.setOnClickListener {
                    toggleHighlightedView(item, !mViewModel.selectedProblemSet.contains(problem.id))
                    mBinding.selectProblem.descTv.text = problem.remark
                    mBinding.selectProblem.descTv.goneIf(
                        problem.remark.isEmpty() || mViewModel.selectedProblemSet.contains(
                            problem.id
                        )
                    )
                    mBinding.selectProblem.root.layoutParams = mBinding.selectProblem.root.layoutParams.apply {
                        height =
                            if ((problem.remark.isNotEmpty() && !mViewModel.selectedProblemSet.contains(problem.id)) || mIsSelectProblemExpand)
                                LinearLayout.LayoutParams.WRAP_CONTENT
                            else
                                48F.dip2px()
                    }
                    if (mViewModel.selectedProblemSet.contains(problem.id)) {
                        mViewModel.selectedProblemSet.remove(problem.id)
                    } else {
                        mViewModel.selectedProblemSet.add(problem.id)
                    }
                }
            }
            mBinding.selectProblem.root.goneIf(it.isEmpty())
            mBinding.problemType.divider.goneIf(it.isNotEmpty())
            mBinding.selectProblem.flexbox.post {
                mBinding.selectProblem.expandIv.goneIf(mBinding.selectProblem.flexbox.flexLines.size < 2)
            }
        }
    }

    protected open fun getProblemTypeItemView(entity: SuggestionProblem): View {
        return ItemIconTabBinding.bind(
            LayoutInflater.from(requireContext()).inflate(com.gh.gamecenter.common.R.layout.item_icon_tab, null)
        ).apply {
            iconIv.visibility = View.GONE
            titleTv.text = entity.name
        }.root.apply {
            layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 28F.dip2px())
        }
    }

    protected open fun toggleHighlightedView(targetView: View, highlightIt: Boolean) {
        val titleTv = targetView.findViewById<TextView>(R.id.titleTv)
        if (highlightIt) {
            targetView.background = com.gh.gamecenter.common.R.drawable.button_round_theme_alpha_10.toDrawable(requireContext())
            titleTv?.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(requireContext()))
        } else {
            targetView.background = com.gh.gamecenter.feature.R.drawable.button_round_gray_light.toDrawable(requireContext())
            titleTv?.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
        }
    }

    protected fun showContactOptionPopup(view: View, callback: ((String) -> Unit)) {
        val inflater = LayoutInflater.from(view.context)
        val mainBinding = LayoutPopupContainerBinding.inflate(inflater)
        mPopupWindow = BugFixedPopupWindow(
            mainBinding.root,
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT
        )
        val windowPos = IntArray(2)
        val anchorLoc = IntArray(2)
        // 获取锚点View在屏幕上的左上角坐标位置
        view.getLocationOnScreen(anchorLoc)
        val anchorHeight = view.height
        // 获取屏幕的高宽
        val screenHeight = view.context.resources.displayMetrics.heightPixels
        mPopupWindow?.let { popupWindow ->
            // 测量contentView
            popupWindow.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
            val windowHeight = popupWindow.contentView.measuredHeight

            // 判断需要向上弹出还是向下弹出显示
            val isNeedShowUp = screenHeight - anchorLoc[1] - anchorHeight < windowHeight
            windowPos[1] = if (isNeedShowUp) {
                anchorLoc[1] - windowHeight
            } else anchorLoc[1] + anchorHeight

            LayoutOptionPopupBinding.inflate(inflater, mainBinding.container, false).apply {
                popupRv.adapter = OptionPopupAdapter(
                    root.context,
                    listOf(
                        ContactType.QQ.value,
                        ContactType.WECHAT.value,
                        ContactType.EMAIL.value,
                        ContactType.PHONE.value
                    )
                ) {
                    callback.invoke(it)
                    popupWindow.dismiss()
                }
                popupRv.layoutManager = LinearLayoutManager(root.context)
                mainBinding.container.addView(root)
            }

            popupWindow.isTouchable = true
            popupWindow.inputMethodMode = PopupWindow.INPUT_METHOD_NEEDED
            popupWindow.isOutsideTouchable = true
            popupWindow.animationStyle = com.gh.gamecenter.common.R.style.popwindow_option_anim_style

            // 设置偏移
            windowPos[0] = anchorLoc[0] - 3.5F.dip2px()
            windowPos[1] = windowPos[1] + 4F.dip2px()
            popupWindow.showAtLocation(view, Gravity.TOP or Gravity.START, windowPos[0], windowPos[1])
        }
    }

    protected open fun handleBackPressed(): Boolean {
        mBinding.run {
            if (mViewModel.selectedProblemType != null ||
                problemDes.editText.text.isNotEmpty() ||
                !mPicAdapter?.fileList.isNullOrEmpty() ||
                contact.contactEt.text.isNotEmpty()
            ) {
                DialogHelper.showDialog(
                    requireContext(), "提示",
                    "确定放弃反馈吗？", "继续反馈", "放弃", cancelClickCallback = {
                        mIsBackConfirm = true
                        requireActivity().onBackPressed()
                    }, extraConfig = DialogHelper.Config(centerContent = true, centerTitle = true)
                )
                return true
            } else {
                return false
            }
        }
    }

    override fun onBackPressed(): Boolean {
        return if (mIsBackConfirm || !handleBackPressed()) {
            (requireActivity() as ToolBarActivity).updateTargetFragment(null)
            val suggestionCategoryFragment =
                requireActivity().supportFragmentManager.findFragmentByTag(SuggestionCategoryFragment::class.java.name)
            if (suggestionCategoryFragment != null) {
                setNavigationTitle("意见反馈")
            }
            false
        } else true
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (data == null) return

        if (requestCode == MEDIA_STORE_REQUEST || requestCode == MEDIA_STORE_CREDENTIALS_REQUEST || requestCode == MEDIA_STORE_SCREENSHOT_REQUEST) {
            val selectedPaths = Matisse.obtainResult(data) ?: return
            val picturePath = PathUtils.getPath(requireContext(), selectedPaths[0])
            Utils.log("picturePath = $picturePath")
            val file = File(picturePath)
            if (file.length() > getUploadFileMaxSize()) {
                val count = getUploadFileMaxSize() / 1024 / 1024
                Utils.toast(requireContext(), getString(com.gh.gamecenter.common.R.string.pic_max_hint, count))
            } else {
                addFileList(requestCode, picturePath)
            }
        }
    }

    protected open fun addFileList(requestCode: Int, path: String) {
        if (requestCode == MEDIA_STORE_REQUEST) {
            mPicAdapter?.addFileList(path)
        }
    }

    override fun onDarkModeChanged() {
        for ((index, view) in mProblemTypeItemViewList.withIndex()) {
            toggleHighlightedView(view, index == mProblemTypeCheckedIndex)
        }
        for (i in 0 until mBinding.selectProblem.flexbox.childCount) {
            val problem = mViewModel.problemLiveData.value?.safelyGetInRelease(i) ?: return
            mBinding.selectProblem.flexbox.getChildAt(i)?.let {
                toggleHighlightedView(it, mViewModel.selectedProblemSet.contains(problem.id))
            }
        }
    }

    companion object {
        const val MEDIA_STORE_REQUEST = 1
        const val MEDIA_STORE_CREDENTIALS_REQUEST = 2
        const val MEDIA_STORE_SCREENSHOT_REQUEST = 3

        const val KEY_FROM_RATING = "from_rating"
    }
}