package com.gh.gamecenter.qa.answer.detail

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.common.history.HistoryHelper
import com.gh.common.util.CollectionUtils
import com.gh.common.util.ErrorHelper
import com.gh.common.util.LogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.retrofit.ApiResponse
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.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.entity.SpecialColumn
import com.gh.gamecenter.entity.VoteEntity
import com.gh.gamecenter.eventbus.EBUserFollow
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONObject
import retrofit2.HttpException

class AnswerDetailViewModel(application: Application) : AndroidViewModel(application) {

    private val mAnswerLiveData = MutableLiveData<ApiResponse<AnswerDetailEntity>>()
    private val mVoteLiveData = MutableLiveData<ApiResponse<VoteEntity>>()
    private val mFollowLiveData = MutableLiveData<Boolean>()

    val highlight = MutableLiveData<Boolean>()
    val hide = MutableLiveData<Boolean>()
    val fold = MutableLiveData<Boolean>()
    val commentable = MutableLiveData<Boolean>()
    val dislike = MutableLiveData<Boolean>()
    val collect = MutableLiveData<Boolean>()

    var answerDetail: AnswerDetailEntity? = null

    val answerLiveData: LiveData<ApiResponse<AnswerDetailEntity>>
        get() = mAnswerLiveData

    val voteLiveData: LiveData<ApiResponse<VoteEntity>>
        get() = mVoteLiveData

    val followLiveData: LiveData<Boolean>
        get() = mFollowLiveData

    fun getAnswerDetail(answerId: String) {
        RetrofitManager.getInstance().api
            .getAnswerDetail(answerId, Utils.getTime(getApplication()))
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<AnswerDetailEntity>() {
                override fun onResponse(response: AnswerDetailEntity?) {
                    val apiResponse = ApiResponse<AnswerDetailEntity>()
                    answerDetail = response
                    apiResponse.data = response
                    mAnswerLiveData.postValue(apiResponse)
                }

                override fun onFailure(e: HttpException?) {
                    val apiResponse = ApiResponse<AnswerDetailEntity>()
                    apiResponse.httpException = e
                    mAnswerLiveData.postValue(apiResponse)
                }
            })
    }

    fun like(answerId: String) {
        RetrofitManager.getInstance().api
            .postAnswerVote(answerId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<VoteEntity>() {
                override fun onResponse(response: VoteEntity?) {
                    // 赞同加一
                    answerDetail?.me?.isAnswerVoted = true
                    answerDetail!!.vote++

                    answerDetail?.me?.isAnswerOpposed = false

                    val apiResponse = ApiResponse<VoteEntity>()
                    apiResponse.data = response
                    mVoteLiveData.postValue(apiResponse)

                    syncVoteData(answerId)
                }

                override fun onFailure(e: HttpException?) {
                    val apiResponse = ApiResponse<VoteEntity>()
                    apiResponse.httpException = e
                    mVoteLiveData.postValue(apiResponse)
                }
            })
    }

    fun cancelLike(answerId: String) {
        RetrofitManager.getInstance().api
            .postAnswerUnvote(answerId)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<VoteEntity>() {
                override fun onResponse(response: VoteEntity?) {
                    // 赞同减一
                    answerDetail?.me?.isAnswerVoted = false
                    answerDetail!!.vote--

                    val apiResponse = ApiResponse<VoteEntity>()
                    apiResponse.data = response
                    mVoteLiveData.postValue(apiResponse)

                    syncVoteData(answerId)
                }

                override fun onFailure(e: HttpException?) {
                    val apiResponse = ApiResponse<VoteEntity>()
                    apiResponse.httpException = e
                    mVoteLiveData.postValue(apiResponse)
                }
            })
    }

    fun dislike(answerId: String) {
        RetrofitManager.getInstance().api
            .postAnswerOppose(answerId)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    if (answerDetail?.me?.isAnswerVoted == true) {
                        answerDetail!!.vote--
                    }
                    answerDetail?.me?.isAnswerOpposed = true
                    answerDetail?.me?.isAnswerVoted = false

                    dislike.postValue(true)

                    syncVoteData(answerId)
                }

                override fun onFailure(e: HttpException?) {
                    ErrorHelper.handleError(getApplication(), e?.response()?.errorBody()?.string())
                }
            })
    }

    fun cancelDislike(answerId: String) {
        RetrofitManager.getInstance().api
            .postAnswerUnoppose(answerId)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    answerDetail?.me?.isAnswerOpposed = false
                    dislike.postValue(false)

                    syncVoteData(answerId)
                }

                override fun onFailure(e: HttpException?) {
                    ErrorHelper.handleError(getApplication(), e?.response()?.errorBody()?.string())
                }
            })
    }

    private fun syncVoteData(answerId: String) {
        SyncPageRepository.postSyncData(
            SyncDataEntity(
                answerId,
                SyncFieldConstants.ANSWER_VOTE_COUNT,
                answerDetail!!.vote
            )
        )
        SyncPageRepository.postSyncData(
            SyncDataEntity(
                answerId,
                SyncFieldConstants.ANSWER_VOTE,
                answerDetail?.me?.isAnswerVoted,
                checkFieldEntity = true
            )
        )
    }

    fun collectAnswer(answerId: String) {
        CollectionUtils.postCollection(
            answerId,
            CollectionUtils.CollectionType.ANSWER,
            object : CollectionUtils.OnCollectionListener {
                override fun onSuccess() {
                    collect.postValue(true)
                    answerDetail?.me?.isAnswerFavorite = true
                }

                override fun onError() {
                    Utils.toast(getApplication(), R.string.collection_failure)
                }
            })
    }

    fun cancelCollectAnswer(answerId: String) {
        CollectionUtils.deleteCollection(
            answerId,
            CollectionUtils.CollectionType.ANSWER,
            object : CollectionUtils.OnCollectionListener {
                override fun onSuccess() {
                    collect.postValue(false)
                    answerDetail?.me?.isAnswerFavorite = false
                }

                override fun onError() {
                    Utils.toast(getApplication(), R.string.collection_cancel_failure)
                }
            })
    }

    fun follow(userId: String) {
        followingCommand(true, userId)
    }

    fun unfollow(userId: String) {
        followingCommand(false, userId)
    }

    private fun followingCommand(isFollow: Boolean, targetUserId: String) {
        val observable = if (isFollow) {
            RetrofitManager.getInstance().api.postFollowing(targetUserId)
        } else {
            RetrofitManager.getInstance().api.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)
                    }
                    EventBus.getDefault().post(EBUserFollow(targetUserId, isFollow))
                }

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

    fun toggleComment(answerId: String, isCommentable: Boolean) {
        val params = HashMap<String, Boolean>()
        params["commentable"] = isCommentable
        val body = RequestBody.create(
            MediaType.parse("application/json"),
            JSONObject(params as Map<*, *>).toString()
        )

        RetrofitManager.getInstance()
            .api
            .postAnswerCommentable(answerId, body)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    answerDetail?.commentable = isCommentable
                    commentable.postValue(isCommentable)
                }

                override fun onFailure(e: HttpException?) {
                    Utils.toast(getApplication(), e?.localizedMessage)
                }
            })
    }

    fun doHighlightThisAnswer(answerId: String) {
        RetrofitManager.getInstance().api
            .highlightAnswer(answerId)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    highlight.postValue(true)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    ErrorHelper.handleError(getApplication(), e?.response()?.errorBody()?.string())
                }
            })
    }

    fun doFoldThisAnswer(answerId: String) {
        RetrofitManager.getInstance().api
            .foldAnswer(answerId)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    fold.postValue(true)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    ErrorHelper.handleError(getApplication(), e?.response()?.errorBody()?.string())
                }
            })
    }

    fun doHideThisAnswer(answerId: String) {
        RetrofitManager.getInstance().api
            .hideAnswer(answerId)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    hide.postValue(true)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    ErrorHelper.handleError(getApplication(), e?.response()?.errorBody()?.string())
                }
            })
    }

    fun trackReadEvent(
        answerId: String,
        answerDetailEntity: AnswerDetailEntity,
        elapsedTime: Int,
        entrance: String,
        path: String,
        specialColumn: SpecialColumn?
    ) {
        val combinedContentAndId = StringUtils.combineTwoString(answerDetailEntity.content, answerId)

        MtaHelper.onEventWithTime("答案阅读量_按社区", elapsedTime, answerDetailEntity.community.name, combinedContentAndId)
        MtaHelper.onEventWithTime("答案阅读量_按位置", elapsedTime, path, combinedContentAndId)
        MtaHelper.onEventWithTime("答案阅读量_社区加位置", elapsedTime, answerDetailEntity.community.name, path)

        LogUtils.uploadAnswerReadTime(
            entrance,
            elapsedTime,
            answerId,
            answerDetailEntity.question,
            answerDetailEntity.community.id,
            answerDetailEntity.community.name,
            specialColumn
        )

        HistoryHelper.insertAnswerEntity(answerDetailEntity)
    }

}