package com.adealink.weparty.profile.relation.viewmodel

import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.Rlt
import com.adealink.frame.coroutine.dispatcher.Dispatcher
import com.adealink.frame.mvvm.livedata.ExtLiveData
import com.adealink.frame.mvvm.livedata.ExtMutableLiveData
import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
import com.adealink.frame.mvvm.viewmodel.BaseViewModel
import com.adealink.frame.util.AppUtil
import com.adealink.weparty.App
import com.adealink.weparty.commonui.toast.util.showToast
import com.adealink.weparty.commonui.widget.CommonDialog
import com.adealink.weparty.module.profile.data.FollowStatus
import com.adealink.weparty.module.profile.viewmodel.IFollowViewModel
import com.adealink.weparty.profile.datasource.remote.FollowHttpService
import com.adealink.weparty.profile.relation.data.FansItemData
import com.adealink.weparty.profile.relation.data.FansListReq
import com.adealink.weparty.profile.relation.data.FollowItemData
import com.adealink.weparty.profile.relation.data.FollowListReq
import com.adealink.weparty.profile.relation.data.FollowReq
import com.adealink.weparty.profile.relation.data.FollowStatusReq
import com.adealink.weparty.util.PageHandler
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlin.coroutines.resume
import com.adealink.weparty.R as APP_R

class FollowViewModel : BaseViewModel(), IFollowViewModel {

    private val followHttpService by lazy {
        App.instance.networkService.getHttpService(FollowHttpService::class.java)
    }

    private val followStatusMap = mutableMapOf<String, FollowStatus>()
    override val isFollowLD = ExtMutableLiveData<Map<String, FollowStatus>>()
    override val followCountLD: ExtLiveData<Long> = ExtMutableLiveData()
    override val fansCountLD: ExtLiveData<Long> = ExtMutableLiveData()
    override fun isFollow(uid: String): LiveData<Rlt<FollowStatus>> {
        val liveData = OnceMutableLiveData<Rlt<FollowStatus>>()
        viewModelScope.launch {
            val rlt = suspendIsFollow(listOf(uid))
            when (rlt) {
                is Rlt.Failed -> {
                    liveData.send(rlt)
                }

                is Rlt.Success -> {
                    val followStatus = rlt.data[uid] ?: FollowStatus.NONE
                    followStatusMap[uid] = followStatus
                    isFollowLD.send(followStatusMap)
                    liveData.send(Rlt.Success(followStatus))
                }
            }
        }
        return liveData
    }


    override fun isFollow(uids: List<String>): LiveData<Rlt<Map<String, FollowStatus>>> {
        val liveData = OnceMutableLiveData<Rlt<Map<String, FollowStatus>>>()
        viewModelScope.launch {
            val rlt = suspendIsFollow(uids)
            when (rlt) {
                is Rlt.Failed -> {
                    liveData.send(rlt)
                }

                is Rlt.Success -> {
                    followStatusMap.putAll(rlt.data)
                    isFollowLD.send(followStatusMap)
                    liveData.send(Rlt.Success(followStatusMap))
                }
            }
        }
        return liveData
    }

    private suspend fun suspendIsFollow(uids: List<String>): Rlt<Map<String, FollowStatus>> {
        val rlt = followHttpService.isFollow(FollowStatusReq(uids.distinct()))
        when (rlt) {
            is Rlt.Failed -> {
                return rlt
            }

            is Rlt.Success -> {
                val followMap = mutableMapOf<String, FollowStatus>()
                rlt.data.data?.list?.forEach {
                    followMap[it.uid] = FollowStatus.map(it.followStatus)
                }
                return Rlt.Success(followMap)
            }
        }
    }

    override fun follow(uid: String, checkEachFollow: Boolean): LiveData<Rlt<FollowStatus>> {
        val liveData = OnceMutableLiveData<Rlt<FollowStatus>>()
        viewModelScope.launch {
            val rlt = followHttpService.follow(FollowReq(uid, true))
            when (rlt) {
                is Rlt.Failed -> {
                    liveData.send(rlt)
                }

                is Rlt.Success -> {
                    showToast(APP_R.string.common_follow_success)
                    val finalStatus: FollowStatus = if (checkEachFollow) {
                        //检查互关状态
                        val rlt = suspendIsFollow(listOf(uid))
                        when (rlt) {
                            is Rlt.Failed -> {
                                FollowStatus.FOLLOW
                            }

                            is Rlt.Success -> {
                                rlt.data[uid] ?: FollowStatus.FOLLOW
                            }
                        }
                    } else {
                        FollowStatus.FOLLOW
                    }
                    followStatusMap[uid] = finalStatus
                    isFollowLD.send(followStatusMap)
                    liveData.send(Rlt.Success(finalStatus))
                }
            }
        }
        return liveData
    }

    override fun unFollow(uid: String, checkEachFollow: Boolean): LiveData<Rlt<FollowStatus>> {
        val liveData = OnceMutableLiveData<Rlt<FollowStatus>>()
        viewModelScope.launch {
            val activity = AppUtil.currentActivity as? FragmentActivity ?: return@launch
            val unFollow = withContext(Dispatcher.UI) {
                checkUnFollowDialog(activity)
            }
            if (!unFollow) {
                return@launch
            }
            val rlt = followHttpService.follow(FollowReq(uid, false))
            when (rlt) {
                is Rlt.Failed -> {
                    liveData.send(rlt)
                }

                is Rlt.Success -> {
                    val finalStatus: FollowStatus = if (checkEachFollow) {
                        //检查互关状态
                        val rlt = suspendIsFollow(listOf(uid))
                        when (rlt) {
                            is Rlt.Failed -> {
                                FollowStatus.NONE
                            }

                            is Rlt.Success -> {
                                rlt.data[uid] ?: FollowStatus.NONE
                            }
                        }
                    } else {
                        FollowStatus.NONE
                    }
                    followStatusMap[uid] = finalStatus
                    isFollowLD.send(followStatusMap)
                    liveData.send(Rlt.Success(finalStatus))
                }
            }

        }
        return liveData
    }

    private suspend fun checkUnFollowDialog(activity: FragmentActivity): Boolean {
        return suspendCancellableCoroutine { coroutine ->
            CommonDialog.Builder()
                .title(getCompatString(APP_R.string.common_unfollow))
                .message(getCompatString(APP_R.string.common_unfollow_tips))
                .positiveText(getCompatString(APP_R.string.common_unfollow_cancel_tips))
                .negativeText(getCompatString(APP_R.string.common_unfollow_confirm_tips))
                .setShowDefaultCancel(true)
                .onDismiss {
                    if (coroutine.isActive) {
                        coroutine.resume(false)
                    }
                }
                .onPositive {
                    if (coroutine.isActive) {
                        coroutine.resume(false)
                    }
                }
                .onNegative {
                    if (coroutine.isActive) {
                        coroutine.resume(true)
                    }
                }
                .build()
                .show(activity.supportFragmentManager)
        }
    }

    override fun getFollowCount() {
        viewModelScope.launch {
            val rlt = followHttpService.pullFollowList(FollowListReq(1, null))
            when (rlt) {
                is Rlt.Failed -> {
                    followCountLD.send(0)
                }

                is Rlt.Success -> {
                    followCountLD.send(rlt.data.data?.total ?: 0)
                }
            }
        }
    }

    override fun getFansCount() {
        viewModelScope.launch {
            val rlt = followHttpService.pullFansList(FansListReq(1, null))
            when (rlt) {
                is Rlt.Failed -> {
                    fansCountLD.send(0)
                }

                is Rlt.Success -> {
                    fansCountLD.send(rlt.data.data?.total ?: 0)
                }
            }
        }
    }

    private val followList = mutableListOf<FollowItemData>()
    private val followUids = mutableSetOf<String>()
    private val followPageHandler = PageHandler()

    val followListRltLD = ExtMutableLiveData<Rlt<Any>>()
    val followListLD = MutableLiveData<List<FollowItemData>>()
    fun pullFollowList() {
        followList.clear()
        followUids.clear()
        followPageHandler.reset()
        loadMoreFollowList()
    }

    fun hasMoreFollow(): Boolean {
        return !followPageHandler.isEnd
    }


    fun loadMoreFollowList() {
        viewModelScope.launch {
            val rlt = followHttpService.pullFollowList(
                FollowListReq(
                    size = followPageHandler.pageSize,
                    next = followPageHandler.currentPage
                )
            )
            when (rlt) {
                is Rlt.Failed -> {
                    followListRltLD.send(rlt)
                }

                is Rlt.Success -> {
                    followPageHandler.nextPage(rlt.data.data?.next)
                    rlt.data.data?.list?.forEach {
                        if (!followUids.contains(it.uid)) {
                            followList.add(FollowItemData(it))
                            followUids.add(it.uid)
                        }
                    }
                    followCountLD.send(rlt.data.data?.total ?: 0)
                    followListRltLD.send(rlt)
                    followListLD.send(followList)
                }
            }
        }
    }


    private val fansList = mutableListOf<FansItemData>()
    private val fansUids = mutableSetOf<String>()
    private val fansPageHandler = PageHandler()
    val fansListRltLD = ExtMutableLiveData<Rlt<Any>>()
    val fansListLD = MutableLiveData<List<FansItemData>>()
    fun pullFansList() {
        fansList.clear()
        fansUids.clear()
        fansPageHandler.reset()
        loadMoreFansList()
    }

    fun hasMoreFans(): Boolean {
        return !fansPageHandler.isEnd
    }

    fun loadMoreFansList() {
        viewModelScope.launch {
            val rlt = followHttpService.pullFansList(
                FansListReq(
                    size = fansPageHandler.pageSize,
                    next = fansPageHandler.currentPage
                )
            )
            when (rlt) {
                is Rlt.Failed -> {
                    fansListRltLD.send(rlt)
                }

                is Rlt.Success -> {
                    fansPageHandler.nextPage(rlt.data.data?.next)
                    rlt.data.data?.list?.forEach {
                        if (!fansUids.contains(it.uid)) {
                            fansList.add(FansItemData(it))
                            fansUids.add(it.uid)
                        }
                    }
                    fansCountLD.send(rlt.data.data?.total ?: 0)
                    fansListRltLD.send(rlt)
                    fansListLD.send(fansList)
                }
            }
        }
    }
}