package com.adealink.weparty.profile.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.adealink.frame.base.Rlt
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.oss.data.UploadFile
import com.adealink.frame.util.formatTime
import com.adealink.weparty.App
import com.adealink.weparty.image.AVATAR_IMAGE_MAX_HEIGHT
import com.adealink.weparty.image.AVATAR_IMAGE_MAX_SIZE_KB
import com.adealink.weparty.image.AVATAR_IMAGE_MAX_WIDTH
import com.adealink.weparty.image.AVATAR_IMAGE_MIN_QUALITY
import com.adealink.weparty.image.PHOTO_WALL_IMAGE_MAX_HEIGHT
import com.adealink.weparty.image.PHOTO_WALL_IMAGE_MAX_SIZE_KB
import com.adealink.weparty.image.PHOTO_WALL_IMAGE_MAX_WIDTH
import com.adealink.weparty.image.PHOTO_WALL_IMAGE_MIN_QUALITY
import com.adealink.weparty.module.im.IMModule
import com.adealink.weparty.module.image.data.PhotoData
import com.adealink.weparty.module.profile.ProfileModule
import com.adealink.weparty.module.profile.data.EditUserInfo
import com.adealink.weparty.module.profile.data.MyUserInfoData
import com.adealink.weparty.module.profile.data.UserInfo
import com.adealink.weparty.module.profile.data.UserNote
import com.adealink.weparty.module.profile.listener.IProfileListener
import com.adealink.weparty.module.profile.viewmodel.IProfileViewModel
import com.adealink.weparty.profile.data.UpdateMyUserInfoReq
import com.adealink.weparty.profile.datasource.remote.ProfileHttpService
import com.adealink.weparty.profile.manager.profileManager
import com.adealink.weparty.util.uploadPhotos
import kotlinx.coroutines.launch

class ProfileViewModel : BaseViewModel(), IProfileViewModel, IProfileListener {

    override val userInfoLD: LiveData<UserInfo?> = MutableLiveData<UserInfo?>()
    override val userNoteLD: LiveData<UserNote?> = MutableLiveData<UserNote?>()
    override val myUserInfoLD: LiveData<MyUserInfoData?> = MutableLiveData<MyUserInfoData?>()
    override val userOnlineLD: LiveData<Map<String, Boolean>> = ExtMutableLiveData()

    override fun pullMyUserInfo(): LiveData<Rlt<MyUserInfoData?>> {
        val liveData = OnceMutableLiveData<Rlt<MyUserInfoData?>>()
        viewModelScope.launch {
            val rlt = profileManager.pullMyUserInfo()
            when (rlt) {
                is Rlt.Failed -> {
                    myUserInfoLD.send(null)
                }

                is Rlt.Success -> {
                    myUserInfoLD.send(rlt.data)
                }
            }
            liveData.send(rlt)
        }
        return liveData
    }

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

    override fun pullUserInfoBy(uid: String, cache: Boolean): LiveData<Rlt<UserInfo>> {
        val liveData = OnceMutableLiveData<Rlt<UserInfo>>()
        viewModelScope.launch {
            val rlt = profileManager.getUserInfoByUid(uid, cache)
            when (rlt) {
                is Rlt.Failed -> {
                    userInfoLD.send(null)
                }

                is Rlt.Success -> {
                    userInfoLD.send(rlt.data)
                }
            }
            liveData.send(rlt)
        }
        return liveData
    }

    override fun pullUserInoBy(
        uids: List<String>,
        cache: Boolean
    ): LiveData<Rlt<Map<String, UserInfo>>> {
        val liveData = OnceMutableLiveData<Rlt<Map<String, UserInfo>>>()
        viewModelScope.launch {
            liveData.send(profileManager.getUsersInfoByUid(uids.toSet(), cache))
        }
        return liveData
    }

    override fun getUserInfoBy(uid: String): UserInfo? {
        return profileManager.getCacheUserInfo(uid)
    }

    override fun updateProfile(editUserInfo: EditUserInfo): LiveData<Rlt<Any>> {
        val liveData = OnceMutableLiveData<Rlt<Any>>()
        viewModelScope.launch {
            //检查头像
            editUserInfo.avatar?.let { avatar ->
                if (avatar.isLocal() && !avatar.isNull()) {
                    val rlt = uploadPhotos(
                        listOf(avatar),
                        AVATAR_IMAGE_MAX_WIDTH,
                        AVATAR_IMAGE_MAX_HEIGHT,
                        AVATAR_IMAGE_MAX_SIZE_KB,
                        AVATAR_IMAGE_MIN_QUALITY,
                        UploadFile.FileType.AVATAR
                    )
                    when (rlt) {
                        is Rlt.Failed -> {
                            liveData.send(rlt)
                            return@launch
                        }

                        is Rlt.Success -> {
                            editUserInfo.avatar?.let {
                                it.url = rlt.data.firstOrNull()?.url
                            }
                        }
                    }
                }
            }
            //照片墙
            editUserInfo.photos?.let { photos ->
                val rlt = uploadPhotos(
                    photos,
                    PHOTO_WALL_IMAGE_MAX_WIDTH,
                    PHOTO_WALL_IMAGE_MAX_HEIGHT,
                    PHOTO_WALL_IMAGE_MAX_SIZE_KB,
                    PHOTO_WALL_IMAGE_MIN_QUALITY,
                    UploadFile.FileType.IMAGE
                )
                when (rlt) {
                    is Rlt.Failed -> {
                        liveData.send(rlt)
                        return@launch
                    }

                    is Rlt.Success<List<PhotoData>> -> {
                        editUserInfo.photos = rlt.data
                    }
                }
            }

            val rlt = profileHttpService.updateUserInfo(
                UpdateMyUserInfoReq(
                    avatar = editUserInfo.avatar?.url,
                    nickname = editUserInfo.nickname,
                    gender = editUserInfo.gender?.gender,
                    intro = editUserInfo.intro,
                    birthday = editUserInfo.birthday?.let { ts ->
                        formatTime(ts, "yyyy-MM-dd")
                    },
                    interests = editUserInfo.interest?.map { it.code },
                    photos = editUserInfo.photos?.mapNotNull { it.url }
                )
            )
            when (rlt) {
                is Rlt.Failed -> {

                }

                is Rlt.Success -> {
                    profileManager.getUserInfoByUid(ProfileModule.getMyUid(), false)
                    IMModule.updateIMSelfInfo(ProfileModule.getMyUserInfo())
                }
            }
            liveData.send(rlt)
        }
        return liveData
    }

    override fun isUserOnline(uid: String): LiveData<Boolean> {
        val liveData = OnceMutableLiveData<Boolean>()
        viewModelScope.launch {
            val rlt = profileManager.isUserOnline(uid, true)
            when (rlt) {
                is Rlt.Failed -> {
                    liveData.send(false)
                }

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

    override fun isUserOnline(uids: Set<String>): LiveData<Map<String, Boolean>> {
        val liveData = OnceMutableLiveData<Map<String, Boolean>>()
        viewModelScope.launch {
            val rlt = profileManager.isUserOnline(uids, true)
            when (rlt) {
                is Rlt.Failed -> {
                    liveData.send(emptyMap())
                }

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

    override fun pullUserNoteBy(
        uid: String,
        cache: Boolean
    ): LiveData<Rlt<UserNote>> {
        val liveData = OnceMutableLiveData<Rlt<UserNote>>()
        viewModelScope.launch {
            val rlt = profileManager.getUserNoteByUid(uid, cache)
            when (rlt) {
                is Rlt.Failed -> {
                    userNoteLD.send(null)
                }

                is Rlt.Success -> {
                    userNoteLD.send(rlt.data)
                }
            }
            liveData.send(rlt)
        }
        return liveData
    }

    override fun pullUserNoteBy(
        uids: List<String>,
        cache: Boolean
    ): LiveData<Rlt<Map<String, UserNote>>> {
        val liveData = OnceMutableLiveData<Rlt<Map<String, UserNote>>>()
        viewModelScope.launch {
            val rlt = profileManager.getUserNoteByUids(uids, cache)
            liveData.send(rlt)
        }
        return liveData
    }

    override fun getUserNoteBy(uid: String): UserNote? {
        return profileManager.getCacheUserNote(uid)
    }

    override fun updateUserNote(
        uid: String,
        note: String?
    ): LiveData<Rlt<Any>> {
        val liveData = OnceMutableLiveData<Rlt<Any>>()
        viewModelScope.launch {
            val rlt = profileManager.setUserNote(uid, note)
            when (rlt) {
                is Rlt.Failed -> {

                }

                is Rlt.Success -> {
                    if (userNoteLD.value?.uid == uid) {
                        userNoteLD.send(UserNote(uid, note))
                    }
                }
            }
            liveData.send(rlt)
        }
        return liveData
    }

    override fun onUserOnlineStatusChanged(online: Map<String, Boolean>) {
        userOnlineLD.send(online)
    }
}