package chat.pyramid.pyramid

import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.core.app.RemoteInput
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.plugin.common.MethodChannel

class ReplyReceiver : BroadcastReceiver() {

    companion object {
        const val ACTION_REPLY   = "chat.pyramid.pyramid.REPLY"
        const val ACTION_DISMISS = "chat.pyramid.pyramid.DISMISS"
        const val EXTRA_ROOM_ID  = "room_id"
        const val EXTRA_NOTIF_ID = "notif_id"
        const val REMOTE_INPUT_KEY = "reply_text"
    }

    override fun onReceive(context: Context, intent: Intent) {
        val roomId  = intent.getStringExtra(EXTRA_ROOM_ID) ?: return
        val notifId = intent.getIntExtra(EXTRA_NOTIF_ID, 0)

        // Dismiss the notification immediately.
        (context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
            .cancel(notifId)

        if (intent.action == ACTION_DISMISS) {
            Log.d("PYRAMID-REPLY", "dismiss action for room $roomId")
            return
        }

        // Extract inline reply text.  Some Samsung/MIUI/OEM devices drop the
        // RemoteInput bundle or use a different key — try multiple fallbacks.
        val remoteInput = RemoteInput.getResultsFromIntent(intent)
        val replyText = remoteInput?.let { bundle ->
            bundle.getCharSequence(REMOTE_INPUT_KEY)?.toString()?.trim()
                ?: bundle.keySet()?.firstOrNull()?.let { bundle.getCharSequence(it)?.toString()?.trim() }
        } ?: intent.getStringExtra(REMOTE_INPUT_KEY)
          ?: intent.getStringExtra("input")
          ?: intent.getStringExtra("notification_action_input")
          ?: intent.getStringExtra("reply_text")
        Log.d("PYRAMID-REPLY", "extracted replyText=${replyText?.take(20)} (remoteInput=${remoteInput != null})")
        if (replyText.isNullOrEmpty()) {
            Log.w("PYRAMID-REPLY", "reply text empty after all fallbacks, aborting")
            return
        }

        Log.d("PYRAMID-REPLY", "reply received: room=$roomId text=$replyText")

        // Fast path: Flutter engine is alive — forward directly via MethodChannel.
        val engine = FlutterEngineCache.getInstance().get("main")
        if (engine != null) {
            Log.d("PYRAMID-REPLY", "Flutter engine alive → MethodChannel")
            try {
                MethodChannel(engine.dartExecutor.binaryMessenger, "chat.pyramid.pyramid/install")
                    .invokeMethod("replyFromNotification",
                        mapOf("room_id" to roomId, "text" to replyText))
                return
            } catch (e: Exception) {
                Log.w("PYRAMID-REPLY", "MethodChannel failed: ${e.message}, falling back to prefs")
            }
        }

        // Slow path: app killed — send the encrypted reply via the background
        // engine (no Activity, fully silent). _bgSendReply falls back to the
        // prefs queue itself if it can't send, so nothing is lost.
        // goAsync() keeps this BroadcastReceiver's process alive while the engine
        // boots + sends (otherwise it could be killed right after onReceive).
        Log.d("PYRAMID-REPLY", "Flutter engine not running → background engine send")
        val pending = goAsync()
        BgEngine.run(context, "sendReply", mapOf(
            "room_id" to roomId,
            "text"    to replyText,
        ))
        // Release after a window long enough for sync + encrypted send (~4 s seen
        // in logs; 15 s gives margin). The engine completes independently.
        android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
            try { pending.finish() } catch (_: Exception) {}
        }, 15_000L)
    }
}
