package com.adealink.weparty.im.session.comp.viewmodel

import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.IError
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.weparty.commonui.toast.util.debugToast
import com.adealink.weparty.im.R
import com.adealink.weparty.im.constant.ChatLimitError
import com.adealink.weparty.im.constant.IM_IN_BLACKLIST
import com.adealink.weparty.im.constant.IM_USER_CHAT_LIMIT
import com.adealink.weparty.im.constant.IM_USER_NOT_FIND
import com.adealink.weparty.im.constant.InBlackError
import com.adealink.weparty.im.constant.UserNotFindError
import com.adealink.weparty.im.session.comp.input.InputAction
import com.adealink.weparty.im.session.comp.input.InputMachineTransaction
import com.adealink.weparty.im.session.comp.input.InputState
import com.adealink.weparty.im.session.comp.input.SessionInputMachine
import com.adealink.weparty.im.session.mesasge.PlaymateSayWelcomeTextMessageBean
import com.adealink.weparty.im.session.mesasge.PlaymateSayWelcomeVoiceMessageBean
import com.adealink.weparty.module.im.data.sendIMMessageLD
import com.adealink.weparty.module.playmate.PlaymateModule
import com.tencent.qcloud.tuicore.TUIConstants
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback
import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo
import com.tencent.qcloud.tuikit.tuichat.component.progress.ProgressPresenter
import com.tencent.qcloud.tuikit.tuichat.presenter.ChatPresenter
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import com.adealink.weparty.R as APP_R


data class SessionInputState(
    val lastState: InputState,
    val currentState: InputState
)

class SessionInputViewModel : BaseViewModel() {

    val bottomImeVisibleLD = ExtMutableLiveData<Boolean>()

    fun notifyBottomSoftInputVisible(visible: Boolean) {
        bottomImeVisibleLD.send(visible)
    }


    val transactionLD = ExtMutableLiveData<InputMachineTransaction>()
    val inputStateLD = MutableLiveData<SessionInputState>()
    private val stateMachine: SessionInputMachine =
        SessionInputMachine(
            InputState.STATE_NONE,
            mutableListOf(
                /**
                 * transition to [InputState.STATE_NONE]
                 */
                InputMachineTransaction(
                    "",
                    currentState = InputState.STATE_NONE,
                    action = InputAction.EMPTY_CLICKED,
                    nextState = InputState.STATE_NONE
                ),
            ),
            { transaction ->
                transactionLD.send(transaction)
            },
            { last, current ->
                inputStateLD.send(SessionInputState(last, current))
            }
        )


    /**
     * 参考:InputAction
     */
    fun execute(action: InputAction) {
        viewModelScope.launch {
            stateMachine.execute(action)
        }
    }

    fun registerTransaction(
        page: String,
        currentState: InputState,
        action: InputAction,
        nextState: InputState
    ): InputMachineTransaction {
        return stateMachine.registerTransaction(page, currentState, action, nextState)
    }


    private var chatInfo: ChatInfo? = null
    private var presenter: ChatPresenter? = null

    val sendMessageResultLD = ExtMutableLiveData<Rlt<TUIMessageBean?>>()

    fun init(
        chatInfo: ChatInfo? = null,
        presenter: ChatPresenter? = null
    ) {
        this.chatInfo = chatInfo
        this.presenter = presenter
    }

    fun sendMessage(message: TUIMessageBean) {
        sendMessage(message, false, null)
    }

    fun sendMessage(
        message: TUIMessageBean,
        retry: Boolean,
        callback: IUIKitCallback<TUIMessageBean>?
    ): LiveData<String?> {
        val liveData = OnceMutableLiveData<String>()
        viewModelScope.launch {
            val presenter = presenter
            if (presenter == null) {
                liveData.send(null)
                return@launch
            }
            val msgId = sendMessage(presenter, message, retry, callback)
            liveData.send(msgId)
        }
        return liveData
    }

    private suspend fun sendMessage(
        presenter: ChatPresenter,
        message: TUIMessageBean,
        retry: Boolean,
        callback: IUIKitCallback<TUIMessageBean>?
    ): String? {
        return suspendCancellableCoroutine { continuation ->
            val lastMessage = presenter.loadedMessageList?.lastOrNull()

            presenter.sendMessage(
                message,
                retry,
                false,
                object : IUIKitCallback<TUIMessageBean?>() {
                    override fun onSuccess(data: TUIMessageBean?) {
                        callback?.onSuccess(data)
                        sendMessageResultLD.send(Rlt.Success(data))
                        sendIMMessageLD.postValue(message)
                        onSendMessageSuccess(lastMessage, message)
                    }

                    override fun onError(module: String?, errCode: Int, errMsg: String?) {
                        var errorMessage = errMsg
                        var error: IError = IError(
                            serverCode = errCode,
                            msg = errMsg ?: ""
                        )
                        if (errCode == IM_IN_BLACKLIST) {
                            errorMessage = getCompatString(R.string.im_send_msg_error_in_black_msg)
                            error = InBlackError()
                        } else if (errCode == IM_USER_NOT_FIND) {
                            errorMessage = getCompatString(R.string.im_send_msg_error_user_not_find)
                            error = UserNotFindError()
                        } else if (errCode == IM_USER_CHAT_LIMIT) {
                            errorMessage =
                                getCompatString(APP_R.string.playmate_user_push_chat_limit)
                            error = ChatLimitError()
                        }
                        callback?.onError(errCode, errorMessage, message)
                        sendMessageResultLD.send(Rlt.Failed(error))

                        if (errCode == TUIConstants.BuyingFeature.ERR_SDK_INTERFACE_NOT_SUPPORT) {
                            debugToast("已读回执功能需要购买旗舰版, 检查IM套餐")
                        }
                    }

                    override fun onProgress(data: Any?) {
                        val progress = (data as? Int) ?: 0
                        callback?.onProgress(progress)
                        ProgressPresenter.updateProgress(message.id, progress)
                    }
                })
        }
    }

    private fun onSendMessageSuccess(lastMessage: TUIMessageBean?, sendMessage: TUIMessageBean) {
        val uid = chatInfo?.id
        if (uid.isNullOrEmpty() || lastMessage == null) {
            return
        }
        if (lastMessage is PlaymateSayWelcomeTextMessageBean
            || lastMessage is PlaymateSayWelcomeVoiceMessageBean
        ) {
            //上一条消息是陪玩欢迎消息
            PlaymateModule.reportWelcomeReply(uid)
        }
    }

    fun sendPhotoVideoMessage(original: Uri?, transcodeUri: Uri? = null) {
        presenter?.sendPhotoVideoMessages(original, transcodeUri)
    }


}