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

import android.annotation.SuppressLint
import android.app.Application
import android.os.Build
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.therouter.TheRouter
import com.gh.gamecenter.common.BuildConfig
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.constant.Config
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.common.entity.SuggestType
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.exposure.meta.MetaUtil.getBase64EncodedIMEI
import com.gh.gamecenter.common.json.json
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.UploadImageUtils
import com.gh.gamecenter.common.utils.UploadImageUtils.OnUploadImageListCountListener
import com.gh.gamecenter.common.utils.observableToMain
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
import com.gh.gamecenter.core.utils.GsonUtils.fromJson
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.feedback.HaloApp
import com.gh.gamecenter.feedback.R
import com.gh.gamecenter.feedback.entity.ContactType
import com.gh.gamecenter.feedback.entity.SuggestionProblem
import com.gh.gamecenter.feedback.retrofit.RetrofitManager
import com.lightgame.utils.Utils
import okhttp3.ResponseBody
import org.json.JSONArray
import org.json.JSONObject
import retrofit2.HttpException

class SuggestViewModel(
    application: Application,
    private val mSuggestType: String,
    private val mHiddenHint: String,
    private val mIsQaFeedback: Boolean,
    private val mQaContentId: String,
    private val mIsFromRating: Boolean
) : AndroidViewModel(application) {
    private val mApi = RetrofitManager.getInstance().api
    val problemTypeLiveData = MutableLiveData<List<SuggestionProblem>>()
    val problemLiveData = MutableLiveData<List<SuggestionProblem>>()
    val postSuccessLiveData = MutableLiveData<Boolean>()
    val errorLiveData = MutableLiveData<ErrorEntity>()

    var selectedProblemType: SuggestionProblem? = null
    var selectedProblemSet = HashSet<String>()
    var contactType = ContactType.QQ
    var copyrightIdentity = COPYRIGHT_IDENTITY_PERSON
    var selectedGameName = ""
    var selectedGameInfo = ""

    private val mCredentialsPathList = arrayListOf<String>()
    private val mScreenshotPathList = arrayListOf<String>()

    init {
        if (mSuggestType != SuggestType.COPYRIGHT.type) {
            getProblemTypeList()
        }
    }

    @SuppressLint("CheckResult")
    fun getProblemTypeList() {
        val filterQuery = UrlFilterUtils.getFilterQuery("suggestion_type", mSuggestType)
        mApi.getSuggestionProblemType(filterQuery)
            .compose(singleToMain())
            .subscribe(object : BiResponse<List<SuggestionProblem>>() {
                override fun onSuccess(data: List<SuggestionProblem>) {
                    // 问题类型和问题都为最多显示9个
                    problemTypeLiveData.postValue(data.take(MAX_PROBLEM_COUNT))
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    Utils.toast(getApplication(), "网络异常")
                }
            })
    }

    @SuppressLint("CheckResult")
    fun getProblemList() {
        if (selectedProblemType == null) {
            problemLiveData.postValue(emptyList())
        } else {
            val filterQuery = UrlFilterUtils.getFilterQuery("type_id", selectedProblemType?.id)
            mApi.getSuggestionProblem(filterQuery)
                .compose(singleToMain())
                .subscribe(object : BiResponse<List<SuggestionProblem>>() {
                    override fun onSuccess(data: List<SuggestionProblem>) {
                        // 问题类型和问题都为最多显示9个
                        problemLiveData.postValue(data.take(MAX_PROBLEM_COUNT))
                    }

                    override fun onFailure(exception: Exception) {
                        super.onFailure(exception)
                        Utils.toast(getApplication(), "网络异常")
                    }
                })
        }
    }

    fun uploadPicAndPostNormalSuggestion(
        fileList: List<String>,
        postDialog: WaitingDialogFragment?,
        contact: String = "",
        content: String = "",
        downloadLink: String = "",
        diagnosisResult: String = ""
    ) {
        UploadImageUtils.compressAndUploadImageList(
            UploadImageUtils.UploadType.suggestion,
            fileList,
            false,
            object : UploadImageUtils.OnUploadImageListListener {
                override fun onCompressSuccess(imageUrls: List<String>) {}
                override fun onProgress(total: Long, progress: Long) {
                    var percent = (100 * (progress / total.toFloat())).toInt()
                    if (percent >= 100) percent = 99
                    postDialog?.uploadWaitingHint("图片上传中 $percent%")
                }

                override fun onSingleSuccess(imageUrlMap: Map<String, String>) {
                    // do nothing
                }

                override fun onSuccess(imageUrlMap: LinkedHashMap<String, String>, errorMap: Map<String, Exception>) {
                    Utils.log("意见反馈:图片上传完成")
                    val picArray = JSONArray()
                    for (entry in imageUrlMap) {
                        picArray.put(entry.value)
                    }

                    postNormalSuggestion(contact, content, downloadLink, picArray, diagnosisResult)
                }

                override fun onError(errorMap: Map<String, Exception>) {
                    postDialog?.dismissAllowingStateLoss()
                    Utils.toast(getApplication(), "上传失败")
                    Utils.log("意见反馈:图片上传失败")
                }
            })
    }

    fun postNormalSuggestion(
        contact: String = "",
        content: String = "",
        downloadLink: String = "",
        picArray: JSONArray? = null,
        diagnosisResult: String = ""
    ) {
        val packageUtilsConfig = TheRouter.get(IPackageUtilsProvider::class.java)
        val appProvider = TheRouter.get(IAppProvider::class.java)

        val suggestType = if (mIsFromRating) {
            "$mSuggestType（评论）"
        } else if (diagnosisResult.isNotEmpty()) {
            "网络诊断"
        } else if (mHiddenHint.contains("APP闪退")) {
            "APP闪退"
        } else if (mIsQaFeedback) {
            "QA反馈"
        } else mSuggestType

        val message = when (mSuggestType) {
            SuggestType.APP.type -> {
                if (mHiddenHint.contains("APP闪退") && BuildConfig.BUILD_TIME != 0L) {
                    "$mHiddenHint$content [此闪退基于" + BuildConfig.BUILD_TIME + "测试包]"
                } else {
                    "$mHiddenHint$content"
                }
            }

            SuggestType.GAME.type -> {
                if (mIsQaFeedback && mQaContentId.isNotEmpty()) {
                    val gameName = appProvider?.get(Constants.GAME_NAME, false) as? String
                    if (gameName.isNullOrEmpty()) {
                        "【游戏问题】$mQaContentId；$selectedGameName，$content"
                    } else {
                        //https://git.shanqu.cc/pm/halo/halo-app-issues/-/issues/1928 第4点
                        "【来自：$gameName-游戏问题】$mQaContentId；$selectedGameName，$content"
                    }
                } else {
                    "$mHiddenHint$selectedGameName，$content"
                }
            }

            SuggestType.FUNCTION.type -> "$mHiddenHint$selectedGameInfo，$content"
            SuggestType.UPDATE.type -> "$mHiddenHint$selectedGameInfo，$content"
            else -> "$mHiddenHint$content"
        }

        val jsonObject = json {
            "ghversion" to packageUtilsConfig?.getGhVersionName()
            "channel" to appProvider?.getChannel()
            "type" to Build.MODEL
            "sdk" to Build.VERSION.SDK_INT.toString()
            "version" to Build.VERSION.RELEASE
            "source" to getApplication<Application>().getString(R.string.app_name)
            "jnfj" to getBase64EncodedIMEI()
            "manufacturer" to Build.MANUFACTURER
            "rom" to MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName
            "suggestion_type" to suggestType
            "from" to contact
            "contact_func" to contactType.value
            "message" to message
            "problem" to json {
                "type" to selectedProblemType?.id
                if (selectedProblemSet.isNotEmpty()) {
                    "subtype" to JSONArray(selectedProblemSet)
                }
            }
            if (downloadLink.isNotEmpty()) {
                "link" to downloadLink
            }
            if (picArray != null) {
                "screenshots" to picArray
            }
            if (diagnosisResult.isNotEmpty()) {
                "log" to diagnosisResult
            }
            if (mHiddenHint.contains("APP闪退")) {
                "log" to Config.getExceptionMsg()
            }
        }
        if (mHiddenHint.contains("APP闪退")) {
            Config.setExceptionMsg(null)
            Config.updateContainsErrorMsg(false)
        }

        sendSuggestion(jsonObject)
    }

    fun uploadPicAndPostCopyrightSuggestion(
        credentialsFileList: List<String>,
        screenshotsFileList: List<String>,
        postDialog: WaitingDialogFragment?,
        contact: String = "",
        content: String = "",
        appName: String = "",
        credentials: String = "",
        isCredentialsPic: Boolean = true
    ) {
        UploadImageUtils.uploadImageListOneByOne(UploadImageUtils.UploadType.suggestion,
            if (isCredentialsPic) credentialsFileList else screenshotsFileList,
            false, object : OnUploadImageListCountListener {
                override fun onSuccess(map: Map<String, String>) {
                    for (entry in map) {
                        if (isCredentialsPic) {
                            mCredentialsPathList.add(entry.value)
                        } else {
                            mScreenshotPathList.add(entry.value)
                        }
                    }
                }

                override fun onFinish() {
                    if (isCredentialsPic) {
                        uploadPicAndPostCopyrightSuggestion(
                            credentialsFileList,
                            screenshotsFileList,
                            postDialog,
                            contact,
                            content,
                            appName,
                            credentials,
                            false
                        )
                    } else {
                        postCopyrightSuggestion(
                            contact,
                            content,
                            appName,
                            credentials,
                            JSONArray(mCredentialsPathList),
                            JSONArray(mScreenshotPathList)
                        )
                    }
                }

                override fun onError() {
                    postDialog?.dismissAllowingStateLoss()
                    mCredentialsPathList.clear()
                    mScreenshotPathList.clear()
                    Utils.toast(getApplication(), "上传失败")
                    Utils.log("意见反馈:图片上传失败")
                }
            })
    }

    fun postCopyrightSuggestion(
        contact: String = "",
        content: String = "",
        appName: String = "",
        credentials: String = "",
        credentialsPicArray: JSONArray?,
        screenshotsPicArray: JSONArray?
    ) {
        val packageUtilsConfig = TheRouter.get(IPackageUtilsProvider::class.java)
        val appProvider = TheRouter.get(IAppProvider::class.java)

        val jsonObject = json {
            "ghversion" to packageUtilsConfig?.getGhVersionName()
            "channel" to appProvider?.getChannel()
            "type" to Build.MODEL
            "sdk" to Build.VERSION.SDK_INT.toString()
            "version" to Build.VERSION.RELEASE
            "source" to getApplication<Application>().getString(R.string.app_name)
            "jnfj" to getBase64EncodedIMEI()
            "manufacturer" to Build.MANUFACTURER
            "rom" to MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName
            "suggestion_type" to mSuggestType
            "app_name" to appName
            "owner_type" to copyrightIdentity
            "owner_card" to credentials
            "from" to contact
            "contact_func" to contactType.value
            "message" to content
            if (credentialsPicArray != null) {
                "certificates" to credentialsPicArray
            }
            if (screenshotsPicArray != null) {
                "screenshots" to screenshotsPicArray
            }
        }

        sendSuggestion(jsonObject)
    }

    private fun sendSuggestion(jsonObject: JSONObject) {
        mApi.postSuggestion(jsonObject.toRequestBody())
            .compose(observableToMain())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    postSuccessLiveData.postValue(true)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    postSuccessLiveData.postValue(false)
                    try {
                        e?.let {
                            val string = e.response().errorBody()?.string() ?: return@let
                            val error = fromJson(string, ErrorEntity::class.java)
                            errorLiveData.postValue(error)
                        }
                    } catch (e1: Exception) {
                        e1.printStackTrace()
                        Utils.toast(getApplication(), "提交失败，请检查网络状态")
                    }
                }
            })
    }


    companion object {
        const val MAX_PROBLEM_COUNT = 9

        const val COPYRIGHT_IDENTITY_PERSON = "person"
        const val COPYRIGHT_IDENTITY_COMPANY = "company"
    }

    class Factory(
        private val mSuggestType: String,
        private val mHiddenHint: String,
        private val mIsQaFeedback: Boolean,
        private val mQaContentId: String,
        private val mIsFromRating: Boolean
    ) : ViewModelProvider.NewInstanceFactory() {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return SuggestViewModel(
                HaloApp.getInstance(),
                mSuggestType,
                mHiddenHint,
                mIsQaFeedback,
                mQaContentId,
                mIsFromRating
            ) as T
        }
    }
}