package wang.yaojia.webterm.push

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.core.app.NotificationManagerCompat
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import wang.yaojia.webterm.api.models.HookDecision
import wang.yaojia.webterm.hostregistry.HostStore
import wang.yaojia.webterm.wiring.ApiClientFactory
import java.util.UUID
import javax.inject.Inject

/**
 * Handles the notification **Deny** action (plan §8 notification-action-trust-split). Deny is
 * **auth-free and fail-safe**: no BiometricPrompt, no UI, no Activity — it just fires the expedited
 * `POST /hook/decision {decision:"deny"}` and dismisses the card. A `BroadcastReceiver` is the right
 * host precisely because Deny needs no biometric gate (Allow does — [AllowTrampolineActivity]).
 *
 * [goAsync] extends the ~10 s receiver budget so the one-shot POST can finish off the main thread.
 * The single-use token arrives via the `FLAG_IMMUTABLE` PendingIntent extras and is handed straight
 * to [PushDecisionSubmitter] — never logged, never persisted.
 */
@AndroidEntryPoint
public class DenyBroadcastReceiver : BroadcastReceiver() {

    @Inject
    public lateinit var hostStore: HostStore

    @Inject
    public lateinit var apiClientFactory: ApiClientFactory

    override fun onReceive(context: Context, intent: Intent) {
        val sessionId = intent.getStringExtra(NotificationBuilder.EXTRA_SESSION_ID)
            ?.let { runCatching { UUID.fromString(it) }.getOrNull() }
        val token = intent.getStringExtra(NotificationBuilder.EXTRA_TOKEN)
        val notificationId = intent.getIntExtra(NotificationBuilder.EXTRA_NOTIFICATION_ID, INVALID_ID)
        if (sessionId == null || token.isNullOrEmpty()) {
            Log.w(TAG, "deny: missing session id or token; ignoring")
            dismiss(context, notificationId)
            return
        }

        val pending = goAsync()
        val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
        val submitter = PushDecisionSubmitter.fromRegistry(hostStore, apiClientFactory) { Log.d(TAG, it) }
        scope.launch {
            try {
                submitter.submit(sessionId, HookDecision.DENY, token)
            } finally {
                dismiss(context, notificationId)
                pending.finish()
            }
        }
    }

    private fun dismiss(context: Context, notificationId: Int) {
        if (notificationId != INVALID_ID) NotificationManagerCompat.from(context).cancel(notificationId)
    }

    private companion object {
        const val TAG = "DenyReceiver"
        const val INVALID_ID = -1
    }
}
