package com.tsmobile.app.viewmodel

import android.app.Application
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.tsmobile.app.TSBridge
import com.tsmobile.app.data.Repository
import com.tsmobile.app.data.VoiceOutputDevice
import com.tsmobile.app.data.VoicePreferences
import com.tsmobile.app.data.VoiceState
import com.tsmobile.app.voice.VoiceService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class VoiceViewModel(application: Application) : AndroidViewModel(application) {

    data class RemoteAudioSettings(val muted: Boolean = false)

    private enum class TransmitMode { PTT, CONTINUOUS }

    companion object {
        private const val TAG = "VoiceViewModel"
    }

    // ── 底层服务 ──
    private val voiceService = VoiceService(application, viewModelScope)
    private val voicePreferences = VoicePreferences(application)

    // ── 状态 ──
    private val _voiceState = MutableStateFlow<VoiceState>(VoiceState.Idle)
    val voiceState: StateFlow<VoiceState> = _voiceState

    private val _isMuted = MutableStateFlow(true)  // 默认静音
    val isMuted: StateFlow<Boolean> = _isMuted

    private val _isTransmitting = MutableStateFlow(false)
    val isTransmitting: StateFlow<Boolean> = _isTransmitting

    private val _isContinuousMicEnabled = MutableStateFlow(false)
    val isContinuousMicEnabled: StateFlow<Boolean> = _isContinuousMicEnabled
    private var transmitMode: TransmitMode? = null

    private val _speakerEnabled = MutableStateFlow(true)
    val speakerEnabled: StateFlow<Boolean> = _speakerEnabled

    private val _denoiseEnabled = MutableStateFlow(true)
    val denoiseEnabled: StateFlow<Boolean> = _denoiseEnabled

    // ── 语音卡状态 ──
    private val _showVoiceCard = MutableStateFlow(false)
    val showVoiceCard: StateFlow<Boolean> = _showVoiceCard

    private val _outputDevice = MutableStateFlow(VoiceOutputDevice.SPEAKER)
    val outputDevice: StateFlow<VoiceOutputDevice> = _outputDevice

    private val _inputVolume = MutableStateFlow(1.0f)
    val inputVolume: StateFlow<Float> = _inputVolume

    private val _outputVolume = MutableStateFlow(1.0f)
    val outputVolume: StateFlow<Float> = _outputVolume

    private val _remoteAudioSettings = MutableStateFlow<Map<Int, RemoteAudioSettings>>(emptyMap())
    val remoteAudioSettings: StateFlow<Map<Int, RemoteAudioSettings>> = _remoteAudioSettings

    // ── 说话检测 ──
    private val _isSelfSpeaking = MutableStateFlow(false)
    val isSelfSpeaking: StateFlow<Boolean> = _isSelfSpeaking

    /** 正在说话的客户端 {clientId → 开始时间} */
    private val _speakingClients = MutableStateFlow<Map<Int, Long>>(emptyMap())
    val speakingClients: StateFlow<Map<Int, Long>> = _speakingClients

    /** 保护 _speakingClients 和 _remoteAudioSettings 的复合读写操作 */
    private val audioStateLock = Any()

    init {
        // 连接 VoiceService 回调到 TSBridge
        voiceService.onVoiceData = { opusData, codec ->
            TSBridge.sendVoice(opusData, codec.toLong())
        }

        voiceService.onVoiceSendError = { error ->
            handleVoiceSendError(error)
        }

        voiceService.onSelfSpeaking = { speaking ->
            _isSelfSpeaking.value = speaking
        }

        viewModelScope.launch {
            voicePreferences.outputVolume.collect { volume ->
                _outputVolume.value = volume
                voiceService.setReceiveVolume(volume)
            }
        }
    }

    // ═══════════════════ 公开 API ═══════════════════

    /** 检查语音是否可用（API 版本 + 权限） */
    fun isVoiceAvailable(): Boolean = voiceService.isVoiceAvailable()

    /** 权限授予后调用 */
    fun onPermissionGranted() {
        Log.d(TAG, "RECORD_AUDIO permission granted")
        if (_voiceState.value is VoiceState.Blocked &&
            (_voiceState.value as VoiceState.Blocked).reason == "需要麦克风权限") {
            _voiceState.value = VoiceState.Idle
        }
    }

    /**
     * 开始语音发送（PTT 按下）
     *
     * 前置条件检查：已连接、已入频道、语音可用
     */
    fun startTransmit() {
        startTransmit(TransmitMode.PTT)
    }

    private fun startTransmit(mode: TransmitMode) {
        Log.d(TAG, "startTransmit called mode=$mode")
        if (_isTransmitting.value) return

        if (!isVoiceAvailable()) {
            endTransmit(VoiceState.Blocked("需要麦克风权限"))
            return
        }

        if (!TSBridge.isConnected()) {
            endTransmit(VoiceState.Blocked("未连接到服务器"))
            return
        }

        if (Repository.currentChannelId.value == "0") {
            endTransmit(VoiceState.Blocked("未加入频道"))
            return
        }

        // PTT 时自动取消静音
        _isMuted.value = false
        voiceService.setMuted(false)

        if (!voiceService.startCapture()) {
            endTransmit(VoiceState.Blocked("麦克风启动失败"))
            return
        }

        transmitMode = mode
        _isContinuousMicEnabled.value = mode == TransmitMode.CONTINUOUS
        _voiceState.value = VoiceState.Transmitting
        _isTransmitting.value = true
        Log.i(TAG, "Voice transmitting started mode=$mode")
    }

    /**
     * 停止语音发送（PTT 松开）
     */
    fun stopTransmit() {
        Log.d(TAG, "stopTransmit called")
        if (transmitMode == TransmitMode.CONTINUOUS) return
        val nextState = if (_voiceState.value is VoiceState.Transmitting) {
            VoiceState.Idle
        } else {
            _voiceState.value
        }
        endTransmit(nextState)
        Log.i(TAG, "Voice transmitting stopped")
    }

    private fun handleVoiceSendError(error: String) {
        if (!_isTransmitting.value) return
        Log.e(TAG, "Voice send failed: $error")
        viewModelScope.launch {
            if (_isTransmitting.value) {
                endTransmit(VoiceState.Blocked(error))
            }
        }
    }

    private fun endTransmit(nextState: VoiceState) {
        voiceService.stopCapture()
        transmitMode = null
        _isContinuousMicEnabled.value = false
        _isTransmitting.value = false
        _isSelfSpeaking.value = false
        _isMuted.value = true
        voiceService.setMuted(true)
        _voiceState.value = nextState
    }

    /** 切换常驻麦克风：开启后持续采集并发送，关闭后恢复静音。 */
    fun toggleMute() {
        if (_isTransmitting.value) {
            if (transmitMode == TransmitMode.CONTINUOUS) {
                endTransmit(VoiceState.Idle)
                Log.i(TAG, "Continuous microphone stopped")
            }
            return
        }
        startTransmit(TransmitMode.CONTINUOUS)
    }

    /** 切换扬声器 */
    fun toggleSpeaker() {
        val newEnabled = !_speakerEnabled.value
        _speakerEnabled.value = newEnabled
        voiceService.setSpeakerEnabled(newEnabled)
        viewModelScope.launch(Dispatchers.IO) {
            if (newEnabled) TSBridge.startReceiveAudio() else TSBridge.stopReceiveAudio()
        }
        Log.d(TAG, "Speaker toggled: $newEnabled")
    }

    /** 切换降噪 */
    fun toggleDenoise() {
        val newEnabled = !_denoiseEnabled.value
        _denoiseEnabled.value = newEnabled
        voiceService.setDenoiseEnabled(newEnabled)
        Log.d(TAG, "Denoise toggled: $newEnabled")
    }

    /** Receives one already-mixed 20 ms interleaved stereo PCM frame from the Go audio worker. */
    fun handleMixedVoicePCM(pcm: ByteArray) {
        if (_speakerEnabled.value) voiceService.handleMixedVoicePCM(pcm)
    }

    /** Go owns speaking detection; Kotlin only reflects explicit bridge transitions. */
    fun handleClientSpeaking(clientID: Long, speaking: Boolean) {
        val clientId = clientID.toInt()
        synchronized(audioStateLock) {
            val current = _speakingClients.value.toMutableMap()
            if (speaking) current[clientId] = System.currentTimeMillis() else current.remove(clientId)
            _speakingClients.value = current
        }
    }

    /** Removes Go's timeline and local transient mute/speaking state for this client. */
    fun removeRemoteClient(clientID: Long, moved: Boolean = false) {
        val clientId = clientID.toInt()
        viewModelScope.launch(Dispatchers.IO) {
            TSBridge.removeRemoteAudioClient(clientId)
        }
        synchronized(audioStateLock) {
            _remoteAudioSettings.value = _remoteAudioSettings.value - clientId
            _speakingClients.value = _speakingClients.value - clientId
        }
    }

    fun setRemoteClientMuted(clientId: Int, muted: Boolean) {
        synchronized(audioStateLock) {
            _remoteAudioSettings.value = _remoteAudioSettings.value + (clientId to RemoteAudioSettings(muted))
        }
        viewModelScope.launch(Dispatchers.IO) {
            TSBridge.setRemoteClientMuted(clientId, muted)
        }
    }

    fun toggleRemoteClientMuted(clientId: Int) {
        synchronized(audioStateLock) {
            val muted = !(_remoteAudioSettings.value[clientId]?.muted ?: false)
            _remoteAudioSettings.value = _remoteAudioSettings.value + (clientId to RemoteAudioSettings(muted))
            viewModelScope.launch(Dispatchers.IO) {
                TSBridge.setRemoteClientMuted(clientId, muted)
            }
        }
    }

    fun onClientMoved(clientId: Long, targetChannelId: String) {
        val id = clientId.toInt()
        if (id == Repository.selfClientId.value) {
            viewModelScope.launch(Dispatchers.IO) {
                TSBridge.clearRemoteAudioClients()
            }
            synchronized(audioStateLock) {
                _remoteAudioSettings.value = emptyMap()
                _speakingClients.value = emptyMap()
            }
        } else if (targetChannelId != Repository.currentChannelId.value) {
            removeRemoteClient(clientId, moved = true)
        }
    }

    /**
     * 停止所有语音活动（断开连接或被踢时调用）
     */
    fun stopVoice() {
        Log.i(TAG, "stopVoice: stopping all voice activity")
        stopTransmit()
        // Go 调用放到 IO 线程，避免主线程阻塞
        viewModelScope.launch(Dispatchers.IO) {
            TSBridge.clearRemoteAudioClients()
            TSBridge.stopReceiveAudio()
        }
        voiceService.stopReceivePlayback("voice stopped")
        _remoteAudioSettings.value = emptyMap()
        _speakingClients.value = emptyMap()
        _voiceState.value = VoiceState.Idle
    }

    /** 连接断开时调用 */
    fun onDisconnected() {
        Log.w(TAG, "onDisconnected: voice blocked")
        endTransmit(VoiceState.Blocked("连接已断开"))
        // Go 调用放到 IO 线程，避免阻塞回调线程
        viewModelScope.launch(Dispatchers.IO) {
            TSBridge.clearRemoteAudioClients()
            TSBridge.stopReceiveAudio()
        }
        voiceService.stopReceivePlayback("disconnected")
        _remoteAudioSettings.value = emptyMap()
        _speakingClients.value = emptyMap()
    }

    /** 重连成功时调用 */
    fun onReconnected() {
        Log.i(TAG, "onReconnected: voice idle")
        voiceService.enableReceivePlayback()
        // Go 调用放到 IO 线程，避免阻塞回调线程
        viewModelScope.launch(Dispatchers.IO) {
            TSBridge.startReceiveAudio()
        }
        _voiceState.value = VoiceState.Idle
    }

    /** 清除阻塞状态（用户手动恢复） */
    fun clearBlocked() {
        if (_voiceState.value is VoiceState.Blocked) {
            _voiceState.value = VoiceState.Idle
        }
    }

    // ═══════════════════ 语音卡控制 ═══════════════════

    fun openVoiceCard() {
        _showVoiceCard.value = true
    }

    fun closeVoiceCard() {
        _showVoiceCard.value = false
    }

    fun switchOutputDevice(device: VoiceOutputDevice) {
        _outputDevice.value = device
        // TODO: 通知底层切换音频输出设备
    }

    fun setInputVolume(volume: Float) {
        _inputVolume.value = volume.coerceIn(0f, 1f)
        // TODO: 通知底层调整输入音量
    }

    fun setOutputVolume(volume: Float) {
        val clamped = volume.coerceIn(0f, 1f)
        _outputVolume.value = clamped
        voiceService.setReceiveVolume(clamped)
        viewModelScope.launch { voicePreferences.setOutputVolume(clamped) }
    }

    // ═══════════════════ 生命周期 ═══════════════════

    override fun onCleared() {
        voiceService.destroy()
        super.onCleared()
        Log.d(TAG, "VoiceViewModel cleared")
    }
}
