package com.remax.visualnovel.ui.chat

/**
 * Created by HJW on 2025/8/13
 */
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.remax.visualnovel.app.viewmodel.base.OssViewModel
import com.remax.visualnovel.entity.imbean.IMAIInMessage
import com.remax.visualnovel.entity.imbean.IMMessageWrapper
import com.remax.visualnovel.entity.imbean.raw.CustomRawData
import com.remax.visualnovel.entity.imbean.raw.CustomScoreData
import com.remax.visualnovel.entity.request.AIFeedback
import com.remax.visualnovel.entity.request.AlbumDTO
import com.remax.visualnovel.entity.request.ChatAlbum
import com.remax.visualnovel.entity.request.ChatSetting
import com.remax.visualnovel.entity.request.Gift
import com.remax.visualnovel.entity.request.S3TypeDTO
import com.remax.visualnovel.entity.request.SendGift
import com.remax.visualnovel.entity.response.Album
import com.remax.visualnovel.entity.response.BucketBean
import com.remax.visualnovel.entity.response.Character
import com.remax.visualnovel.entity.response.ChatModel
import com.remax.visualnovel.entity.response.ChatSet
import com.remax.visualnovel.entity.response.HeartbeatLevelEnum
import com.remax.visualnovel.entity.response.VoiceASR
import com.remax.visualnovel.entity.response.base.ApiEmptyResponse
import com.remax.visualnovel.entity.response.base.ApiFailedResponse
import com.remax.visualnovel.entity.response.base.Response
import com.remax.visualnovel.extension.convertFromJson
import com.remax.visualnovel.manager.nim.FetchResult
import com.remax.visualnovel.manager.nim.LoadStatus
import com.remax.visualnovel.manager.nim.NimManager
import com.remax.visualnovel.repository.api.AIRepository
import com.remax.visualnovel.repository.api.ChatRepository
import com.remax.visualnovel.repository.api.DictRepository
import com.remax.visualnovel.repository.api.MessageRepository
import com.remax.visualnovel.repository.ext.convertMessage
import com.remax.visualnovel.ui.chat.message.call.manager.RTCManager
import com.google.gson.Gson
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum
import com.netease.nimlib.sdk.v2.message.V2NIMClearHistoryNotification
import com.netease.nimlib.sdk.v2.message.V2NIMMessage
import com.netease.nimlib.sdk.v2.message.V2NIMMessageCreator
import com.netease.nimlib.sdk.v2.message.V2NIMMessageDeletedNotification
import com.netease.nimlib.sdk.v2.message.V2NIMMessageListener
import com.netease.nimlib.sdk.v2.message.V2NIMMessagePinNotification
import com.netease.nimlib.sdk.v2.message.V2NIMMessageQuickCommentNotification
import com.netease.nimlib.sdk.v2.message.V2NIMMessageRevokeNotification
import com.netease.nimlib.sdk.v2.message.V2NIMP2PMessageReadReceipt
import com.netease.nimlib.sdk.v2.message.V2NIMTeamMessageReadReceipt
import com.netease.nimlib.sdk.v2.utils.V2NIMConversationIdUtil
import com.remax.visualnovel.manager.gift.GiftManager
import com.remax.visualnovel.ui.chat.message.detail.flirting.FlirtingLevelActivity
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject


@HiltViewModel
class ChatViewModel @Inject constructor(
    private val chatRepository: ChatRepository,
    private val dictRepository: DictRepository,
    private val messageRepository: MessageRepository,
    private val aiRepository: AIRepository,
) : OssViewModel() {

    var aiId: String = ""

    var character: Character? = null
        private set

    val conversationId: String
        get() = V2NIMConversationIdUtil.conversationId(character?.nimAccountId, SessionTypeEnum.P2P) ?: ""

    private val _aiBaseInfoFlow = MutableLiveData<Pair<Boolean, Character?>>()
    val aiBaseInfoFlow = _aiBaseInfoFlow

    fun checkHeartbeatLevel(targetLevel: HeartbeatLevelEnum, checkSuccess: () -> Unit) {
        val currLevel = character?.aiUserHeartbeatRelation?.currHeartbeatEnum
        if ((currLevel?.level ?: 0) >= targetLevel.level) {
            checkSuccess()
        } else {
            FlirtingLevelActivity.start(aiId)
        }
    }

    suspend fun refreshAIBaseInfo(enterPage: Boolean) = chatRepository.getIMAICharacterProfile(aiId).transformResult({
        character = it
        NimManager.getUserList(listOf(character?.nimAccountId))
        _aiBaseInfoFlow.value = Pair(enterPage, it)
        getChatSetting()
        getChatModels()
    })

    var chatModels: List<ChatModel>? = null
        private set

    suspend fun getChatModels() = dictRepository.getAIChatModel().transformResult({
        chatModels = it
    })

    suspend fun setChatModel(request: ChatSetting) = chatRepository.setChatModel(request).transformResult({
        getChatSetting()
    })

    var chatSet: ChatSet? = null
        private set

    suspend fun getChatSetting() = chatRepository.getChatSetting(aiId).transformResult({
        chatSet = it
    })


    /**
     * 云信发送消息，raw代表是自定义消息
     */
    fun sendMsg(msgContent: String, raw: CustomRawData? = null, errorCallback: (Int) -> Unit) {

        val v2Message = if (raw != null)
            V2NIMMessageCreator.createCustomMessage(msgContent, Gson().toJson(raw))
        else
            V2NIMMessageCreator.createTextMessage(msgContent)

        messageRepository.sendMessage(v2Message, character?.nimAccountId) { errorCode ->
            errorCallback(errorCode)
        }
    }

    // 消息发送LiveData，本地发送消息通过该LiveData通知UI
    private val _sendScoreLiveData = MutableLiveData<Double?>()
    val sendScoreLiveData: LiveData<Double?> = _sendScoreLiveData

    /**
     * 接受方添加消息接收回调
     */
    private val messageListener = object : V2NIMMessageListener {
        /**
         *  消息接收
         */
        override fun onReceiveMessages(messages: List<V2NIMMessage>) {
            NimManager.log("消息接收回调 onReceiveMessages")
            NimManager.clearUnreadCountByIds(conversationId)
            messages.firstOrNull()?.let { message ->
                if (message.conversationId == conversationId) {
                    /**
                     * message中的分数
                     * 本地实时加减一下
                     * AI发送的文本消息和语音通话时，都会有serverExtension:{"score":0.1}的计算
                     */
                    message.serverExtension?.convertFromJson<CustomScoreData>()?.let {
                        _sendScoreLiveData.value = it.score
                        RTCManager.sendIMScoreMessage(it.score)
                    }

                    val messageRecFetchResult = FetchResult<IMMessageWrapper>(LoadStatus.Success)
                    message.convertMessage()?.let { messageWrapper ->
                        if (messageWrapper.type == IMMessageWrapper.IN_TEXT_TYPE) {
                            /**
                             * 处理自动播放
                             */
                            if (character?.isAutoPlayVoice == 1) {
                                (messageWrapper as? IMAIInMessage)?.imVoice?.autoPlay = true
                            }
                        }
                        messageRecFetchResult.data = messageWrapper
                        messageRecFetchResult.type = messageWrapper.fetchType

                        messageRecFetchResult.typeIndex = -1
                        _sendMessageLiveData.value = messageRecFetchResult
                    }
                }
            }
        }

        override fun onReceiveP2PMessageReadReceipts(readReceipts: List<V2NIMP2PMessageReadReceipt?>?) {
        }

        override fun onReceiveTeamMessageReadReceipts(readReceipts: List<V2NIMTeamMessageReadReceipt?>?) {
        }

        override fun onMessageRevokeNotifications(revokeNotifications: List<V2NIMMessageRevokeNotification?>?) {
        }

        override fun onMessagePinNotification(pinNotification: V2NIMMessagePinNotification?) {
        }

        override fun onMessageQuickCommentNotification(quickCommentNotification: V2NIMMessageQuickCommentNotification?) {
        }

        override fun onMessageDeletedNotifications(messageDeletedNotifications: List<V2NIMMessageDeletedNotification?>?) {
        }

        override fun onClearHistoryNotifications(clearHistoryNotifications: List<V2NIMClearHistoryNotification?>?) {
        }

        /**
         *  本端发送消息状态回调
         */
        override fun onSendMessage(message: V2NIMMessage) {
            val sendingState = message.sendingState
            NimManager.log("本端发送消息 $message")
            NimManager.log("本端发送消息状态 $sendingState")
            /**
             * 发消息时需要刷新一下调用推荐回复接口
             */
            refreshPrompts = true
            if (message.conversationId == conversationId) {
                postMessageSend(message)
            }
        }

        override fun onReceiveMessagesModified(messages: List<V2NIMMessage>) {
            NimManager.log("收到更新的消息 $messages")
            messages.firstOrNull()?.let { message ->
                NimManager.log("收到更新的消息 conversationId:${message.conversationId}")
                if (message.conversationId == conversationId) {
                    val messageRecFetchResult = FetchResult<IMMessageWrapper>(LoadStatus.Success)
                    messageRecFetchResult.data = message.convertMessage()
                    messageRecFetchResult.type = FetchResult.FetchType.Update
                    messageRecFetchResult.typeIndex = -1
                    _sendMessageLiveData.value = messageRecFetchResult
                }
            }
        }
    }

    fun updateMsg(message: V2NIMMessage) {
        val messageRecFetchResult = FetchResult<IMMessageWrapper>(LoadStatus.Success)
        messageRecFetchResult.data = message.convertMessage()
        messageRecFetchResult.type = FetchResult.FetchType.Update
        messageRecFetchResult.typeIndex = -1
        _sendMessageLiveData.value = messageRecFetchResult
    }

    fun aiFeedback(request: AIFeedback) {
        viewModelScope.launch {
            chatRepository.aiFeedback(request)
        }
    }

    // 消息发送LiveData，本地发送消息通过该LiveData通知UI
    private val _sendMessageLiveData = MutableLiveData<FetchResult<IMMessageWrapper>?>()
    val sendMessageLiveData: LiveData<FetchResult<IMMessageWrapper>?> = _sendMessageLiveData

    private val sendMessageFetchResult by lazy {
        FetchResult<IMMessageWrapper>(LoadStatus.Finish)
    }

    // 同步发送消息
    private fun postMessageSend(message: V2NIMMessage) {
        message.convertMessage()?.let { messageWrapper ->
            sendMessageFetchResult.loadStatus = LoadStatus.Success
            sendMessageFetchResult.type = messageWrapper.fetchType
            sendMessageFetchResult.data = messageWrapper
            _sendMessageLiveData.value = sendMessageFetchResult
        }
    }

    fun addMessageListener() {
        messageRepository.setMessageListener(true, messageListener)
    }

    private var bucketBean: BucketBean? = null

    override fun onStart() {
        viewModelScope.launch {
            getBucketToken("mp3", S3TypeDTO.SOUND_PATH).transformResult({
                bucketBean = it
            })
        }
    }

    override fun onDestroy() {
        messageRepository.setMessageListener(false, messageListener)
        NimManager.clearUnreadCountByIds(conversationId)
        GiftManager.initSelect()
    }

    private var anchorMessage: V2NIMMessage? = null

    /**
     * 获取历史消息
     */
    suspend fun getMessageList(isRefresh: Boolean): FetchResult<List<IMMessageWrapper>> {
        if (isRefresh) anchorMessage = null
        val res = messageRepository.getMessageList(conversationId, anchorMessage, character)
//        if (isRefresh && res.data?.size == 1) {
//            sendDialogueMsg()
//        }
        anchorMessage = res.extraInfo as? V2NIMMessage
        return res
    }

    suspend fun voiceASR(filePath: String): Response<VoiceASR> {
        ossUploadFile(filePath, S3TypeDTO.SOUND, isImg = false, token = bucketBean).transformResult({
            return chatRepository.voiceASR(aiId, it?.urlPath)
        }) {
            return Response.createZipFailResponse(it)
        }
        return ApiEmptyResponse()
    }

    suspend fun sendGift(request: SendGift, gift: Gift): Response<Any> {
        return messageRepository.sendGift(request, gift)
    }

    var refreshPrompts = true
        private set

    suspend fun getPrompts(): Response<List<String>> {
        return if (refreshPrompts) {
            refreshPrompts = false
            chatRepository.getPrompts(aiId).transformResult {
                // 失败的话需要重新拉
                refreshPrompts = true
            }
        } else {
            ApiFailedResponse()
        }
    }

    suspend fun viewAlbumImg(request: ChatAlbum) = chatRepository.viewAlbumImg(request)

    suspend fun unlockAlbum(request: ChatAlbum) = aiRepository.unlockAlbum(request)

    fun sendDialogueMsg() {
        viewModelScope.launch {
            chatRepository.sendDialogueMsg(aiId)
        }
    }

    suspend fun changeLiked(): Response<Any> {
        val isLiked = character?.liked == true
        val request = AlbumDTO(
            aiId = aiId,
            likedStatus = if (isLiked) Album.LIKED else Album.CANCELED,
            liked = isLiked
        )
        return aiRepository.setAILikeOrCancel(request).transformResult({
            changeCharacterLiked(isLiked)
        })
    }

    fun changeCharacterLiked(isLiked: Boolean) {
        character?.apply {
            liked = isLiked
            likedNum = if (isLiked) {
                likedNum?.plus(1)
            } else {
                likedNum?.minus(1)
            }
        }
    }

}
