package com.seven.ikar.kotlin.core.push

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationManagerCompat
import com.seven.ikar.kotlin.app.IkarNativeApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class NotificationActionReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val pendingResult = goAsync()
        CoroutineScope(Dispatchers.IO).launch {
            try {
                handleIntent(context, intent)
            } finally {
                pendingResult.finish()
            }
        }
    }

    private suspend fun handleIntent(context: Context, intent: Intent) {
        val action = intent.action.orEmpty()
        when (action) {
            NotificationAction.MarkReadAction -> handleMarkRead(context, intent)
            NotificationAction.AcceptIncomingCallAction -> handleAcceptIncomingCall(context, intent)
            NotificationAction.DeclineIncomingCallAction -> handleDeclineIncomingCall(context, intent)
        }
    }

    private suspend fun handleMarkRead(context: Context, intent: Intent) {
        val chatId = intent.getStringExtra(PushDataKeys.ChatId).orEmpty()
        val messageId = intent.getStringExtra(PushDataKeys.MessageId).orEmpty()
        val notificationId = intent.getIntExtra(NotificationAction.NotificationIdExtra, Int.MIN_VALUE)
        if (chatId.isBlank() || messageId.isBlank()) {
            return
        }

        val app = context.applicationContext as? IkarNativeApp ?: return
        runCatching {
            app.container.executeAuthorized { session ->
                app.container.apiClient.acknowledgeRead(
                    accessToken = session.accessToken,
                    chatId = chatId,
                    messageId = messageId
                )
            }
        }.onSuccess {
            if (notificationId != Int.MIN_VALUE) {
                NotificationManagerCompat.from(context).cancel(notificationId)
            }
        }
    }

    private fun handleAcceptIncomingCall(context: Context, intent: Intent) {
        val invite = pendingIncomingCallInviteFromIntent(intent) ?: return
        val app = context.applicationContext as? IkarNativeApp ?: return
        if (app.container.sessionStore.read() == null) {
            return
        }

        app.container.incomingCallInviteStore.clearByCallId(invite.callId)
        IncomingCallNotificationManager.cancelIncomingCall(context, invite.callId)
        IncomingCallNotificationManager.openIncomingCallScreen(context, invite, autoAccept = true)
    }

    private fun handleDeclineIncomingCall(context: Context, intent: Intent) {
        val invite = pendingIncomingCallInviteFromIntent(intent) ?: return
        val app = context.applicationContext as? IkarNativeApp ?: return
        if (app.container.sessionStore.read() == null) {
            return
        }

        app.container.incomingCallInviteStore.clearByCallId(invite.callId)
        app.container.callManager.presentIncomingCallInvite(
            callId = invite.callId,
            chatId = invite.chatId,
            callerId = invite.callerId,
            callerDisplayName = invite.callerDisplayName,
            callerPhoneNumber = invite.callerPhoneNumber,
            mediaType = invite.mediaType
        )
        IncomingCallNotificationManager.cancelIncomingCall(context, invite.callId)
        app.container.callManager.declineCurrentCall()
    }
}

object NotificationAction {
    const val MarkReadAction = "com.seven.ikar.kotlin.NOTIFICATION_MARK_READ"
    const val AcceptIncomingCallAction = "com.seven.ikar.kotlin.NOTIFICATION_ACCEPT_INCOMING_CALL"
    const val DeclineIncomingCallAction = "com.seven.ikar.kotlin.NOTIFICATION_DECLINE_INCOMING_CALL"
    const val NotificationIdExtra = "notificationId"
}
