package com.system.cloudservice.ai

import com.system.cloudservice.util.Logger
import java.util.concurrent.ConcurrentLinkedDeque

data class TaskItem(
    val id: String = "task_${System.currentTimeMillis()}",
    val source: String = "ai",
    val instruction: String,
    val priority: Int = 5,
    val createdAt: Long = System.currentTimeMillis(),
    var status: String = "pending",
    var result: Map<String, Any?>? = null,
)

class AIBrain(
    private val llmClient: LLMClient,
    val brainInterval: Int = 60,
    private val maxOfflineBuffer: Int = 500,
    initialStandingOrders: List<String> = emptyList(),
    var enabled: Boolean = true,
) {
    companion object {
        const val VERSION = "1.0.0"
        private const val SYSTEM_PROMPT = """你是一个运行在 Android 手机上的 AI 助手。你的任务是根据当前手机状态和待办事项，决定下一步要执行的操作。

你可以控制以下 APP：微信(wechat)、抖音(douyin)、小红书(xhs)、闲鱼(xianyu)、Soul(soul)。

每个 APP 支持的操作(action)：
- wechat: send_message, get_messages, get_contacts, add_friend, accept_friend, post_moment, like_moment, get_groups,
  check_login_state, ensure_logged_in, login_by_password, unblock_via_customer_service
- douyin: send_message, get_messages, get_fans, reply_comment
- xhs: send_message, get_messages, like_note
- xianyu: send_message, get_messages
- soul: send_message, get_messages

通用操作：screenshot, click, input, swipe, app_start, app_stop, device_info

你必须以 JSON 格式回复，结构如下：
{
  "should_act": true/false,
  "reason": "决策原因",
  "actions": [
    {"script": "wechat", "action": "send_message", "params": {"to": "xxx", "content": "xxx"}}
  ]
}

如果当前没有需要执行的任务，返回 {"should_act": false, "reason": "无待处理任务"}。
如果设备状态异常（低电量、无网络），优先处理设备问题。"""
    }

    val taskQueue = ConcurrentLinkedDeque<TaskItem>()
    private val offlineBuffer = ConcurrentLinkedDeque<Map<String, Any?>>()
    val standingOrders = mutableListOf<String>().apply { addAll(initialStandingOrders) }

    var online: Boolean = true
        set(value) {
            if (field != value) {
                field = value
                Logger.i("AIBrain mode: ${if (value) "online" else "offline(autonomous)"}")
            }
        }

    private var lastThinkTime = 0L
    private var thinkCount = 0
    private var executeCount = 0

    /** AB-06 批量闸门：返回 false 时整批动作跳过（由 AgentEngine 注入 antiBan::canBatch） */
    var batchGate: (() -> Boolean)? = null

    fun addTask(instruction: String, source: String = "server", priority: Int = 5): String {
        val task = TaskItem(instruction = instruction, source = source, priority = priority)
        taskQueue.add(task)
        if (taskQueue.size > 200) taskQueue.pollFirst()
        Logger.i("Task enqueued [$source]: ${instruction.take(50)}...")
        return task.id
    }

    fun addStandingOrder(order: String) {
        if (order !in standingOrders) {
            standingOrders.add(order)
            Logger.i("Standing order added: ${order.take(50)}...")
        }
    }

    fun flushOfflineBuffer(): List<Map<String, Any?>> {
        val results = offlineBuffer.toList()
        offlineBuffer.clear()
        return results
    }

    suspend fun heartbeatCycle(
        deviceStatus: Map<String, Any?>,
        executeFn: suspend (script: String, action: String, params: Map<String, Any?>) -> Map<String, Any?>
    ): Map<String, Any?> {
        if (!enabled) return mapOf("thought" to false, "acted" to false)

        val now = System.currentTimeMillis()
        if (now - lastThinkTime < brainInterval * 1000L) {
            return mapOf("thought" to false, "acted" to false, "skip" to "interval")
        }

        lastThinkTime = now
        thinkCount++

        val pending = taskQueue.filter { it.status == "pending" }.map { it.instruction }
        val decision = think(deviceStatus, pending.takeIf { it.isNotEmpty() })
            ?: return mapOf("thought" to true, "acted" to false, "reason" to "AI无响应")

        if (decision["should_act"] != true) {
            return mapOf("thought" to true, "acted" to false, "reason" to decision["reason"])
        }

        val results = mutableListOf<Map<String, Any?>>()
        @Suppress("UNCHECKED_CAST")
        val actions = decision["actions"] as? List<Map<String, Any?>> ?: emptyList()

        // AB-06 高风险禁批量：level>=3 时整批跳过（NurtureScheduler 已同步暂停）
        if (actions.isNotEmpty() && batchGate?.invoke() == false) {
            Logger.w("AIBrain heartbeat: batch blocked by risk gate (level>=3)")
            return mapOf("thought" to true, "acted" to false, "reason" to "风控熔断，批量已禁")
        }

        for (spec in actions) {
            val script = spec["script"] as? String ?: continue
            val action = spec["action"] as? String ?: continue
            @Suppress("UNCHECKED_CAST")
            val params = spec["params"] as? Map<String, Any?> ?: emptyMap()

            try {
                val result = executeFn(script, action, params)
                executeCount++
                val entry = mapOf(
                    "script" to script, "action" to action, "params" to params,
                    "result" to result, "timestamp" to System.currentTimeMillis()
                )
                results.add(entry)
                if (!online) offlineBuffer.add(entry.plus("buffered_at" to System.currentTimeMillis()))
            } catch (e: Exception) {
                Logger.e("AIBrain execute failed [$script.$action]", e)
                results.add(mapOf("script" to script, "action" to action, "error" to e.message))
            }
        }

        taskQueue.filter { it.status == "pending" }.forEach { it.status = "done" }

        return mapOf("thought" to true, "acted" to true, "results" to results, "reason" to (decision["reason"] ?: ""))
    }

    /** 用户对话：立即走卡若网关决策并执行（不经心跳间隔） */
    suspend fun chatAndExecute(
        userInstruction: String,
        deviceStatus: Map<String, Any?>,
        executeFn: suspend (script: String, action: String, params: Map<String, Any?>) -> Map<String, Any?>
    ): Map<String, Any?> {
        if (!enabled) return mapOf("code" to 503, "message" to "AI Brain 未启用")
        addTask(userInstruction, "user", 10)
        thinkCount++
        lastThinkTime = System.currentTimeMillis()

        val decision = think(deviceStatus, listOf(userInstruction))
            ?: return mapOf("code" to 503, "message" to "卡若AI 无响应", "instruction" to userInstruction)

        if (decision["should_act"] != true) {
            return mapOf(
                "code" to 200,
                "acted" to false,
                "reason" to (decision["reason"] ?: "无需操作"),
                "instruction" to userInstruction,
            )
        }

        val results = mutableListOf<Map<String, Any?>>()
        @Suppress("UNCHECKED_CAST")
        val actions = decision["actions"] as? List<Map<String, Any?>> ?: emptyList()

        // AB-06 高风险禁批量：level>=3 时整批跳过（与 heartbeatCycle 一致）
        if (actions.isNotEmpty() && batchGate?.invoke() == false) {
            Logger.w("AIBrain chat: batch blocked by risk gate (level>=3)")
            return mapOf("code" to 429, "acted" to false, "reason" to "风控熔断，批量已禁", "instruction" to userInstruction)
        }

        for (spec in actions) {
            val script = spec["script"] as? String ?: continue
            val action = spec["action"] as? String ?: continue
            @Suppress("UNCHECKED_CAST")
            val params = spec["params"] as? Map<String, Any?> ?: emptyMap()
            try {
                val result = executeFn(script, action, params)
                executeCount++
                results.add(mapOf("script" to script, "action" to action, "params" to params, "result" to result))
            } catch (e: Exception) {
                results.add(mapOf("script" to script, "action" to action, "error" to e.message))
            }
        }
        taskQueue.filter { it.status == "pending" }.forEach { it.status = "done" }
        return mapOf(
            "code" to 200,
            "acted" to true,
            "results" to results,
            "reason" to (decision["reason"] ?: ""),
            "instruction" to userInstruction,
            "gateway" to "卡若AI /api/gateway/chat",
        )
    }

    private suspend fun think(
        deviceStatus: Map<String, Any?>,
        pendingInstructions: List<String>?
    ): Map<String, Any?>? {
        val parts = mutableListOf<String>()
        parts.add("当前时间: ${java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss", java.util.Locale.getDefault()).format(java.util.Date())}")
        parts.add("设备状态: ${com.google.gson.Gson().toJson(deviceStatus)}")

        if (!online) parts.add("⚠️ 当前处于离线模式（服务器未连接），需要自主决策")
        if (pendingInstructions != null) parts.add("待处理任务: ${com.google.gson.Gson().toJson(pendingInstructions)}")
        if (standingOrders.isNotEmpty() && !online) parts.add("常驻指令: ${com.google.gson.Gson().toJson(standingOrders)}")

        val messages = listOf(
            mapOf("role" to "system", "content" to SYSTEM_PROMPT),
            mapOf("role" to "user", "content" to parts.joinToString("\n")),
        )

        val response = llmClient.chat(messages) ?: return null

        return try {
            val start = response.indexOf("{")
            val end = response.lastIndexOf("}") + 1
            if (start >= 0 && end > start) {
                @Suppress("UNCHECKED_CAST")
                com.google.gson.Gson().fromJson(response.substring(start, end), Map::class.java) as Map<String, Any?>
            } else null
        } catch (e: Exception) {
            Logger.w("AI response parse failed: ${response.take(200)}")
            null
        }
    }

    fun getStatus(): Map<String, Any?> = mapOf(
        "enabled" to enabled,
        "online" to online,
        "brain_interval" to brainInterval,
        "think_count" to thinkCount,
        "execute_count" to executeCount,
        "task_queue_size" to taskQueue.size,
        "offline_buffer_size" to offlineBuffer.size,
        "standing_orders" to standingOrders.size,
        "version" to VERSION,
    )
}
