package com.remax.visualnovel.ui.chat.message.call.manager


import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.remax.visualnovel.BuildConfig
import com.remax.visualnovel.app.base.app.CommonApplicationProxy
import com.remax.visualnovel.entity.imbean.IMLevelMessage
import com.remax.visualnovel.entity.imbean.raw.CustomCallData
import com.remax.visualnovel.entity.imbean.raw.CustomRawData
import com.remax.visualnovel.entity.request.HeartbeatRelation
import com.remax.visualnovel.manager.nim.NimManager
import com.remax.visualnovel.utils.TimeUtils
import com.google.gson.Gson
import com.netease.nimlib.sdk.v2.message.V2NIMMessageCreator
import com.ss.bytertc.engine.RTCRoom
import com.ss.bytertc.engine.RTCRoomConfig
import com.ss.bytertc.engine.RTCVideo
import com.ss.bytertc.engine.UserInfo
import com.ss.bytertc.engine.data.AudioPropertiesConfig
import com.ss.bytertc.engine.data.LocalAudioPropertiesInfo
import com.ss.bytertc.engine.data.LocalAudioStreamError
import com.ss.bytertc.engine.data.LocalAudioStreamState
import com.ss.bytertc.engine.data.RemoteAudioPropertiesInfo
import com.ss.bytertc.engine.data.RemoteAudioState
import com.ss.bytertc.engine.data.RemoteAudioStateChangeReason
import com.ss.bytertc.engine.data.RemoteStreamKey
import com.ss.bytertc.engine.data.StreamSycnInfoConfig
import com.ss.bytertc.engine.handler.IRTCRoomEventHandler
import com.ss.bytertc.engine.handler.IRTCVideoEventHandler
import com.ss.bytertc.engine.type.AudioProfileType
import com.ss.bytertc.engine.type.AudioScenarioType
import com.ss.bytertc.engine.type.ChannelProfile
import com.ss.bytertc.engine.type.MediaStreamType
import com.ss.bytertc.engine.type.NetworkQualityStats
import com.ss.bytertc.engine.utils.LogUtil
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import timber.log.Timber
import java.nio.ByteBuffer

/**
 * Created by HJW on 2025/8/25
 */
object RTCManager : DefaultLifecycleObserver {

    private var mRTCVideo: RTCVideo? = null
    private var mRTCRoom: RTCRoom? = null

    override fun onDestroy(owner: LifecycleOwner) {
        leaveRoom()
        destroyEngine()
    }

    fun log(content: String?) {
        Timber.i("RTCManager $content")
    }

    var onAudioPropertiesReport: ((isLocal: Boolean, linearVolume: Int) -> Unit)? = null

    private val mRTCVideoEventHandler = object : IRTCVideoEventHandler() {
        override fun onLocalAudioPropertiesReport(audioPropertiesInfos: Array<out LocalAudioPropertiesInfo?>?) {
            audioPropertiesInfos?.forEach {
//                log("onLocalAudioPropertiesReport  audioPropertiesInfos:${it.toString()}")
                /**
                 * 线性音量，与原始音量呈线性关系，数值越大，音量越大。取值范围是：[0,255]。
                 *
                 * [0, 25]: 近似无声
                 * [26, 75]: 低音量
                 * [76, 204]: 中音量
                 * [205, 255]: 高音量
                 */
                val linearVolume = it?.audioPropertiesInfo?.linearVolume ?: 0
                onAudioPropertiesReport?.invoke(true, linearVolume)
                log(" 本地 在说话，音量是:$linearVolume")
            }
        }

        override fun onAudioPlaybackDeviceTestVolume(volume: Int) {
            log("onAudioPlaybackDeviceTestVolume  volume:$volume")
        }

        override fun onRemoteAudioPropertiesReport(
            audioPropertiesInfos: Array<out RemoteAudioPropertiesInfo?>?,
            totalRemoteVolume: Int
        ) {
            audioPropertiesInfos?.forEach {
//                log("onRemoteAudioPropertiesReport  audioPropertiesInfos:${it.toString()}")
                /**
                 * 线性音量，与原始音量呈线性关系，数值越大，音量越大。取值范围是：[0,255]。
                 *
                 * [0, 25]: 近似无声
                 * [26, 75]: 低音量
                 * [76, 204]: 中音量
                 * [205, 255]: 高音量
                 */
                val linearVolume = it?.audioPropertiesInfo?.linearVolume ?: 0
                onAudioPropertiesReport?.invoke(false, linearVolume)
                log(" 远端 在说话，音量是:$linearVolume")
            }
        }

        override fun onUserStartAudioCapture(roomId: String?, uid: String?) {
            log("onUserStartAudioCapture  roomId:$roomId  uid:$uid")

        }

        override fun onUserStopAudioCapture(roomId: String?, uid: String?) {
            log("onUserStopAudioCapture  roomId:$roomId  uid:$uid")
        }

        override fun onLocalAudioStateChanged(state: LocalAudioStreamState?, error: LocalAudioStreamError?) {
            log("onLocalAudioStateChanged  state:$state  error:$error")
        }

        override fun onRemoteAudioStateChanged(
            key: RemoteStreamKey?,
            state: RemoteAudioState?,
            reason: RemoteAudioStateChangeReason?
        ) {
            log("onRemoteAudioStateChanged  state:$state  reason:$reason")
        }


        override fun onStreamSyncInfoReceived(
            streamKey: RemoteStreamKey?,
            streamType: StreamSycnInfoConfig.SyncInfoStreamType?,
            data: ByteBuffer?
        ) {
//            log("onStreamSyncInfoReceived  streamType:$streamType  data:$data")
        }

        override fun onWarning(warn: Int) {
            log("onWarning:$warn")
        }

        override fun onError(err: Int) {
            log("onError:$err")
        }

        override fun onLoggerMessage(level: LogUtil.LogLevel?, msg: String?, throwable: Throwable?) {
            log("onLoggerMessage  level:$level  msg:$msg  throwable:$throwable")
        }
    }

    var joinRoomCallback: (() -> Unit)? = null

    var binaryMessageReceived: ((SubtitleMsgData) -> Unit)? = null

    private val mRTCRoomEventHandler = object : IRTCRoomEventHandler() {

        override fun onRoomStateChanged(roomId: String?, uid: String?, state: Int, extraInfo: String?) {
            log("onRoomStateChanged: roomId=$roomId, uid=$uid, state=$state, extra=$extraInfo")
            if (state == 0) {
                joinRoomCallback?.invoke()
            }
        }

        override fun onStreamPublishSuccess(uid: String?, isScreen: Boolean) {
            log("onRoomStateChanged: uid=$uid, isScreen=$isScreen")
        }

        override fun onStreamStateChanged(roomId: String?, uid: String?, state: Int, extraInfo: String?) {
            log("onStreamStateChanged:roomId=$roomId, uid=$uid, state=$state, extraInfo=$extraInfo")
        }

        override fun onRoomBinaryMessageReceived(uid: String, message: ByteBuffer?) {
            log("onRoomBinaryMessageReceived :$message")
            message?.let {
                val bytes = ByteArray(message.remaining())
                message.get(bytes)
                BinaryMessageHandler().unpack(bytes) { subtitleMsgData ->
                    binaryMessageReceived?.invoke(subtitleMsgData)
                }
            }
        }

        override fun onNetworkQuality(localQuality: NetworkQualityStats, remoteQualities: Array<NetworkQualityStats?>) {
//            log("onNetworkQuality: localQuality=$localQuality, remoteQualities=$remoteQualities")
        }

        private fun notifyLocalRTTUpdated(rtt: Int) {
            log("notifyLocalRTTUpdated: rtt=$rtt")
        }
    }

    private var userId = ""

    fun createEngine(roomId: String, userId: String, token: String) {
        this.userId = userId
        if (mRTCVideo != null) {
            log("createRTCVideo: already created")
            return
        } else {
            joinRoom(roomId, userId, token)
        }

        val context = CommonApplicationProxy.application
        val rtcVideo = RTCVideo.createRTCVideo(context, BuildConfig.RTC_APP_ID, mRTCVideoEventHandler, null, null)

        val config = AudioPropertiesConfig(300)
        with(rtcVideo) {
            // 开启发言者音量监听
            enableAudioPropertiesReport(config)
            setAudioScenario(AudioScenarioType.AUDIO_SCENARIO_COMMUNICATION)
            setAudioProfile(AudioProfileType.AUDIO_PROFILE_DEFAULT)

//            // 获取 AudioManager 实例
//            val audioManager =
//                CommonApplicationProxy.application.getSystemService(Context.AUDIO_SERVICE) as AudioManager
//
//            // 获取当前媒体音量
//            val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
//
//            // 可选：获取最大媒体音量
//            val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
//
//            Timber.d("audioManager currentVolume:$currentVolume  maxVolume:$maxVolume")
//
//            setPlaybackVolume(1)
        }

        mRTCVideo = rtcVideo
        if (mRTCVideo != null) {
            joinRoom(roomId, userId, token)
        }
    }

    fun destroyEngine() {
        log("destroyEngine")
        onAudioPropertiesReport = null
        joinRoomCallback = null
        binaryMessageReceived = null
        leaveRoom()
        if (mRTCVideo != null) {
            RTCVideo.destroyRTCVideo()
            mRTCVideo = null
        }
    }

    fun joinRoom(roomId: String, userId: String, token: String) {
        log("joinRoom: roomId=$roomId, userId=$userId, token=$token")

        leaveRoom()
        if (mRTCVideo == null) {
            return
        }
        mRTCRoom = mRTCVideo?.createRTCRoom(roomId)
        mRTCRoom?.setRTCRoomEventHandler(mRTCRoomEventHandler)
        val userInfo = UserInfo(userId, null)
        val roomConfig = RTCRoomConfig(
            ChannelProfile.CHANNEL_PROFILE_CHAT,
            true,
            true,
            false
        )
        mRTCRoom?.setUserVisibility(false)
        val result = mRTCRoom?.joinRoom(token, userInfo, roomConfig)
        startInteract()
        log("joinRoom: result=$result")
    }

    fun leaveRoom() {
        log("leaveRoom")
        if (mRTCRoom != null) {
            mRTCRoom?.leaveRoom()
            mRTCRoom?.destroy()
        }
    }

    fun startInteract() {
        mRTCRoom?.setUserVisibility(true)
    }

    fun stopInteract() {
        val userVisibility = mRTCRoom?.setUserVisibility(false)
    }

    /**
     * 本地音频采集
     * 开关推流
     */
    fun startAudioCapture(start: Boolean) {
        if (mRTCVideo == null) {
            return
        }
        if (start) {
            val publishRes = mRTCRoom?.publishStream(MediaStreamType.RTC_MEDIA_STREAM_TYPE_AUDIO)
            log("publishRes:$publishRes")
            val startRes = mRTCVideo?.startAudioCapture()
            log("startAudioCapture start:$startRes")
        } else {
            val stopRes = mRTCVideo?.stopAudioCapture()
            log("startAudioCapture stop:$stopRes")
            val unpublishRes = mRTCRoom?.unpublishStream(MediaStreamType.RTC_MEDIA_STREAM_TYPE_AUDIO)
            log("unpublishRes:$unpublishRes")
        }
    }

    fun sendEndMsg(accountId: String, durationTime: Long) {
        val callType =
            if (durationTime < TimeUtils.ONE_SECOND) CustomCallData.CALL_CANCEL else CustomCallData.CALL_END
        val raw = CustomCallData(
            CustomRawData.CALL,
            CustomCallData.CALL_CANCEL, durationTime
        )
//        WalletManager.refreshWallet()
        val v2Message = V2NIMMessageCreator.createCustomMessage(raw.callTxt, Gson().toJson(raw))
        NimManager.v2SendMessage(v2Message, accountId)
    }

    /**
     * 心动等级变化
     */
    private val _levelFlow = MutableSharedFlow<IMLevelMessage?>()
    val levelFlow = _levelFlow.asSharedFlow()

    fun sendIMLevelMessage(message: IMLevelMessage?) {
        MainScope().launch { _levelFlow.emit(message) }
    }

    /**
     * 语音通话中分数变化
     */
    private val _scoreFlow = MutableSharedFlow<Double?>()
    val scoreFlow = _scoreFlow.asSharedFlow()

    fun sendIMScoreMessage(score: Double) {
        MainScope().launch { _scoreFlow.emit(score) }
    }

    /**
     * 更新心动关系
     */
    private val _relationLiveData = MutableSharedFlow<HeartbeatRelation?>()
    val relationLiveData = _relationLiveData.asSharedFlow()

    fun setRelation(relation: HeartbeatRelation?) {
        MainScope().launch { _relationLiveData.emit(relation) }
    }

    /**
     * 余额不足，关闭语音通话
     */
    private val _closeRCTFlow = MutableSharedFlow<Boolean>()
    val closeRCTFlow = _closeRCTFlow.asSharedFlow()

    fun balanceInsufficient() {
        MainScope().launch { _closeRCTFlow.emit(true) }
    }
}