package com.inou.clawdnode.notifications

import android.app.Notification
import android.app.RemoteInput
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import com.inou.clawdnode.ClawdNodeApp
import com.inou.clawdnode.protocol.NotificationEvent
import com.inou.clawdnode.service.NodeService
import com.inou.clawdnode.service.NotificationManager

/**
 * Listens to all notifications and forwards them to Gateway.
 * Can also trigger notification actions (reply, dismiss, etc.)
 */
class NotificationListener : NotificationListenerService() {
    
    private val tag = "NotificationListener"
    
    // Track notifications for action triggering
    private val activeNotifications = mutableMapOf<String, StatusBarNotification>()
    
    private var nodeService: NodeService? = null
    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            nodeService = (service as NodeService.LocalBinder).getService()
        }
        override fun onServiceDisconnected(name: ComponentName?) {
            nodeService = null
        }
    }
    
    override fun onCreate() {
        super.onCreate()
        Log.i(tag, "NotificationListener created")
        NotificationManager.register(this)
        
        // Bind to NodeService
        Intent(this, NodeService::class.java).also { intent ->
            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }
    
    override fun onDestroy() {
        Log.i(tag, "NotificationListener destroyed")
        unbindService(serviceConnection)
        super.onDestroy()
    }
    
    override fun onNotificationPosted(sbn: StatusBarNotification) {
        // Skip our own notifications
        if (sbn.packageName == packageName) return
        
        // Skip ongoing/persistent notifications (media players, etc.)
        if (sbn.isOngoing && !isImportantOngoing(sbn)) return
        
        Log.d(tag, "Notification posted: ${sbn.packageName}")
        
        val notificationId = generateNotificationId(sbn)
        activeNotifications[notificationId] = sbn
        
        val event = createNotificationEvent(sbn, notificationId)
        nodeService?.sendEvent(event)
        
        ClawdNodeApp.instance.auditLog.logNotification(
            "NOTIFICATION_POSTED",
            sbn.packageName,
            event.title
        )
    }
    
    override fun onNotificationRemoved(sbn: StatusBarNotification) {
        val notificationId = generateNotificationId(sbn)
        activeNotifications.remove(notificationId)
        Log.d(tag, "Notification removed: ${sbn.packageName}")
    }
    
    // ========================================
    // ACTION TRIGGERING
    // ========================================
    
    fun triggerAction(notificationId: String, actionTitle: String, replyText: String?) {
        val sbn = activeNotifications[notificationId] ?: run {
            Log.w(tag, "Notification not found: $notificationId")
            return
        }
        
        val notification = sbn.notification
        val actions = notification.actions ?: return
        
        val action = actions.find { it.title.toString().equals(actionTitle, ignoreCase = true) }
        if (action == null) {
            Log.w(tag, "Action not found: $actionTitle")
            return
        }
        
        try {
            if (replyText != null && action.remoteInputs?.isNotEmpty() == true) {
                // This is a reply action
                sendReply(action, replyText)
            } else {
                // Regular action
                action.actionIntent.send()
            }
            
            ClawdNodeApp.instance.auditLog.log(
                "NOTIFICATION_ACTION",
                "Triggered action: $actionTitle",
                mapOf("notification_id" to notificationId, "reply" to (replyText != null))
            )
        } catch (e: Exception) {
            Log.e(tag, "Failed to trigger action", e)
        }
    }
    
    fun dismissNotification(notificationId: String) {
        val sbn = activeNotifications[notificationId] ?: return
        cancelNotification(sbn.key)
        
        ClawdNodeApp.instance.auditLog.log(
            "NOTIFICATION_DISMISS",
            "Dismissed notification",
            mapOf("notification_id" to notificationId)
        )
    }
    
    private fun sendReply(action: Notification.Action, text: String) {
        val remoteInput = action.remoteInputs?.firstOrNull() ?: return
        
        val intent = Intent()
        val bundle = Bundle()
        bundle.putCharSequence(remoteInput.resultKey, text)
        RemoteInput.addResultsToIntent(arrayOf(remoteInput), intent, bundle)
        
        action.actionIntent.send(this, 0, intent)
    }
    
    // ========================================
    // HELPERS
    // ========================================
    
    private fun generateNotificationId(sbn: StatusBarNotification): String {
        return "${sbn.packageName}:${sbn.id}:${sbn.postTime}"
    }
    
    private fun createNotificationEvent(sbn: StatusBarNotification, id: String): NotificationEvent {
        val notification = sbn.notification
        val extras = notification.extras
        
        val title = extras.getCharSequence(Notification.EXTRA_TITLE)?.toString()
        val text = extras.getCharSequence(Notification.EXTRA_TEXT)?.toString()
            ?: extras.getCharSequence(Notification.EXTRA_BIG_TEXT)?.toString()
        
        val actions = notification.actions?.map { it.title.toString() } ?: emptyList()
        
        val appName = try {
            val appInfo = packageManager.getApplicationInfo(sbn.packageName, 0)
            packageManager.getApplicationLabel(appInfo).toString()
        } catch (e: Exception) {
            sbn.packageName
        }
        
        return NotificationEvent(
            id = id,
            app = appName,
            packageName = sbn.packageName,
            title = title,
            text = text,
            actions = actions,
            timestamp = sbn.postTime
        )
    }
    
    private fun isImportantOngoing(sbn: StatusBarNotification): Boolean {
        // Whitelist certain ongoing notifications we care about
        val importantPackages = setOf(
            "com.whatsapp",
            "org.telegram.messenger",
            "com.google.android.apps.messaging"
        )
        return sbn.packageName in importantPackages
    }
}
