package com.gh.gamecenter.qa.article.detail

import android.app.Application
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.util.CollectionUtils
import com.gh.common.util.ErrorHelper
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.json.json
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.observableToMain
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.ActivityLabelEntity
import com.gh.gamecenter.entity.CommentEntity
import com.gh.gamecenter.entity.VoteEntity
import com.gh.gamecenter.eventbus.EBCollectionChanged
import com.gh.gamecenter.eventbus.EBUserFollow
import com.gh.gamecenter.feature.entity.Permissions
import com.gh.gamecenter.qa.comment.base.BaseCommentViewModel
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
import com.gh.gamecenter.retrofit.RetrofitManager
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 retrofit2.HttpException

class ArticleDetailViewModel(
    application: Application,
    articleId: String = "",
    communityId: String = "",
    val recommendId: String = "",
    topCommentId: String
) : BaseCommentViewModel(
    application,
    articleId = articleId,
    communityId = communityId,
    videoId = "",
    questionId = "",
    gameCollectionId = "",
    topCommentId = topCommentId
) {

    var detailEntity: ArticleDetailEntity? = null

    val mFollowLiveData = MutableLiveData<Boolean>()

    val hide = MutableLiveData<Boolean>()
    val like = MutableLiveData<VoteEntity>()
    val dislike = MutableLiveData<Boolean>()
    val highlight = MutableLiveData<Boolean>()
    val cancelHighlight = MutableLiveData<Boolean>()
    val applyHighlight = MutableLiveData<Boolean>()
    val commentable = MutableLiveData<Boolean>()
    val updateDetailLiveData = MutableLiveData<ArticleDetailEntity>()
    val followLiveData = mFollowLiveData

    var articleRenderedLiveData = MutableLiveData<Boolean>()
    var articlePageFinishedLiveData = MutableLiveData<Boolean>()

    override fun provideDataObservable(page: Int): Observable<List<CommentEntity>> {
        val map = hashMapOf<String, Any>()
        if (!isHandleTopComment && topCommentId.isNotEmpty()) {
            map["top_comment_id"] = topCommentId
        }
        return RetrofitManager.getInstance().api.getCommunityArticleCommentList(
            articleId,
            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) }
    }

    fun getArticleDetail() {
        mApi.getCommunityArticleDetail(articleId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ArticleDetailEntity>() {
                override fun onResponse(response: ArticleDetailEntity?) {
                    detailEntity = response
                    topItemData = CommentItemData(articleDetail = response)
                    commentCount = response?.count?.comment ?: 0
                    loadResultLiveData.postValue(LoadResult.SUCCESS)
                    mergeListData(mListLiveData.value)

                    NewLogUtils.logForumContentBrowser(articleId, "bbs_article", recommendId)
                }

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

    fun cancelLikeArticle() {
        mApi.postCommunityArticleUnVote(articleId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<VoteEntity>() {
                override fun onResponse(response: VoteEntity?) {
                    // 赞同减一
                    detailEntity?.me?.isCommunityArticleVote = false
                    detailEntity!!.count.vote--

                    like.postValue(response)

                    syncVoteData()
                }

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

    fun likeArticle() {
        mApi.postCommunityArticleVote(articleId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<VoteEntity>() {
                override fun onResponse(response: VoteEntity?) {
                    // 赞同加一
                    detailEntity?.me?.isCommunityArticleOppose = false
                    detailEntity?.me?.isCommunityArticleVote = true
                    detailEntity!!.count.vote++

                    like.postValue(response)

                    syncVoteData()
                }

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

    fun dislikeArticle() {
        mApi.postCommunityArticleOppose(communityId, articleId)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    if (detailEntity?.me?.isCommunityArticleVote == true) {
                        detailEntity!!.count.vote--
                    }
                    detailEntity?.me?.isCommunityArticleOppose = true
                    detailEntity?.me?.isCommunityArticleVote = false

                    dislike.postValue(true)

                    syncVoteData()
                }

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

    fun cancelDislikeArticle() {
        mApi.postCommunityArticleUnoppose(communityId, articleId)
            .subscribeOn(Schedulers.io())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    detailEntity?.me?.isCommunityArticleOppose = false

                    dislike.postValue(false)

                    syncVoteData()
                }

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

    private fun syncVoteData() {
        articleId.apply {
            SyncPageRepository.postSyncData(
                SyncDataEntity(
                    this,
                    SyncFieldConstants.ARTICLE_VOTE_COUNT,
                    detailEntity?.count?.vote,
                    checkFieldEntity = true
                )
            )
            SyncPageRepository.postSyncData(
                SyncDataEntity(
                    this,
                    SyncFieldConstants.ARTICLE_VOTE,
                    detailEntity?.me?.isCommunityArticleVote,
                    checkFieldEntity = true
                )
            )
        }
    }

    private fun syncFollowData(isFollow: Boolean) {
        articleId.apply {
            SyncPageRepository.postSyncData(
                SyncDataEntity(
                    this,
                    SyncFieldConstants.IS_FOLLOWER,
                    isFollow,
                    checkFieldEntity = true
                )
            )
        }
    }

    fun collectionCommand(isCollection: Boolean, callback: (isFollow: Boolean) -> Unit) {
        val observable = if (isCollection) {
            mApi.postCommunityArticleFavorites(articleId)
        } else {
            mApi.deleteCommunityArticleFavorites(articleId)
        }
        observable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    EventBus.getDefault().post(
                        EBCollectionChanged(
                            articleId,
                            true,
                            CollectionUtils.CollectionType.COMMUNITY_ARTICLE
                        )
                    )
                    if (isCollection) {
                        // 收藏成功
                        callback(true)
                        ToastUtils.showToast(getApplication<Application>().getString(R.string.collection_success))
                    } else {
                        // 取消收藏成功
                        callback(false)
                        ToastUtils.showToast(getApplication<Application>().getString(R.string.collection_cancel))
                    }
                }

                override fun onFailure(e: HttpException?) {
                    if (isCollection) {
                        ToastUtils.showToast(getApplication<Application>().getString(R.string.collection_failure))
                    } else {
                        ToastUtils.showToast(getApplication<Application>().getString(R.string.collection_cancel_failure))
                    }
                }
            })
    }

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

    fun unfollow() {
        followingCommand(false, detailEntity?.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)
                        syncFollowData(true)
                    } else {
                        // 取消关注成功
                        mFollowLiveData.postValue(false)
                        syncFollowData(false)
                    }
                    EventBus.getDefault().post(EBUserFollow(targetUserId, isFollow))
                }

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

    fun doHighlightThisArticle(articleId: String?) {
        mApi.highlightCommunityArticle(articleId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    highlight.postValue(true)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    highlight.postValue(false)
                }
            })
    }

    fun cancelHighlightThisArticle(articleId: String) {
        mApi.cancelHighlightCommunityArticle(articleId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    cancelHighlight.postValue(true)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    cancelHighlight.postValue(false)
                }
            })
    }

    fun doApplyHighlightThisArticle(articleId: String?) {
        mApi.applyHighlightCommunityArticle(articleId)
            .compose(observableToMain())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    applyHighlight.postValue(true)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    applyHighlight.postValue(false)
                }
            })
    }

    fun doHideThisArticle(articleId: String?) {
        mApi.hideCommunityArticle(articleId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    hide.postValue(true)
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    hide.postValue(false)
                }
            })
    }

    fun modifyArticleActivityTag(
        articleId: String,
        label: ActivityLabelEntity?
    ) {
        val body = json { "tag_activity_id" to label?.id }.toRequestBody()
        mApi.modifyArticleActivityTag(articleId, body)
            .compose(observableToMain())
            .subscribe(object : Response<ResponseBody>() {
                override fun onResponse(response: ResponseBody?) {
                    super.onResponse(response)
                    detailEntity?.run {
                        if (me.moderatorPermissions.updateArticleActivityTag == Permissions.ADMIN) {
                            tagActivityId = label?.id ?: ""
                            tagActivityName = label?.name ?: ""
                            updateDetailLiveData.postValue(this)
                            ToastUtils.showToast("修改活动标签成功")
                        } else {
                            ToastUtils.showToast("提交成功")
                        }
                    }
                }

                override fun onFailure(e: HttpException?) {
                    super.onFailure(e)
                    ToastUtils.showToast("修改活动标签失败")
                }
            })
    }

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

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

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

}