package com.jishisongfu.duobibi.service

import android.accessibilityservice.AccessibilityService
import android.util.Log
import android.view.accessibility.AccessibilityEvent
import com.jishisongfu.duobibi.floating.AccessibilityServiceHolder
import com.jishisongfu.duobibi.floating.NodeDto
import com.jishisongfu.duobibi.floating.TreeSerializer
import com.jishisongfu.duobibi.heartbeat.HeartbeatSender
import com.jishisongfu.duobibi.util.Constants
import com.jishisongfu.duobibi.util.PrivacyPrefs
import com.jishisongfu.duobibi.util.SettingsPrefs
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch

class PriceBotAccessibilityService : AccessibilityService() {

    // 心跳上报独立 scope,SupervisorJob 防一次失败拖死后续。a11y 进程死时整个 scope 一起 GC。
    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

    override fun onServiceConnected() {
        super.onServiceConnected()
        Log.i(TAG, "[A11Y] onServiceConnected")
        AccessibilityServiceHolder.attach(this)
        // a11y 服务被启用 = 关键的"复活"信号 —— 后端可能正在按"a11y_enabled=false 持续 N 分钟"
        // 准备推送召回,这一帧立刻把 a11y_enabled=true 送过去清掉这个判定状态。
        if (PrivacyPrefs.agreed(this)) {
            scope.launch { HeartbeatSender.send(applicationContext, "a11y_connected") }
        }
    }

    override fun onUnbind(intent: android.content.Intent?): Boolean {
        // 用户在系统设置关闭无障碍 / 系统资源压力剥夺 → onUnbind 触发(通常先于 onDestroy)。
        // 这一帧 a11y 还在 ENABLED_ACCESSIBILITY_SERVICES 列表里(系统刚开始拆卸),
        // A11yStateProbe 在这一刻可能仍报 true,所以我们在心跳的 trigger 字段里用
        // a11y_unbinding 显式标识,后端可据此立刻进入"准死亡"判定。
        Log.i(TAG, "[A11Y] onUnbind")
        if (PrivacyPrefs.agreed(this)) {
            scope.launch { HeartbeatSender.send(applicationContext, "a11y_unbinding") }
        }
        return super.onUnbind(intent)
    }

    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
        if (event == null) return
        if (event.eventType != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) return
        val pkg = event.packageName?.toString()
        val cls = event.className?.toString()
        Log.d(TAG, "[A11Y] event pkg=$pkg cls=$cls")
        if (pkg == null) return

        // 自家 APP 自己的窗口(包括浮窗本身) 切换时不要影响浮窗显隐 ——
        // 否则浮窗一显示就会触发自家 window 事件,又把它藏回去,死循环。
        if (pkg == packageName) {
            Log.d(TAG, "[A11Y] -> SKIP own package")
            return
        }

        if (isTransientSystemWindow(pkg)) {
            Log.d(TAG, "[A11Y] -> SKIP transient pkg=$pkg")
            return
        }

        AccessibilityServiceHolder.updateForegroundPackage(pkg)

        if (!PrivacyPrefs.agreed(this) || !SettingsPrefs.floatingEnabled(this)) {
            Log.d(TAG, "[A11Y] -> HIDE (privacy/floating-off)")
            FloatingWindowService.notifyVisibility(this, false)
            return
        }
        val show = pkg in Constants.WHITELIST_PACKAGES
        Log.d(TAG, "[A11Y] -> notifyVisibility($show) for pkg=$pkg")
        FloatingWindowService.notifyVisibility(this, show)
    }

    private fun isTransientSystemWindow(pkg: String): Boolean {
        if (pkg in SYSTEM_WINDOW_PACKAGES) return true
        if (pkg.contains("inputmethod") || pkg.contains(".ime.") || pkg.endsWith(".ime")) return true
        return false
    }

    override fun onInterrupt() {}

    override fun onDestroy() {
        Log.i(TAG, "[A11Y] onDestroy")
        AccessibilityServiceHolder.detach()
        super.onDestroy()
    }

    fun captureCurrentTree(): NodeDto? {
        val root = rootInActiveWindow ?: return null
        return TreeSerializer.serialize(root)
    }

    companion object {
        private const val TAG = "DUOBIBI"

        private val SYSTEM_WINDOW_PACKAGES: Set<String> = setOf(
            "com.android.systemui",
            "android",
            "com.miui.systemAdSolution",
            "com.iflytek.inputmethod",
            "com.sohu.inputmethod.sogou",
            "com.sohu.inputmethod.sogouoem",
            "com.baidu.input",
            "com.baidu.input_mi",
            "com.baidu.input_huawei",
            "com.tencent.qqpinyin",
            "com.touchtype.swiftkey",
            "com.google.android.inputmethod.latin",
            "com.google.android.inputmethod.pinyin",
            "com.android.inputmethod.latin",
            "com.android.inputmethod.pinyin",
        )
    }
}
