package com.beancount.mobile.notification

import android.app.Notification
import android.content.ComponentName
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.WritableNativeMap
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.beancount.mobile.accessibility.SelectToSpeakService
import com.beancount.mobile.accessibility.ReactContextHolder

/**
 * 通知监听服务（plan.md「4.1 通知监听服务」+「决策 4 Config Plugin」）。
 *
 * 参考 AutoAccounting 的 NotificationListenerService：
 * - 提取支付 App 通知的 title/text
 * - 白名单过滤（复用 SelectToSpeakService.PAYMENT_PACKAGES，单一数据源）
 * - 关键词黑白名单（JS 层 keywordFilter 进一步过滤）
 * - MD5 去重（JS 层 NotificationChannel 处理，避免原生持有状态）
 * - onListenerDisconnected 时 requestRebind 自动重连
 *
 * 通过 DeviceEventEmitter 把通知事件推送到 JS 层 NotificationChannel。
 */
class BillingNotificationListenerService : NotificationListenerService() {

    companion object {
        private const val TAG = "BillingNotification"
    }

    override fun onNotificationPosted(sbn: StatusBarNotification?) {
        super.onNotificationPosted(sbn)
        runCatching {
            val packageName = sbn?.packageName?.toString() ?: return
            // 白名单过滤（复用无障碍服务的 PAYMENT_PACKAGES）
            if (!SelectToSpeakService.PAYMENT_PACKAGES.contains(packageName)) return

            val notification = sbn.notification
            val extras = notification.extras
            val title = extras?.getCharSequence(Notification.EXTRA_TITLE)?.toString() ?: ""
            val text = (extras?.getCharSequence(Notification.EXTRA_BIG_TEXT)
                ?: extras?.getCharSequence(Notification.EXTRA_TEXT))?.toString() ?: ""

            if (title.isBlank() && text.isBlank()) return

            Log.d(TAG, "收到支付通知: pkg=$packageName, title=$title")
            // 推送到 JS 层
            sendNotificationEvent(packageName, title, text)
        }.onFailure {
            Log.e(TAG, "通知处理异常: ${it.message}", it)
        }
    }

    /**
     * 监听断开时自动重连（参考 AutoAccounting requestRebind）。
     * Android Doze / App Standby 可能断开通知监听。
     */
    override fun onListenerDisconnected() {
        super.onListenerDisconnected()
        Log.w(TAG, "通知监听断开，尝试重连")
        requestRebind(ComponentName(this, BillingNotificationListenerService::class.java))
    }

    /** 把通知事件推送到 JS 层 NotificationChannel.handleNotification。 */
    private fun sendNotificationEvent(packageName: String, title: String, text: String) {
        val reactContext = ReactContextHolder.context ?: run {
            Log.w(TAG, "RN 上下文未就绪，丢弃通知")
            return
        }
        try {
            val map = WritableNativeMap().apply {
                putString("packageName", packageName)
                putString("title", title)
                putString("text", text)
                putDouble("timestamp", System.currentTimeMillis().toDouble())
            }
            reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
                .emit("billingNotification", map)
        } catch (e: Exception) {
            Log.e(TAG, "推送通知事件失败: ${e.message}")
        }
    }
}
