Android Kotlin. Проанализируй код и приготовься подробно отвечать на мои вопросы. package ru.maxi.mobile.service.notification

import android.app.Notification
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.os.SystemClock
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap
import com.bumptech.glide.Glide
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import ru.maxi.mobile.R
import ru.maxi.mobile.business.coupon.UpdateCouponStatusInteractor
import ru.maxi.mobile.business.deeplinks.DeepLinkInteractor
import ru.maxi.mobile.common.utils.android.glide.ImageLoadListener
import ru.maxi.mobile.common.utils.android.glide.withLoadListener
import ru.maxi.mobile.core.di.CoroutineDispatcherIO
import ru.maxi.mobile.entity.coupon.CouponStatus
import ru.maxi.mobile.repositories.deeplink.DeepLinkType
import ru.maxi.mobile.ui.splash.SplashActivity
import ru.maxi.mobile.utils.MaxiNotificationManager
import ru.maxi.mobile.utils.formatToTime
import java.time.LocalTime
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import ru.maxi.mobile.uikit.R as UIKitR

/**
 * Обработчик сообщений с сервера [RemoteMessage]
 *
 * Инкапсулирует логику по расшифровке данных из сервисов отправки пуш-уведомлений на устройство
 */
@Singleton
class RemoteMessageHandler @Inject constructor(
    @ApplicationContext private val context: Context,
    @CoroutineDispatcherIO private val ioDispatcher: CoroutineDispatcher,
    private val maxiNotificationManager: MaxiNotificationManager,
    private val updateCouponStatusInteractor: UpdateCouponStatusInteractor,
    private val deepLinkInteractor: DeepLinkInteractor,
) {

    /**
     * Спарсить [RemoteMessage] из данных [data]
     */
    fun parseMessage(data: Map<String, String>): RemoteMessage {
        check(data.canShowMessage) {
            "Message cannot be shown at this time. LocalTime: ${LocalTime.now().formatToTime()}"
        }

        val pushTypeAction = PushTypeAction.getByActionName(data[MessageSettingsKeys.CLICK_ACTION])
            ?: throw IllegalArgumentException("Unknown 'PushTypeAction': ${data[MessageSettingsKeys.CLICK_ACTION]}")

        return when (pushTypeAction) {
            PushTypeAction.COUPON_STATUS_CHANGE -> pushTypeAction.parseSilentMessage(data)
            else -> pushTypeAction.parseNotificationMessage(data)
        }
    }

    /**
     * Обработать сообщение [message]
     */
    suspend fun handleMessage(message: RemoteMessage) {
        when (message) {
            is SilentMessage -> message.handle()
            is NotificationMessage -> message.handle()
        }
    }

    private val Map<String, String>.canShowMessage: Boolean
        get() {
            val ignoreTime = getOrDefault(MessageSettingsKeys.SHOW_IGNORE_TIME, "false")
                .toBooleanStrictOrNull()
                ?: false
            if (ignoreTime) return true

            val currentTime = LocalTime.now()
            val morning = LocalTime.of(9, 0)
            val evening = LocalTime.of(22, 0)

            return currentTime in morning..evening
        }

    private fun PushTypeAction.parseSilentMessage(data: Map<String, String>): RemoteMessage {
        return when (this) {
            PushTypeAction.COUPON_STATUS_CHANGE -> {
                val couponId = requireNotNull(data[NotificationDataKeys.COUPON_ID]).toLong()
                val couponStatus = CouponStatus.valueOf(requireNotNull(data[NotificationDataKeys.COUPON_STATUS]))
                SilentMessage.UpdateCouponStatus(couponId, couponStatus)
            }

            else -> throw IllegalArgumentException("'parseSilentMessage' called on non silent 'PushTypeAction'")
        }
    }

    private fun PushTypeAction.parseNotificationMessage(data: Map<String, String>): RemoteMessage {
        val pushId: Long? = data[NotificationDataKeys.PUSH_ID]?.toLongOrNull()
        val notificationId = (pushId ?: SystemClock.uptimeMillis()).toInt()
        val analyticsLabel: String? = data[NotificationDataKeys.ANALYTICS_LABEL]

        val notificationData = NotificationMessage.NotificationData(
            title = data[NotificationSettingsKeys.TITLE],
            body = data[NotificationSettingsKeys.BODY],
            image = data[NotificationSettingsKeys.IMAGE],
        )

        val messageData = when (this) {
            PushTypeAction.POST -> NotificationMessage.MessageData.PostData(
                postId = requireNotNull(data[NotificationDataKeys.POST_ID]).toLong(),
            )

            PushTypeAction.DELIVERY_PROMO_CODES -> NotificationMessage.MessageData.DeliveryPromoCodesData(
                promoCode = requireNotNull(data[NotificationDataKeys.PROMO_CODE])
                    .also { require(it.isNotBlank()) },
            )

            PushTypeAction.CRM_ACTIONS -> NotificationMessage.MessageData.CrmData(
                transitionType = requireNotNull(
                    CRMNotificationType.safeValueOf(data[NotificationDataKeys.CRM_TRANSITION_TYPE]),
                ),
                value = data[NotificationDataKeys.CRM_VALUE],
            )

            PushTypeAction.MAXI_PAY_STATUS -> NotificationMessage.MessageData.MaxiPay(
                paymentUuid = requireNotNull(data[NotificationDataKeys.MAXI_PAY_UUID]).toString(),
            )

            PushTypeAction.MAXI_PAY_CONFIRMATION -> NotificationMessage.MessageData.MaxiPay(
                paymentUuid = requireNotNull(data[NotificationDataKeys.MAXI_PAY_UUID]).toString(),
            )

            PushTypeAction.MESSAGE,
            PushTypeAction.DELIVERY,
            PushTypeAction.COUPON_STATUS_CHANGE,
            -> null
        }

        return NotificationMessage(
            pushTypeAction = this,
            notificationId,
            pushId,
            analyticsLabel,
            notificationData,
            messageData,
        )
    }

    private suspend fun SilentMessage.handle() {
        when (this) {
            is SilentMessage.UpdateCouponStatus -> withContext(ioDispatcher) {
                updateCouponStatusInteractor.updateCouponStatus(couponId, couponStatus)
            }
        }
    }

    private suspend fun NotificationMessage.handle() {
        logNotificationView()
        createNotificationChannel()
        show()

        if (pushTypeAction == PushTypeAction.MAXI_PAY_CONFIRMATION &&
            messageData is NotificationMessage.MessageData.MaxiPay
        ) {
            deepLinkInteractor.saveDeepLink(
                DeepLinkType.OpenMaxiPayPaymentConfirmation(
                    messageData.paymentUuid,
                    notificationId,
                ),
            )
        }
    }

    private fun NotificationMessage.logNotificationView() {
        when (pushTypeAction) {
            PushTypeAction.MESSAGE,
            PushTypeAction.POST,
            PushTypeAction.DELIVERY,
            PushTypeAction.COUPON_STATUS_CHANGE,
            PushTypeAction.CRM_ACTIONS,
            PushTypeAction.DELIVERY_PROMO_CODES,
            PushTypeAction.MAXI_PAY_CONFIRMATION,
            PushTypeAction.MAXI_PAY_STATUS,
            -> return
        }
    }

    private fun createNotificationChannel() {
        maxiNotificationManager.createNotificationChannel(
            NotificationsChannel.ID,
            NotificationsChannel.NAME,
            NotificationsChannel.IMPORTANCE,
        )
    }

    private suspend fun NotificationMessage.show() {
        val requestCode = System.currentTimeMillis().toInt()
        val pendingIntent = PendingIntent.getActivity(
            context,
            requestCode,
            splashIntent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
        )

        val notificationBuilder = NotificationCompat.Builder(context, NotificationsChannel.ID)
            .setSmallIcon(R.drawable.ic_push_notification)
            .setColor(ContextCompat.getColor(context, UIKitR.color.primary_color))
            .setContentTitle(notificationData.title)
            .setContentText(notificationData.body)
            .setStyle(NotificationCompat.BigTextStyle().bigText(notificationData.body))
            .setContentIntent(pendingIntent)
            .setDefaults(Notification.DEFAULT_ALL)
            .setPriority(NotificationCompat.PRIORITY_MAX)
            .setAutoCancel(true)

        notificationData.image?.let { image ->
            val imageBitmap = withContext(ioDispatcher) {
                loadPushImage(image)
            }
            val notificationStyle = NotificationCompat.BigPictureStyle()
                .bigPicture(imageBitmap)
                .bigLargeIcon(null as Bitmap?)
            notificationBuilder.apply {
                setLargeIcon(imageBitmap)
                setStyle(notificationStyle)
            }
        }

        val notification = notificationBuilder.build()
        maxiNotificationManager.showNotification(notificationId, notification)
    }

    private suspend fun loadPushImage(imageUrl: String): Bitmap? = suspendCancellableCoroutine { continuation ->
        val bitmapFutureTarget = Glide.with(context)
            .load(imageUrl)
            .withLoadListener(
                object : ImageLoadListener {
                    override fun onLoadSuccess(drawable: Drawable) {
                        continuation.resume(drawable.toBitmap())
                    }

                    override fun onLoadFailed(exception: Exception?) {
                        val loadError = exception ?: error("Failed to load image $imageUrl")
                        continuation.resumeWithException(loadError)
                    }
                },
            )
            .submit()

        continuation.invokeOnCancellation {
            bitmapFutureTarget.cancel(true)
        }
    }

    private val NotificationMessage.splashIntent: Intent
        get() = Intent(context, SplashActivity::class.java).apply {
            action = pushTypeAction.actionName
            flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP

            pushId?.let { putExtra(NotificationDataKeys.PUSH_ID, it) }
            analyticsLabel?.let { putExtra(NotificationDataKeys.ANALYTICS_LABEL, it) }

            when (messageData) {
                null -> {}

                is NotificationMessage.MessageData.PostData -> {
                    putExtra(NotificationDataKeys.POST_ID, messageData.postId)
                }

                is NotificationMessage.MessageData.DeliveryNpsData -> {
                    putExtra(NotificationDataKeys.ORDER_ID, messageData.orderId)
                }

                is NotificationMessage.MessageData.DeliveryPromoCodesData -> {
                    putExtra(NotificationDataKeys.PROMO_CODE, messageData.promoCode)
                }

                is NotificationMessage.MessageData.MaxiPay -> {
                    putExtra(NotificationDataKeys.MAXI_PAY_UUID, messageData.paymentUuid)
                }

                is NotificationMessage.MessageData.CrmData -> {
                    putExtra(NotificationDataKeys.CRM_TRANSITION_TYPE, messageData.transitionType)
                    messageData.value?.let {
                        putExtra(NotificationDataKeys.CRM_VALUE, it)
                    }
                }
            }
        }

    companion object {

        private object NotificationsChannel {
            const val ID = "MAXI_NOTIFICATIONS_CHANNEL"
            const val NAME = "MAXI NOTIFICATIONS"
            const val IMPORTANCE = NotificationManager.IMPORTANCE_DEFAULT
        }

        private object MessageSettingsKeys {
            const val SHOW_IGNORE_TIME = "show_ignore_time"
            const val CLICK_ACTION = "click_action"
        }

        private object NotificationSettingsKeys {
            const val TITLE = "title"
            const val BODY = "body"
            const val IMAGE = "image"
        }

        object NotificationDataKeys {
            const val NOTIFICATION_ID = "notification_id"
            const val PUSH_ID = "push_id"
            const val ANALYTICS_LABEL = "analytics_label"

            const val POST_ID = "post_id"
            const val ORDER_ID = "order_id"
            const val PROMO_CODE = "promo_code"

            const val CRM_TRANSITION_TYPE = "transition_type"
            const val CRM_VALUE = "value"

            const val COUPON_ID = "coupon_id"
            const val COUPON_STATUS = "coupon_status"

            const val MAXI_PAY_UUID = "uuid"
        }
    }
}
package ru.maxi.mobile.service.notification

/**
 * Типы уведомления
 */
enum class PushTypeAction(val actionName: String) {

    POST(".SHOW_POST_NOTIFICATION"),
    MESSAGE(".SHOW_MESSAGE"),
    DELIVERY(".DELIVERY_NOTIFICATION"),
    DELIVERY_PROMO_CODES(".DELIVERY_PROMOCODES_NOTIFICATION"),
    COUPON_STATUS_CHANGE(".COUPON_STATUS_CHANGE_NOTIFICATION"),
    CRM_ACTIONS(".CRM_ACTIONS_PUSH"),
    MAXI_PAY_CONFIRMATION(".MAXI_PAY_CONFIRMATION"),
    MAXI_PAY_STATUS(".MAXI_PAY_STATUS"),
    ;

    companion object {
        fun getByActionName(actionName: String?): PushTypeAction? =
            entries.firstOrNull { it.actionName == actionName }
    }
}
package ru.maxi.mobile.ui.splash

import android.content.Intent
import android.os.Bundle
import androidx.core.os.BundleCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.work.WorkManager
import com.axmor.maxi.AgreementActivity
import com.axmor.maxi.Constants
import com.axmor.maxi.UserPolicyActivity
import com.axmor.maxi.model.user.UserInfoProvider
import com.axmor.maxi.view.main.MainNavigationActivity
import com.axmor.maxi.view.main.TabType
import ru.maxi.mobile.MyTrackerInitializer
import ru.maxi.mobile.base.ui.BaseActivity
import ru.maxi.mobile.common.card.repository.local.LocalCardRepository
import ru.maxi.mobile.common.client.repository.local.LocalClientRepository
import ru.maxi.mobile.entity.app.AppIntentData
import ru.maxi.mobile.feature.achievements.AchievementsScreens
import ru.maxi.mobile.feature.analytics.model.events.AnalyticsPushEvent
import ru.maxi.mobile.feature.analytics.model.eventsource.PushCouponDetailsEventSource
import ru.maxi.mobile.feature.analytics.model.eventsource.PushPostEventSource
import ru.maxi.mobile.feature.analytics.model.eventsource.PushProductEventSource
import ru.maxi.mobile.feature.analytics.usecase.AnalyticsUseCase
import ru.maxi.mobile.feature.appLink.AppLinkParser
import ru.maxi.mobile.feature.city.repository.local.LocalCityRepository
import ru.maxi.mobile.presentation.auth.AuthScreens
import ru.maxi.mobile.repositories.client.local.LocalUserPolicyRepository
import ru.maxi.mobile.repositories.deeplink.DeepLinkType
import ru.maxi.mobile.service.notification.CRMNotificationType
import ru.maxi.mobile.service.notification.PushTypeAction
import ru.maxi.mobile.service.notification.ReadNotificationWorker
import ru.maxi.mobile.service.notification.RemoteMessageHandler
import javax.inject.Inject

/**
 * Splash-экран при запуске приложения
 */
class SplashActivity : BaseActivity() {

    private var appIntentData: AppIntentData? = null

    private var pushId: Long? = null
    private var analyticsLabel: String? = null

    @Inject
    lateinit var workManager: WorkManager

    @Inject
    lateinit var localClientRepository: LocalClientRepository

    @Inject
    lateinit var localCardRepository: LocalCardRepository

    @Inject
    lateinit var localUserPolicyRepository: LocalUserPolicyRepository

    @Inject
    lateinit var userInfoProvider: UserInfoProvider

    @Inject
    lateinit var localCityRepository: LocalCityRepository

    @Inject
    lateinit var analyticsUseCase: AnalyticsUseCase

    override fun onCreate(savedInstanceState: Bundle?) {
        activityComponent.inject(this)
        installSplashScreen()
        super.onCreate(savedInstanceState)
    }

    override fun onStart() {
        super.onStart()
        PushTypeAction.getByActionName(intent.action)
            ?.let { pushTypeAction -> parsePushIntentData(intent.extras, pushTypeAction) }
            ?: (MyTrackerInitializer.handleDeeplink(intent) ?: intent.data)
                ?.let(AppLinkParser::parseUri)
                ?.let { appIntentData = AppIntentData.OpenDeepLink(it) }
    }

    override fun onResume() {
        super.onResume()
        checkRules()
    }

    private fun parsePushIntentData(bundle: Bundle?, action: PushTypeAction) {
        val pushId = bundle?.getLong(RemoteMessageHandler.Companion.NotificationDataKeys.PUSH_ID)
        this.pushId = pushId
        this.analyticsLabel = bundle?.getString(RemoteMessageHandler.Companion.NotificationDataKeys.ANALYTICS_LABEL)
        appIntentData = when (action) {
            PushTypeAction.POST -> {
                val postId = bundle?.getLong(RemoteMessageHandler.Companion.NotificationDataKeys.POST_ID)
                if (pushId != null && postId != null) {
                    ReadNotificationWorker.enqueueWorkWith(workManager, pushId)
                    AppIntentData.OpenDeepLink(DeepLinkType.OpenPost(postId, PushPostEventSource))
                } else {
                    null
                }
            }

            PushTypeAction.MESSAGE -> AppIntentData.OpenDeepLink(DeepLinkType.SwitchTab(TabType.MESSAGES_TAB))
            PushTypeAction.DELIVERY -> AppIntentData.UpdateDeliveryOrderStatus

            PushTypeAction.COUPON_STATUS_CHANGE -> null
            PushTypeAction.CRM_ACTIONS -> parseCrmActionIntentData(bundle)
            PushTypeAction.DELIVERY_PROMO_CODES -> {
                bundle?.getString(RemoteMessageHandler.Companion.NotificationDataKeys.PROMO_CODE)
                    ?.let { promoCode ->
                        AppIntentData.OpenDeepLink(DeepLinkType.ShowDeliveryPromoCode(promoCode))
                    }
            }

            PushTypeAction.MAXI_PAY_CONFIRMATION -> {
                val paymentUuid =
                    bundle?.getString(RemoteMessageHandler.Companion.NotificationDataKeys.MAXI_PAY_UUID)
                val notificationId = bundle?.getInt(RemoteMessageHandler.Companion.NotificationDataKeys.NOTIFICATION_ID)
                if (paymentUuid != null && notificationId != null) {
                    AppIntentData.OpenDeepLink(
                        DeepLinkType.OpenMaxiPayPaymentConfirmation(
                            paymentUuid,
                            notificationId,
                        ),
                    )
                } else {
                    null
                }
            }

            PushTypeAction.MAXI_PAY_STATUS -> {
                val paymentUuid = bundle?.getString(RemoteMessageHandler.Companion.NotificationDataKeys.MAXI_PAY_UUID)
                paymentUuid?.let { AppIntentData.OpenDeepLink(DeepLinkType.OpenMaxiPayPaymentNotification(it)) }
            }
        }
    }

    private fun parseCrmActionIntentData(bundle: Bundle?): AppIntentData? {
        if (bundle == null) return null

        val notificationType = BundleCompat.getSerializable(
            bundle,
            RemoteMessageHandler.Companion.NotificationDataKeys.CRM_TRANSITION_TYPE,
            CRMNotificationType::class.java,
        ) ?: return null

        return when (notificationType) {
            CRMNotificationType.CATEGORY -> {
                bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.toLongOrNull()
                    ?.let { categoryId ->
                        AppIntentData.OpenDeepLink(DeepLinkType.OpenProductsCategory(categoryId))
                    }
            }

            CRMNotificationType.COUPON -> {
                val couponId = bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.toLongOrNull()
                AppIntentData.OpenDeepLink(DeepLinkType.OpenCoupons(couponId, PushCouponDetailsEventSource))
            }

            CRMNotificationType.CASHBACK -> AppIntentData.OpenDeepLink(DeepLinkType.OpenCashback)
            CRMNotificationType.MOMENT_DISCOUNT -> AppIntentData.OpenDeepLink(DeepLinkType.OpenMomentDiscount)
            CRMNotificationType.LOTTERY -> {
                val lotteryId = bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                AppIntentData.OpenDeepLink(DeepLinkType.OpenLottery(lotteryId))
            }

            CRMNotificationType.BIRTHDAY -> AppIntentData.OpenDeepLink(DeepLinkType.OpenBirthdayPromo)
            CRMNotificationType.GIFT_CARD -> AppIntentData.OpenDeepLink(DeepLinkType.OpenGiftCardPromo)
            CRMNotificationType.CATALOG -> AppIntentData.OpenDeepLink(DeepLinkType.SwitchTab(TabType.CATALOG_TAB))
            CRMNotificationType.CATEGORY_COLLECTION -> {
                bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.toLongOrNull()
                    ?.let { collectionId ->
                        AppIntentData.OpenDeepLink(
                            DeepLinkType.OpenCategoryCollection(collectionId),
                        )
                    }
            }

            CRMNotificationType.PRODUCT_COLLECTION -> {
                bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.toLongOrNull()
                    ?.let { productCollectionId ->
                        AppIntentData.OpenDeepLink(
                            DeepLinkType.OpenProductCollection(productCollectionId),
                        )
                    }
            }

            CRMNotificationType.USER_PROFILE -> AppIntentData.OpenDeepLink(DeepLinkType.OpenClientData)
            CRMNotificationType.USER_CARD -> AppIntentData.OpenDeepLink(DeepLinkType.SwitchTab(TabType.CARD_TAB))
            CRMNotificationType.ADVENT_CALENDAR -> AppIntentData.OpenDeepLink(DeepLinkType.OpenAdventCalendar)
            CRMNotificationType.CLUBS -> {
                bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.toLongOrNull()
                    ?.let { clubId ->
                        AppIntentData.OpenDeepLink(
                            DeepLinkType.OpenClub(clubId),
                        )
                    }
            }

            CRMNotificationType.CLUB_COUPONS -> {
                bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.toLongOrNull()
                    ?.let { clubId ->
                        AppIntentData.OpenDeepLink(
                            DeepLinkType.OpenClubCoupons(clubId),
                        )
                    }
            }

            CRMNotificationType.CLUBS_LIST -> AppIntentData.OpenDeepLink(DeepLinkType.OpenClubsList)

            CRMNotificationType.POPULAR_DISCOUNT -> AppIntentData.OpenDeepLink(DeepLinkType.OpenPopularProductsDiscount)
            CRMNotificationType.WELCOME_PACKAGE -> AppIntentData.OpenDeepLink(DeepLinkType.OpenWelcomePackagePromo)
            CRMNotificationType.PARTNERS_DISCOUNTS -> {
                val discountId = bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.toLongOrNull()
                AppIntentData.OpenDeepLink(DeepLinkType.OpenPartnersDiscounts(discountId))
            }

            CRMNotificationType.WEB_URL -> {
                bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.let { url ->
                        AppIntentData.OpenDeepLink(DeepLinkType.OpenExternalLink(url))
                    }
            }

            CRMNotificationType.PROFILE_EXTRA_DATA -> AppIntentData.OpenDeepLink(DeepLinkType.OpenClientExtraData)

            CRMNotificationType.PROMO_CODE -> {
                val promoCode = bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                AppIntentData.OpenDeepLink(DeepLinkType.ShowOfflinePromoCode(promoCode))
            }

            CRMNotificationType.COUPON_FOR_CHIPS -> AppIntentData.OpenDeepLink(DeepLinkType.OpenCouponsForChips)
            CRMNotificationType.COUPON_FOR_CHIPS_PROMO ->
                AppIntentData.OpenDeepLink(DeepLinkType.OpenCouponsForChipsPromo)

            CRMNotificationType.SCRATCH_CARDS ->
                AppIntentData.OpenDeepLink(DeepLinkType.OpenScratchCards)

            CRMNotificationType.MARATHON -> AppIntentData.OpenDeepLink(DeepLinkType.OpenMarathon)
            CRMNotificationType.MAXI_PAY -> AppIntentData.OpenDeepLink(DeepLinkType.OpenMaxiPay)
            CRMNotificationType.SHOPPING_LIST -> AppIntentData.OpenDeepLink(DeepLinkType.OpenShoppingList)
            CRMNotificationType.CHIPS -> AppIntentData.OpenDeepLink(DeepLinkType.OpenChips)
            CRMNotificationType.SHARE_CHIPS -> AppIntentData.OpenDeepLink(DeepLinkType.OpenShareChips)

            CRMNotificationType.PRODUCT -> {
                bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                    ?.toLongOrNull()
                    ?.let { productId ->
                        AppIntentData.OpenDeepLink(
                            DeepLinkType.OpenProductDetails(
                                productId = productId,
                                eventSource = PushProductEventSource,
                            ),
                        )
                    }
            }

            CRMNotificationType.ACHIEVEMENTS -> {
                val achievementId = bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                AppIntentData.OpenDeepLink(
                    DeepLinkType.OpenAchievements(
                        AchievementsScreens.AchievementsTab.IN_PROGRESS_TAB,
                        achievementId?.toLongOrNull(),
                    ),
                )
            }

            CRMNotificationType.ACHIEVEMENTS_RECEIVED -> {
                val achievementId = bundle.getString(RemoteMessageHandler.Companion.NotificationDataKeys.CRM_VALUE)
                AppIntentData.OpenDeepLink(
                    DeepLinkType.OpenAchievements(
                        AchievementsScreens.AchievementsTab.RECEIVED_TAB,
                        achievementId?.toLongOrNull(),
                    ),
                )
            }
        }
    }

    private fun checkRules() {
        if (localClientRepository.isUserAnonymous() || localUserPolicyRepository.getUserPolicy()?.isAccepted != false) {
            openNextScreen()
        } else {
            val intent = Intent(this, UserPolicyActivity::class.java)
            startActivity(intent)
        }
    }

    private fun openNextScreen() {
        if (userInfoProvider.needAcceptAgreement()) {
            return openAgreementScreen()
        }

        val isUserAuthenticated = localClientRepository.isUserAuthenticated() &&
            localCardRepository.hasCardNumber() &&
            localCityRepository.getCurrentCityCode().isNotBlank()
        if (localClientRepository.isAuthSkipped() || isUserAuthenticated) {
            return openMainScreen()
        }

        return openAuthScreen()
    }

    private fun openAgreementScreen() {
        val intent = Intent(this, AgreementActivity::class.java)
        startActivity(intent)
        finish()
    }

    private fun openAuthScreen() {
        val intent = AuthScreens.AuthContainerScreen().createIntent(this)
        startActivity(intent)
        finish()
    }

    private fun openMainScreen() {
        val intent = Intent(this, MainNavigationActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        appIntentData?.let {
            intent.putExtra(Constants.EXTRA_INTENT_DATA, it)
            sendPushOpenAnalytic(it)
        } ?: intent.putExtras(getIntent())
        startActivity(intent)
        finish()
    }

    private fun sendPushOpenAnalytic(intentData: AppIntentData) {
        val eventAdditionalValue = when (intentData) {
            is AppIntentData.OpenDeepLink -> when (val deepLink = intentData.deepLink) {
                is DeepLinkType.OpenPost -> deepLink.postId.toString()
                is DeepLinkType.ShowDeliveryPromoCode -> deepLink.promoCode
                is DeepLinkType.OpenCategoryCollection -> deepLink.collectionId.toString()
                is DeepLinkType.OpenProductsCategory -> deepLink.categoryId.toString()
                else -> null
            }

            else -> null
        }
        analyticsUseCase log AnalyticsPushEvent.AppOpenFromPush(
            intentData,
            pushId,
            eventAdditionalValue,
            analyticsLabel,
        )
    }
}