package com.system.cloudservice.ui

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import com.system.cloudservice.R
import com.system.cloudservice.service.AgentForegroundService
import com.system.cloudservice.util.DeviceInfo
import com.system.cloudservice.util.Logger
import kotlinx.coroutines.*

class WechatFragment : Fragment() {

    private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
    private val prefs by lazy { requireContext().getSharedPreferences("agent_config", 0) }

    /** WP-WX-04 相册选图加友：选图后转缓存文件交给 add_friend_from_image skill */
    private val pickImageLauncher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == android.app.Activity.RESULT_OK) {
            result.data?.data?.let { handlePickedImage(it) }
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        return inflater.inflate(R.layout.fragment_wechat, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        view.findViewById<Button>(R.id.btnOpenWechat).setOnClickListener { executeAction("open_app", mapOf("package" to "com.tencent.mm")) }
        view.findViewById<Button>(R.id.btnGetContacts).setOnClickListener { executeAction("get_contacts", emptyMap(), "wechat") }
        view.findViewById<Button>(R.id.btnGetMessages).setOnClickListener { executeAction("get_messages", emptyMap(), "wechat") }
        view.findViewById<Button>(R.id.btnUnblockAssistant).setOnClickListener { triggerUnblockAssistant() }
        view.findViewById<Button>(R.id.btnScanAddFriend).setOnClickListener {
            val intent = Intent(Intent.ACTION_PICK).apply { type = "image/*" }
            pickImageLauncher.launch(intent)
        }
        refresh(view)
    }

    override fun onResume() {
        super.onResume()
        view?.let { refresh(it) }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        scope.cancel()
    }

    private fun refresh(view: View) {
        scope.launch(Dispatchers.IO) {
            val info = DeviceInfo.collectQuick(requireContext())
            val engine = AgentForegroundService.instance?.engine
            val isConnected = engine?.wsManager?.isConnected ?: false
            val hookReady = engine?.isWechatHookAttached() == true
            val antiBanStatus = engine?.getAntiBanStatus()

            withContext(Dispatchers.Main) {
                if (!isAdded) return@withContext

                val wechatRunning = info["wechat_running"] == true

                val tvRunning = view.findViewById<TextView>(R.id.tvWxRunning)
                tvRunning.text = if (wechatRunning) "运行中" else "未运行"
                tvRunning.setTextColor(resources.getColor(
                    if (wechatRunning) R.color.accent_green else R.color.accent_red, null
                ))
                tvRunning.setBackgroundResource(
                    if (wechatRunning) R.drawable.bg_pill_online else R.drawable.bg_pill_offline
                )

                view.findViewById<TextView>(R.id.tvWxVersion).text =
                    "版本  ${info["wechat_version"] ?: "未检测到"}"

                view.findViewById<TextView>(R.id.tvHookStatus).text =
                    "Hook  ${if (hookReady) "已注入" else "未注入"}"

                val available = hookReady && isConnected
                view.findViewById<TextView>(R.id.tvMsgCapability).text =
                    "消息收发  ${if (available) "✓ 可用" else "—"}"
                view.findViewById<TextView>(R.id.tvContactCapability).text =
                    "通讯录  ${if (available) "✓ 可用" else "—"}"
                view.findViewById<TextView>(R.id.tvMomentCapability).text =
                    "朋友圈  ${if (available) "✓ 可用" else "—"}"

                view.findViewById<Button>(R.id.btnOpenWechat).isEnabled = true
                view.findViewById<Button>(R.id.btnGetContacts).isEnabled = available
                view.findViewById<Button>(R.id.btnGetMessages).isEnabled = available

                updateAntiBanUI(view, antiBanStatus, engine != null)
            }
        }
    }

    /** AB-02~06 防封 runtime 信号渲染 + AB-02/03 风险 Banner 显隐 */
    private fun updateAntiBanUI(view: View, status: Map<String, Any?>?, engineRunning: Boolean) {
        val tvEngine = view.findViewById<TextView>(R.id.tvAntiBanStatus)
        val tvRisk = view.findViewById<TextView>(R.id.tvRiskLevel)
        val tvQuota = view.findViewById<TextView>(R.id.tvQuota)
        val tvNurture = view.findViewById<TextView>(R.id.tvNurturePhase)
        val banner = view.findViewById<android.view.View>(R.id.bannerCircuitBreaker)
        val tvBannerTitle = view.findViewById<TextView>(R.id.tvBannerTitle)
        val tvCooldown = view.findViewById<TextView>(R.id.tvCooldownRemaining)

        if (status == null) {
            tvEngine.text = "防封引擎  ${if (engineRunning) "初始化中" else "服务未运行"}"
            tvRisk.text = "风险等级  —"
            tvQuota.text = "今日配额  —/min · —/hr"
            tvNurture.text = "暖机阶段  —"
            banner.visibility = android.view.View.GONE
            return
        }

        val risk = status["risk_sentinel"] as? Map<*, *> ?: emptyMap<String, Any?>()
        val nurture = status["nurture"] as? Map<*, *> ?: emptyMap<String, Any?>()
        val level = (risk["level"] as? Number)?.toInt() ?: 0
        val levelName = risk["level_name"]?.toString() ?: "未知"
        val minuteCount = (risk["minute_count"] as? Number)?.toInt() ?: 0
        val hourCount = (risk["hour_count"] as? Number)?.toInt() ?: 0
        val cooldownMs = (risk["cooldown_remaining_ms"] as? Number)?.toLong() ?: 0L
        val consecutiveFailures = (risk["consecutive_failures"] as? Number)?.toInt() ?: 0
        val phase = nurture["phase"]?.toString() ?: "—"
        val accountAgeDays = (nurture["account_age_days"] as? Number)?.toInt() ?: 0

        tvEngine.text = "防封引擎  已启用"
        tvRisk.text = "风险等级  $levelName"
        tvRisk.setTextColor(resources.getColor(
            when (level) {
                0 -> R.color.accent_green
                1 -> R.color.accent_blue
                2 -> R.color.accent_orange
                else -> R.color.accent_red
            }, null
        ))
        tvQuota.text = "今日配额  $minuteCount/min · $hourCount/hr"
        tvNurture.text = "暖机阶段  $phase（账号 $accountAgeDays 天）"

        // AB-02 熔断红条 / AB-03 长暂停黄条
        when {
            level >= 3 || cooldownMs > 0 -> {
                banner.visibility = android.view.View.VISIBLE
                banner.setBackgroundResource(R.drawable.bg_pill_offline)
                tvBannerTitle.text = "已熔断，自动化已暂停"
                tvBannerTitle.setTextColor(resources.getColor(R.color.accent_red, null))
                tvCooldown.text = if (cooldownMs > 0) "剩余 ${cooldownMs / 1000}s" else ""
                tvCooldown.setTextColor(resources.getColor(R.color.accent_red, null))
            }
            level == 2 -> {
                banner.visibility = android.view.View.VISIBLE
                banner.setBackgroundResource(R.drawable.bg_pill_connecting)
                tvBannerTitle.text = "风险较高，已降速"
                tvBannerTitle.setTextColor(resources.getColor(R.color.accent_orange, null))
                tvCooldown.text = ""
            }
            else -> banner.visibility = android.view.View.GONE
        }

        // 防封运行时卡点击 → 详情弹窗
        val cardAntiBan = view.findViewById<android.view.View>(R.id.cardAntiBan)
        cardAntiBan?.setOnClickListener {
            showAntiBanDetail(level, levelName, minuteCount, hourCount, cooldownMs, consecutiveFailures, phase, accountAgeDays)
        }
    }

    /** §十·五 防封详情弹窗：今日发送数 · 连续失败 · 冷却 · 暖机 · 打开 hub 防封页 */
    private fun showAntiBanDetail(
        level: Int, levelName: String,
        minuteCount: Int, hourCount: Int,
        cooldownMs: Long, consecutiveFailures: Int,
        phase: String, accountAgeDays: Int,
    ) {
        val msg = buildString {
            append("风险等级  $levelName（L$level）\n")
            append("今日配额  $minuteCount/min · $hourCount/hr\n")
            append("连续失败  $consecutiveFailures 次\n")
            if (cooldownMs > 0) append("冷却剩余  ${cooldownMs / 1000}s\n")
            append("暖机阶段  $phase（账号 $accountAgeDays 天）")
        }
        androidx.appcompat.app.AlertDialog.Builder(requireContext())
            .setTitle("防封详情")
            .setMessage(msg)
            .setPositiveButton("关闭", null)
            .setNeutralButton("打开 hub 防封页") { _, _ ->
                val pwaUrl = prefs.getString("pwa_url", "") ?: ""
                if (pwaUrl.isNotEmpty()) {
                    startActivity(android.content.Intent(android.content.Intent.ACTION_VIEW, android.net.Uri.parse(pwaUrl)))
                } else {
                    Toast.makeText(requireContext(), "未配置 hub 地址", Toast.LENGTH_SHORT).show()
                }
            }
            .show()
    }

    /** WP-WX-03 解封助手入口：服务端 SkillExecutor 不支持时返回 503，UI 诚实提示 */
    private fun triggerUnblockAssistant() {
        val engine = AgentForegroundService.instance?.engine
        if (engine == null) {
            Toast.makeText(requireContext(), "服务未运行，无法启动解封助手", Toast.LENGTH_LONG).show()
            return
        }
        if (!engine.isFridaReady()) {
            Toast.makeText(requireContext(), "Frida 未注入，解封助手需 Hook 通道在线", Toast.LENGTH_LONG).show()
            return
        }
        scope.launch {
            try {
                Toast.makeText(requireContext(), "正在启动解封助手...", Toast.LENGTH_SHORT).show()
                val result = withContext(Dispatchers.IO) {
                    engine.executeLocal(
                        "unblock_via_customer_service",
                        mapOf("reason" to "manual_trigger_from_apk"),
                        "wechat",
                    )
                }
                val code = result["code"]?.toString() ?: "-"
                val msg = result["message"]?.toString().orEmpty()
                val summary = "解封助手  code=$code · ${msg.ifEmpty { "已触发" }}"
                view?.findViewById<TextView>(R.id.tvWechatResult)?.text = summary
                Toast.makeText(requireContext(), summary, Toast.LENGTH_LONG).show()
            } catch (e: Exception) {
                Logger.e("UnblockAssistant error", e)
                Toast.makeText(requireContext(), "解封助手调用失败: ${e.message}", Toast.LENGTH_LONG).show()
            }
        }
    }

    /** WP-WX-04 二维码加友：相册选图 → 缓存文件 → add_friend_from_image skill（Frida 未就绪返回 503） */
    private fun handlePickedImage(uri: Uri) {
        val engine = AgentForegroundService.instance?.engine
        if (engine == null) {
            Toast.makeText(requireContext(), "服务未运行，无法识别二维码", Toast.LENGTH_LONG).show()
            return
        }
        if (!engine.isFridaReady()) {
            Toast.makeText(requireContext(), "Frida 未注入，二维码加友需 Hook 通道在线", Toast.LENGTH_LONG).show()
            return
        }
        scope.launch {
            try {
                Toast.makeText(requireContext(), "正在识别二维码并加好友...", Toast.LENGTH_SHORT).show()
                val tempFile = withContext(Dispatchers.IO) {
                    requireContext().contentResolver.openInputStream(uri)?.use { input ->
                        java.io.File(requireContext().cacheDir, "temp_qr_${System.currentTimeMillis()}.png").apply {
                            outputStream().use { output -> input.copyTo(output) }
                        }
                    } ?: throw java.io.IOException("无法读取图片")
                }
                val result = withContext(Dispatchers.IO) {
                    engine.executeLocal(
                        "add_friend_from_image",
                        mapOf("image_path" to tempFile.absolutePath),
                        "wechat",
                    )
                }
                val code = result["code"]?.toString() ?: "-"
                val msg = result["message"]?.toString().orEmpty()
                val summary = "二维码加友  code=$code · ${msg.ifEmpty { "已触发" }}"
                view?.findViewById<TextView>(R.id.tvWechatResult)?.text = summary
                Toast.makeText(requireContext(), summary, Toast.LENGTH_LONG).show()
                tempFile.delete()
            } catch (e: Exception) {
                Logger.e("ScanAddFriend error", e)
                Toast.makeText(requireContext(), "二维码加友失败: ${e.message}", Toast.LENGTH_LONG).show()
            }
        }
    }

    private fun executeAction(action: String, params: Map<String, Any?>, script: String? = null) {
        val engine = AgentForegroundService.instance?.engine
        if (engine == null) {
            Toast.makeText(requireContext(), "服务未运行", Toast.LENGTH_SHORT).show()
            return
        }
        scope.launch {
            try {
                Toast.makeText(requireContext(), "执行中...", Toast.LENGTH_SHORT).show()
                val result = withContext(Dispatchers.IO) {
                    AgentForegroundService.instance?.engine?.executeLocal(action, params, script)
                }
                val summary = summarizeResult(action, result)
                view?.findViewById<TextView>(R.id.tvWechatResult)?.text = summary
                Toast.makeText(requireContext(), summary, Toast.LENGTH_SHORT).show()
                delay(1000)
                view?.let { refresh(it) }
            } catch (e: Exception) {
                Logger.e("WechatFragment action error", e)
                Toast.makeText(requireContext(), "执行失败: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun summarizeResult(action: String, result: Map<String, Any?>?): String {
        if (result == null) return "$action  未返回"
        val code = result["code"]?.toString() ?: "-"
        val data = result["data"] as? Map<*, *> ?: result
        val success = data["success"] == true || code == "200"
        val count = when {
            data["contacts"] is List<*> -> (data["contacts"] as List<*>).size
            data["messages"] is List<*> -> (data["messages"] as List<*>).size
            data["moments"] is List<*> -> (data["moments"] as List<*>).size
            else -> null
        }
        val suffix = count?.let { "，数量 $it" } ?: ""
        val err = data["error"]?.toString()?.takeIf { it.isNotBlank() }
        return if (success) "$action  完成$suffix" else "$action  失败：${err ?: code}"
    }
}
