package top.r3944realms.ltdmanager.module

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import top.r3944realms.ltdmanager.module.common.filter.TriggerMessageFilter
import top.r3944realms.ltdmanager.module.common.filter.type.IgnoreSelfFilter
import top.r3944realms.ltdmanager.module.common.filter.type.KeywordFilter
import top.r3944realms.ltdmanager.module.common.filter.type.NewMessageFilter
import top.r3944realms.ltdmanager.napcat.data.ID
import top.r3944realms.ltdmanager.napcat.data.MessageElement
import top.r3944realms.ltdmanager.napcat.data.msghistory.MsgHistorySpecificMsg
import top.r3944realms.ltdmanager.napcat.data.MessageType
import top.r3944realms.ltdmanager.napcat.request.message.SendForwardMsgRequest
import top.r3944realms.ltdmanager.napcat.request.other.SendGroupMsgRequest
import top.r3944realms.ltdmanager.utils.CmdUtil
import top.r3944realms.ltdmanager.utils.LoggerUtil

class RconCommandModule(
    moduleName: String,
    private val groupMessagePollingModule: GroupMessagePollingModule,
    private val rconPath: String,
    private val rconConfigPath: String,
    private val rconTimeoutSec: Long,
    private val selfId: Long,
    private val selfNickName: String,
    private val allowedUsers: Set<Long>,
    private val commandBlocklist: Set<String>,
    private val commandPrefix: String,
) : BaseModule(Modules.RCON_COMMAND, moduleName) {

    private var scope: CoroutineScope? = null

    private var lastTriggeredRealId: Long = -1
    private var lastTriggerTime: Long = 0

    private val triggerFilter by lazy {
        TriggerMessageFilter(
            listOf(
                IgnoreSelfFilter(selfId),
                NewMessageFilter { lastTriggerTime to lastTriggeredRealId },
                KeywordFilter(setOf(commandPrefix)),
            )
        )
    }

    override fun onLoad() {
        LoggerUtil.logger.info("[$name] RCON命令模块已装载")
        LoggerUtil.logger.info("[$name] 允许用户: $allowedUsers")
        LoggerUtil.logger.info("[$name] 命令黑名单: $commandBlocklist")

        scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
        scope!!.launch {
            groupMessagePollingModule.messagesFlow.collect { messages ->
                if (loaded) handleMessages(messages)
            }
        }
    }

    override suspend fun onUnload() {
        scope?.cancel()
        LoggerUtil.logger.info("[$name] RCON命令模块已卸载")
    }

    private suspend fun handleMessages(messages: List<MsgHistorySpecificMsg>) {
        val filtered = triggerFilter.filter(messages)
        val triggerMsg = filtered.maxByOrNull { it.time } ?: return

        try {
            processCommand(triggerMsg)
        } catch (e: Exception) {
            LoggerUtil.logger.error("[$name] 处理RCON命令失败", e)
            sendReply(triggerMsg, "命令执行异常: ${e.message}")
        }
    }

    private suspend fun processCommand(msg: MsgHistorySpecificMsg) {
        val text = msg.message.firstOrNull { it.type == MessageType.Text }?.data?.text ?: return
        val rconCommand = text.removePrefix(commandPrefix).trim()

        if (rconCommand.isEmpty()) {
            sendReply(msg, buildHelpMessage())
            updateTriggerState(msg)
            return
        }

        // 权限检查
        if (msg.userId !in allowedUsers) {
            LoggerUtil.logger.warn("[$name] 用户 ${msg.userId} 无权限执行RCON: $rconCommand")
            sendReply(msg, "你没有权限执行 RCON 命令")
            return
        }

        // 危险命令检查
        val blocked = findBlocklistMatch(rconCommand)
        if (blocked != null) {
            LoggerUtil.logger.warn("[$name] 阻止危险命令: '$rconCommand' (匹配黑名单: $blocked)")
            sendReply(msg, "命令已被阻止 (匹配黑名单规则: $blocked)")
            return
        }

        // 执行RCON
        LoggerUtil.logger.info("[$name] 用户 ${msg.userId} 执行RCON: $rconCommand")
        val output = runRconCommand(rconCommand)
        sendResult(msg, rconCommand, output)
        updateTriggerState(msg)
    }

    private fun findBlocklistMatch(command: String): String? {
        val lower = command.lowercase().trimStart('/')
        return commandBlocklist.firstOrNull { blocked ->
            lower == blocked.lowercase() ||
            lower.startsWith(blocked.lowercase() + " ") ||
            lower.startsWith(blocked.lowercase() + "/")
        }
    }

    private fun runRconCommand(command: String): String {
        return CmdUtil.runExeCommand(
            rconPath,
            "-c", rconConfigPath,
            "-T", "${rconTimeoutSec}s",
            command
        )
    }

    private suspend fun sendResult(msg: MsgHistorySpecificMsg, command: String, output: String) {
        val trimmed = output.trim()
        val maxLen = 3000

        if (trimmed.length <= maxLen) {
            sendReply(msg, buildString {
                appendLine("执行: $command")
                appendLine("─".repeat(24))
                append(trimmed.ifEmpty { "(无输出)" })
            })
            return
        }

        // 长输出 → 合并转发
        val chunks = trimmed.chunked(maxLen)
        val messages = chunks.map { chunk ->
            SendForwardMsgRequest.Message(
                data = SendForwardMsgRequest.PurpleData(chunk),
                type = MessageType.Text
            )
        }

        val topMessage = SendForwardMsgRequest.TopForwardMsg(
            data = SendForwardMsgRequest.MessageData(
                content = messages,
                nickname = selfNickName,
                userId = ID.long(selfId),
            ),
            type = MessageType.Node
        )

        val request = SendForwardMsgRequest(
            groupId = ID.long(groupMessagePollingModule.targetGroupId),
            messages = listOf(topMessage),
            news = listOf(
                SendForwardMsgRequest.ForwardModelNews("RCON: $command"),
                SendForwardMsgRequest.ForwardModelNews("输出 ${trimmed.length} 字符"),
            ),
            prompt = "RCON命令执行结果",
            source = "RCON",
            summary = "RCON: $command",
        )

        napCatClient.sendUnit(request)
    }

    private suspend fun sendReply(msg: MsgHistorySpecificMsg, text: String) {
        napCatClient.sendUnit(
            SendGroupMsgRequest(
                MessageElement.reply(ID.long(msg.realId), text),
                ID.long(groupMessagePollingModule.targetGroupId)
            )
        )
    }

    private fun updateTriggerState(msg: MsgHistorySpecificMsg) {
        lastTriggeredRealId = msg.realId
        lastTriggerTime = msg.time
    }

    private fun buildHelpMessage(): String = buildString {
        appendLine("RCON 命令模块")
        appendLine("用法: $commandPrefix <MC命令>")
        appendLine("─".repeat(16))
        appendLine("示例:")
        appendLine("  $commandPrefix list")
        appendLine("  $commandPrefix forge tps")
        appendLine("  $commandPrefix difficulty peaceful")
    }

    override fun info(): String = "RCON命令模块 - 前缀: $commandPrefix, 允许用户: ${allowedUsers.size}人, 黑名单规则: ${commandBlocklist.size}条"
    override fun help(): String = buildString {
        appendLine("RCON命令模块 - 通过QQ群执行Minecraft RCON命令")
        appendLine("前缀: $commandPrefix")
        appendLine("权限: 仅以下QQ号可执行: ${allowedUsers.joinToString()}")
        appendLine("黑名单命令前缀: ${commandBlocklist.joinToString()}")
    }
}
