package com.gh.gamecenter.qa.questions.newdetail

import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.util.*
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.baselist.LoadType
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.syncpage.SyncDataEntity
import com.gh.gamecenter.common.syncpage.SyncFieldConstants
import com.gh.gamecenter.common.syncpage.SyncPageRepository
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.feature.entity.CommentEntity
import com.gh.gamecenter.eventbus.EBUserFollow
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.qa.article.detail.CommentItemData
import com.gh.gamecenter.qa.comment.base.BaseCommentViewModel
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
import com.google.gson.reflect.TypeToken
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONObject
import retrofit2.HttpException

class NewQuestionDetailViewModel(
    application: Application,
    questionId: String = "",
    communityId: String = "",
    val answerId: String = "",
    val recommendId: String = "",
    topCommentId: String = "",
) :
    BaseCommentViewModel(
        application,
        articleId = "",
        communityId = communityId,
        videoId = "",
        questionId = questionId,
        gameCollectionId = "",
        topCommentId = topCommentId
    ) {
    var questionRenderedLiveData = MutableLiveData<Boolean>()
    var questionPageFinishedLiveData = MutableLiveData<Boolean>()
    val moderatorsHideLiveData = MutableLiveData<Boolean>()
    val favoriteLiveData = MutableLiveData<Boolean>()
    val mFollowLiveData = MutableLiveData<Boolean>()
    val top = MutableLiveData<Boolean>()
    val updateDetailLiveData = MutableLiveData<QuestionsDetailEntity>()
    var questionDetail: QuestionsDetailEntity? = null
    val questionDetailLD = MutableLiveData<QuestionsDetailEntity>()
    val followLiveData = mFollowLiveData

    fun getQuestionDetail() {
        mApi.getQuestionsById(questionId)
            .compose(observableToMain())
            .subscribe(object : Response<QuestionsDetailEntity>() {
                override fun onResponse(response: QuestionsDetailEntity?) {
                    super.onResponse(response)
                    questionDetail = response
                    questionDetailLD.value = response
                    topItemData = CommentItemData(questionDetail = response)
                    commentCount = response?.count?.answer ?: 0
                    loadResultLiveData.postValue(LoadResult.SUCCESS)
                    mergeListData(mListLiveData.value)

                    NewLogUtils.logForumContentBrowser(questionId, "bbs_question", recommendId)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    if (e?.code().toString().startsWith("404")) {
                        loadResultLiveData.postValue(LoadResult.DELETED)
                    } else {
                        loadResultLiveData.postValue(LoadResult.NETWORK_ERROR)
                    }
                }
            })
    }

    override fun provideDataObservable(page: Int): Observable<MutableList<CommentEntity>>? {
        val map = hashMapOf<String, Any>()
        when {
            answerId.isNotEmpty() -> map["top_comment_id"] = answerId
            !isHandleTopComment && topCommentId.isNotEmpty() -> map["top_comment_id"] = topCommentId
        }
        return mApi.getQuestionComment(questionId, currentSortType.value, page, map)
            .map {
                mTotal = it.headers().get("total")?.toInt() ?: 0
                val type = object : TypeToken<List<CommentEntity>>() {}.type
                GsonUtils.gson.fromJson(it.body()?.toJson() ?: "", type)
            }
    }

    override fun mergeResultLiveData() {
        mResultLiveData.addSource(mListLiveData) { mergeListData(it) }
    }

    override fun hideCommentSuccess() {
        questionDetail?.count?.answer = (questionDetail?.count?.answer ?: 0) - 1
        loadResultLiveData.postValue(LoadResult.SUCCESS)
    }

    fun follow() {
        followingCommand(true, questionDetail?.user?.id!!)
    }

    fun unFollow() {
        followingCommand(false, questionDetail?.user?.id!!)
    }

    private fun followingCommand(isFollow: Boolean, targetUserId: String) {
        val observable = if (isFollow) {
            mApi.postFollowing(targetUserId)
        } else {
            mApi.deleteFollowing(targetUserId)
        }
        observable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    if (isFollow) {
                        // 关注成功
                        mFollowLiveData.postValue(true)
                    } else {
                        // 取消关注成功
                        mFollowLiveData.postValue(false)
                    }

                    SyncPageRepository.postSyncData(
                        SyncDataEntity(
                            questionDetail?.id ?: "",
                            SyncFieldConstants.IS_FOLLOWER,
                            isFollow,
                            checkFieldEntity = true
                        )
                    )
                    EventBus.getDefault().post(EBUserFollow(targetUserId, isFollow))
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    Utils.toast(getApplication(), com.gh.gamecenter.feature.R.string.loading_failed_hint)
                }
            })
    }

    fun moderatorsHideQuestion() {
        mApi.moderatorsHideQuestion(UserManager.getInstance().userId, questionId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    moderatorsHideLiveData.postValue(true)
                    mLoadStatusLiveData.value = LoadStatus.INIT_EMPTY
                }

                override fun onFailure(e: HttpException?) {
                    if (e != null && e.code() == 403) {
                        val string = e.response().errorBody()?.string()
                        val errorJson = JSONObject(string ?: "")
                        val errorCode = errorJson.getInt("code")
                        if (errorCode == 403059) {
                            Utils.toast(getApplication(), "权限错误，请刷新后重试")
                            load(LoadType.REFRESH)
                            return
                        }
                    }
                    Utils.toast(getApplication(), R.string.post_failure_hint)
                }
            })
    }

    @SuppressLint("CheckResult")
    fun postFavoriteQuestion() {
        if (questionDetail == null) return
        val single = if (questionDetail?.me?.isFavorite == true) {
            mApi.deleteFavoriteQuestion(UserManager.getInstance().userId, questionId)
        } else {
            mApi.favoriteQuestion(UserManager.getInstance().userId, questionId)
        }
        single.compose(singleToMain())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    if (questionDetail?.me?.isFavorite == true) {
                        ToastUtils.showToast("取消收藏")
                    } else {
                        ToastUtils.showToast("收藏成功")
                    }
                    questionDetail?.me?.isFavorite =
                        questionDetail?.me?.isFavorite != true
                    favoriteLiveData.postValue(true)
                }
            })
    }

    fun postSolveQuestion(isSolve: Boolean) {
        if (questionDetail == null) return
        val body = json { "finish" to isSolve }.toRequestBody()
        mApi.solveQuestion(questionDetail?.id ?: "", body)
            .compose(observableToMain())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    questionDetail?.apply {
                        finish = isSolve
                        updateDetailLiveData.postValue(this)
                    }
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    ToastUtils.showToast("操作失败")
                }
            })
    }

    fun topCommunityQuestion(topCategoryId: String) {
        questionDetail?.let { questionDetail ->
            mApi.topCommunityQuestion(
                questionDetail.id,
                mapOf(
                    "title" to questionDetail.title,
                    "top_category_id" to topCategoryId
                ).toRequestBody()
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : Response<ResponseBody>() {
                    override fun onResponse(response: ResponseBody?) {
                        getQuestionDetail()
                        top.postValue(true)
                    }
                })
        }

    }

    fun cancelTopCommunityQuestion() {
        questionDetail?.also {questionDetail ->
            questionDetail.top?.let { communityTop ->
                mApi.cancelTopCommunityQuestion(
                    questionDetail.id,
                    mapOf(
                        "question_top_id" to communityTop.id
                    ).toRequestBody()
                )
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : Response<ResponseBody>() {
                        override fun onResponse(response: ResponseBody?) {
                            getQuestionDetail()
                            top.postValue(false)
                        }
                    })
            }
        }

    }

    fun getFirstAnswer() = mListLiveData.value?.safelyGetInRelease(0)

    class Factory(
        private val application: Application,
        private val questionId: String = "",
        private val communityId: String = "",
        private val answerId: String = "",
        private val recommendId: String = "",
        private val topCommentId: String = ""
    ) : ViewModelProvider.NewInstanceFactory() {

        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return NewQuestionDetailViewModel(
                application = application,
                questionId = questionId,
                communityId = communityId,
                answerId = answerId,
                recommendId = recommendId,
                topCommentId = topCommentId
            ) as T
        }
    }
}