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.ChatMessage
import com.tsmobile.app.data.MessageDeliveryState
import com.tsmobile.app.data.MessageSendState
import com.tsmobile.app.data.MessageType
import com.tsmobile.app.data.Repository
import com.tsmobile.app.data.parseFileMessageMeta
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicLong

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

    companion object {
        private const val TAG = "ChatViewModel"
        /** 消息送达确认超时（毫秒）：超时未收到回显则标记为 FAILED */
        private const val DELIVERY_TIMEOUT_MS = 10_000L
        /** 系统消息 ID 计数器，避免同毫秒并发调用产生重复 key */
        private val sysMsgSeq = AtomicLong(0)
    }

    // 当前会话的消息列表
    private val _messages = MutableStateFlow<List<ChatMessage>>(emptyList())
    val messages: StateFlow<List<ChatMessage>> = _messages.asStateFlow()

    // 发送状态（用于输入框 UI 反馈）
    private val _sendState = MutableStateFlow<MessageSendState>(MessageSendState.Idle())
    val sendState: StateFlow<MessageSendState> = _sendState.asStateFlow()

    // 当前查看的会话参数
    private var currentTargetMode: Int = 2
    private var currentTargetId: Long = 0

    // 送达确认超时 Job（每条消息独立管理，避免快速发送时相互覆盖）
    private val deliveryTimeoutJobs = ConcurrentHashMap<String, Job>()

    /**
     * 进入聊天页。
     * 加载消息并设置活跃会话标识。
     */
    fun enterChat(targetMode: Int, targetId: Long) {
        currentTargetMode = targetMode
        currentTargetId = targetId

        Repository.setActiveChat(targetMode, targetId)
        _messages.value = Repository.getMessages(targetMode, targetId)

        Log.d(TAG, "Entered chat: mode=$targetMode, target=$targetId, messages=${_messages.value.size}")
    }

    /**
     * 离开聊天页。
     */
    fun leaveChat() {
        Repository.setActiveChat(null, null)
        _sendState.value = MessageSendState.Idle()
        deliveryTimeoutJobs.values.forEach { it.cancel() }
        deliveryTimeoutJobs.clear()
        Log.d(TAG, "Left chat")
    }

    /**
     * 清理聊天状态（断开连接时调用）
     */
    fun clearMessages() {
        _messages.value = emptyList()
        _sendState.value = MessageSendState.Idle()
        deliveryTimeoutJobs.values.forEach { it.cancel() }
        deliveryTimeoutJobs.clear()
        currentTargetMode = 2
        currentTargetId = 0
    }

    /**
     * 添加系统消息（频道成员变动等提示）。
     * 归档到 Repository 并刷新当前列表。
     */
    fun addSystemMessage(content: String) {
        val message = ChatMessage(
            id = "sys_${System.currentTimeMillis()}_${sysMsgSeq.incrementAndGet()}",
            targetMode = 2,
            targetId = Repository.currentChannelId.value.toLongOrNull() ?: 0L,
            senderId = 0,
            senderName = "",
            content = content,
            timestamp = System.currentTimeMillis(),
            isSelf = false,
            messageType = MessageType.SYSTEM,
        )
        Repository.archiveMessage(message)
        refreshMessages()
    }

    /**
     * 发送文本消息。
     *
     * 流程：
     * 1. 立即添加到本地消息列表（PENDING 状态）
     * 2. 调用 TSBridge 发送命令
     * 3. 命令成功 → 等待 OnTextMessage 回显确认
     * 4. 命令失败 → 立即标记为 FAILED
     * 5. 超时未确认 → 标记为 FAILED
     */
    fun sendMessage(text: String): Boolean {
        if (text.isBlank()) return false
        if (_sendState.value is MessageSendState.Sending) {
            Log.w(TAG, "Send already in progress")
            return false
        }

        // 同步占用发送状态，避免快速点击或键盘提交重复进入发送流程。
        _sendState.value = MessageSendState.Sending

        val selfId = Repository.selfClientId.value
        val selfName = Repository.getClient(selfId)?.nickname ?: ""

        // 生成唯一 ID（用于匹配回显）
        val messageId = "local_${System.currentTimeMillis()}_${selfId}"
        val timestamp = System.currentTimeMillis()

        // 1. 立即添加到本地列表（PENDING 状态）
        val pendingMessage = ChatMessage(
            id = messageId,
            targetMode = currentTargetMode,
            targetId = currentTargetId,
            senderId = selfId,
            senderName = selfName,
            content = text,
            timestamp = timestamp,
            isSelf = true,
            deliveryState = MessageDeliveryState.PENDING,
            fileMeta = parseFileMessageMeta(text)
        )
        Repository.archiveMessage(pendingMessage)
        refreshMessages()

        // 2. 异步发送命令
        viewModelScope.launch {
            try {
                val error = withContext(Dispatchers.IO) {
                    TSBridge.sendTextMessage(
                        currentTargetMode,
                        currentTargetId.toString(),
                        text
                    )
                }

                if (error.isEmpty()) {
                    Log.d(TAG, "SendTextMessage accepted, waiting for echo")
                    _sendState.value = MessageSendState.Idle(justSent = true)

                    // 3. 启动送达确认超时
                    startDeliveryTimeout(messageId)
                } else {
                    Log.w(TAG, "SendTextMessage rejected: $error")
                    _sendState.value = MessageSendState.Failed(mapSendError(error))

                    // 4. 命令失败 → 标记为 FAILED
                    markMessageFailed(messageId)
                }
            } catch (e: Exception) {
                Log.e(TAG, "SendTextMessage exception", e)
                _sendState.value = MessageSendState.Failed("发送失败：${e.message}")

                // 4. 异常 → 标记为 FAILED
                markMessageFailed(messageId)
            }
        }
        return true
    }

    /**
     * 启动送达确认超时。
     * 如果在 DELIVERY_TIMEOUT_MS 内没有收到回显，标记为 FAILED。
     * 每条消息独立管理超时 Job，快速发送多条消息时互不影响。
     */
    private fun startDeliveryTimeout(messageId: String) {
        val job = viewModelScope.launch {
            delay(DELIVERY_TIMEOUT_MS)

            // 超时：检查消息是否仍然是 PENDING
            deliveryTimeoutJobs.remove(messageId)
            val messages = _messages.value
            val pending = messages.find {
                it.id == messageId && it.deliveryState == MessageDeliveryState.PENDING
            }
            if (pending != null) {
                Log.w(TAG, "Delivery timeout for message: $messageId")
                markMessageFailed(messageId)
            }
        }
        deliveryTimeoutJobs[messageId] = job
    }

    /**
     * 标记指定消息为 FAILED。
     */
    private fun markMessageFailed(messageId: String) {
        // 清理超时 Job
        deliveryTimeoutJobs.remove(messageId)?.cancel()
        // 原子更新本地 _messages 快照（避免与 refreshMessages 并发覆盖）
        _messages.update { current ->
            current.map { msg ->
                if (msg.id == messageId && msg.deliveryState == MessageDeliveryState.PENDING) {
                    msg.copy(deliveryState = MessageDeliveryState.FAILED)
                } else {
                    msg
                }
            }
        }

        // 同步更新 Repository 归档（确保导航离开再回来时状态不丢失）
        Repository.markMessageDeliveryFailed(currentTargetMode, currentTargetId, messageId)
    }

    /**
     * 处理收到的文本消息（由 ServerViewModel 调用）。
     *
     * 关键逻辑：如果是自己发送的消息回显，匹配 PENDING 消息并更新为 SENT，
     * 而不是重复添加。
     */
    fun handleTextMessage(
        targetMode: Int,
        targetId: Long,
        senderId: Int,
        senderName: String,
        content: String
    ) {
        val selfId = Repository.selfClientId.value
        val isSelf = senderId == selfId

        Log.d(TAG, "handleTextMessage: mode=$targetMode, target=$targetId, sender=$senderName($senderId), " +
            "isSelf=$isSelf, current=[$currentTargetMode, $currentTargetId]")
        // 打印完整的消息内容以便调试文件消息结构
        if (content.trimStart().startsWith("{")) {
            Log.d(TAG, "handleTextMessage JSON content: $content")
        }

        // 尝试匹配 PENDING 消息（送达确认）。
        // AAR 已支持 InvokerID，senderId 可靠。仍保留降级逻辑：senderId=0 时仅匹配 content。
        val confirmedId = Repository.confirmMessageDelivery(targetMode, targetId, senderId, content)
        if (confirmedId != null) {
            Log.d(TAG, "Delivery confirmed: id=$confirmedId, content=$content")
            deliveryTimeoutJobs.remove(confirmedId)?.cancel()
            if (targetMode == currentTargetMode && targetId == currentTargetId) {
                refreshMessages()
            }
            return
        }

        // 自己的消息但未匹配到 PENDING → 可能是历史消息，检查是否重复
        if (isSelf) {
            val existingMessages = Repository.getMessages(targetMode, targetId)
            val duplicate = existingMessages.any {
                it.isSelf && it.content == content &&
                    (System.currentTimeMillis() - it.timestamp) < 5000 // 5 秒内同内容视为重复
            }
            if (duplicate) {
                Log.d(TAG, "Duplicate self-message ignored: $content")
                return
            }
        }

        // 非自己的消息，或无法匹配的自己的消息 → 正常归档
        val message = ChatMessage(
            id = "${System.currentTimeMillis()}_${senderId}",
            targetMode = targetMode,
            targetId = targetId,
            senderId = senderId,
            senderName = senderName,
            content = content,
            timestamp = System.currentTimeMillis(),
            isSelf = isSelf,
            deliveryState = MessageDeliveryState.SENT,
            fileMeta = parseFileMessageMeta(content)
        )

        Repository.archiveMessage(message)

        // 如果是当前查看的会话，更新消息列表
        val matchesCurrentChat = targetMode == currentTargetMode && targetId == currentTargetId
        Log.d(TAG, "Message archived: mode=$targetMode, target=$targetId, from=$senderName, " +
            "matchesCurrentChat=$matchesCurrentChat, archiveSize=${Repository.getMessages(targetMode, targetId).size}")
        if (matchesCurrentChat) {
            refreshMessages()
        }
    }

    /**
     * 刷新当前消息列表。
     */
    private fun refreshMessages() {
        val msgs = Repository.getMessages(currentTargetMode, currentTargetId)
        Log.d(TAG, "refreshMessages: mode=$currentTargetMode, target=$currentTargetId, count=${msgs.size}")
        _messages.value = msgs
    }

    /**
     * 重试发送失败的消息。
     */
    fun retrySend(text: String) {
        _sendState.value = MessageSendState.Idle()
        sendMessage(text)
    }

    /**
     * 清除发送状态。
     */
    fun clearSendState() {
        _sendState.value = MessageSendState.Idle()
    }

    private fun mapSendError(error: String): String {
        return when {
            error.contains("permission", ignoreCase = true) -> "权限不足"
            error.contains("flood", ignoreCase = true) -> "发送过于频繁"
            error.contains("empty", ignoreCase = true) -> "消息不能为空"
            else -> "发送失败：$error"
        }
    }
}
