package com.tangem.feature.wallet.presentation.wallet.state.model

import androidx.annotation.DrawableRes
import androidx.compose.runtime.Immutable
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsState
import com.tangem.core.ui.components.notifications.NotificationConfig.IconTint
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.pluralReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
import com.tangem.feature.wallet.impl.R
import com.tangem.core.res.R as CoreResR
import com.tangem.core.ui.R as CoreUiR

/**
 * Wallet notification component state
 *
 * @property config state
 *
[REDACTED_AUTHOR]
 */
@Immutable
sealed class WalletNotification(val config: NotificationConfig) {

    sealed class Critical(
        title: TextReference,
        subtitle: TextReference,
        buttonsState: NotificationConfig.ButtonsState? = null,
    ) : WalletNotification(
        config = NotificationConfig(
            title = title,
            subtitle = subtitle,
            iconResId = R.drawable.ic_alert_circle_24,
            buttonsState = buttonsState,
        ),
    ) {

        data object DevCard : Critical(
            title = resourceReference(id = R.string.warning_developer_card_title),
            subtitle = resourceReference(id = R.string.warning_developer_card_message),
        )

        data object FailedCardValidation : Critical(
            title = resourceReference(id = R.string.warning_failed_to_verify_card_title),
            subtitle = resourceReference(id = R.string.warning_failed_to_verify_card_message),
        )

        data class BackupError(val onSupportClick: () -> Unit) : Critical(
            title = resourceReference(R.string.warning_backup_error_attention_title),
            subtitle = resourceReference(R.string.warning_backup_error_attention_message),
            buttonsState = ButtonsState.PrimaryButtonConfig(
                text = resourceReference(id = R.string.common_contact_support),
                onClick = onSupportClick,
            ),
        )
    }

    sealed class Warning(
        title: TextReference,
        subtitle: TextReference,
        buttonsState: NotificationConfig.ButtonsState? = null,
        onClick: (() -> Unit)? = null,
        onCloseClick: (() -> Unit)? = null,
    ) : WalletNotification(
        config = NotificationConfig(
            title = title,
            subtitle = subtitle,
            iconResId = R.drawable.img_attention_20,
            buttonsState = buttonsState,
            onClick = onClick,
            onCloseClick = onCloseClick,
        ),
    ) {

        data class MissingBackup(val onStartBackupClick: () -> Unit) : Warning(
            title = resourceReference(id = R.string.warning_no_backup_title),
            subtitle = resourceReference(id = R.string.warning_no_backup_message),
            buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
                text = resourceReference(id = R.string.button_start_backup_process),
                onClick = onStartBackupClick,
            ),
        )

        data object NetworksUnreachable : Warning(
            title = resourceReference(id = R.string.warning_network_unreachable_title),
            subtitle = resourceReference(id = R.string.warning_network_unreachable_message),
        )

        data object SomeNetworksUnreachable : Warning(
            title = resourceReference(id = R.string.warning_some_networks_unreachable_title),
            subtitle = resourceReference(id = R.string.warning_some_networks_unreachable_message),
        )

        data class NumberOfSignedHashesIncorrect(val onCloseClick: () -> Unit) : Warning(
            title = resourceReference(id = R.string.warning_number_of_signed_hashes_incorrect_title),
            subtitle = resourceReference(id = R.string.warning_number_of_signed_hashes_incorrect_message),
            onCloseClick = onCloseClick,
        )

        data object TestNetCard : Warning(
            title = resourceReference(id = R.string.warning_testnet_card_title),
            subtitle = resourceReference(id = R.string.warning_testnet_card_message),
        )

        data class LowSignatures(val count: Int) : Warning(
            title = resourceReference(id = R.string.warning_low_signatures_title),
            subtitle = resourceReference(
                id = R.string.warning_low_signatures_message,
                formatArgs = wrappedList(count),
            ),
        )

        data object YeildSupplyApprove : Warning(
            title = resourceReference(R.string.yield_module_main_view_approve_notification_title),
            subtitle = resourceReference(R.string.yield_module_main_view_approve_notification_description),
        )

        data object TangemPayUnreachable : Warning(
            title = resourceReference(id = R.string.tangempay_temporarily_unavailable),
            subtitle = resourceReference(id = R.string.tangempay_service_unreachable_try_later),
        )

        data class TangemPayRefreshNeeded(
            private val onRefreshClick: () -> Unit,
            private val buttonText: TextReference,
            private val shouldShowProgress: Boolean,
        ) : Warning(
            title = resourceReference(id = R.string.tangempay_sync_needed_title),
            subtitle = resourceReference(id = R.string.tangempay_sync_needed_body),
            buttonsState = ButtonsState.PrimaryButtonConfig(
                text = buttonText,
                iconResId = R.drawable.ic_tangem_24,
                onClick = onRefreshClick,
                shouldShowProgress = shouldShowProgress,
            ),
        )
    }

    sealed class Informational(
        title: TextReference,
        subtitle: TextReference,
        buttonsState: NotificationConfig.ButtonsState? = null,
    ) : WalletNotification(
        config = NotificationConfig(
            title = title,
            subtitle = subtitle,
            iconResId = R.drawable.ic_alert_circle_24,
            buttonsState = buttonsState,
        ),
    ) {

        data class MissingAddresses(
            @DrawableRes val tangemIcon: Int?,
            val missingAddressesCount: Int,
            val onGenerateClick: () -> Unit,
        ) : Informational(
            title = resourceReference(id = R.string.warning_missing_derivation_title),
            subtitle = pluralReference(
                id = R.plurals.warning_missing_derivation_message,
                count = missingAddressesCount,
                formatArgs = wrappedList(missingAddressesCount),
            ),
            buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
                text = resourceReference(id = R.string.common_generate_addresses),
                iconResId = tangemIcon,
                onClick = onGenerateClick,
            ),
        )

        data class NoAccount(val network: String, val symbol: String, val amount: String) : Informational(
            title = resourceReference(id = R.string.warning_no_account_title),
            subtitle = resourceReference(
                id = R.string.no_account_generic,
                wrappedList(network, amount, symbol),
            ),
        )

        data object DemoCard : Informational(
            title = resourceReference(id = R.string.warning_demo_mode_title),
            subtitle = resourceReference(id = R.string.warning_demo_mode_message),
        )
    }

    data class UnlockWallets(val onClick: () -> Unit) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(id = R.string.common_access_denied),
            subtitle = resourceReference(
                id = R.string.warning_access_denied_message,
                formatArgs = wrappedList(
                    resourceReference(R.string.common_biometrics),
                ),
            ),
            iconResId = R.drawable.ic_locked_24,
            onClick = onClick,
        ),
    )

    data class UnlockVisaAccess(val onUnlockClick: () -> Unit) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(id = R.string.visa_unlock_notification_title),
            subtitle = resourceReference(id = R.string.visa_unlock_notification_subtitle),
            iconResId = R.drawable.ic_locked_24,
            buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
                text = resourceReference(id = R.string.visa_unlock_notification_button),
                iconResId = R.drawable.ic_tangem_24,
                onClick = onUnlockClick,
            ),
        ),
    )

    data class RateApp(
        val onLikeClick: () -> Unit,
        val onDislikeClick: () -> Unit,
        val onCloseClick: () -> Unit,
    ) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(id = R.string.warning_rate_app_title),
            subtitle = resourceReference(id = R.string.warning_rate_app_message),
            iconResId = R.drawable.ic_star_24,
            buttonsState = NotificationConfig.ButtonsState.PairButtonsConfig(
                primaryText = resourceReference(id = R.string.warning_button_like_it),
                onPrimaryClick = onLikeClick,
                secondaryText = resourceReference(id = R.string.warning_button_could_be_better),
                onSecondaryClick = onDislikeClick,
            ),
            onCloseClick = onCloseClick,
        ),
    )

    data class NoteMigration(val onClick: () -> Unit) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(R.string.wallet_promo_banner_title),
            subtitle = resourceReference(R.string.wallet_promo_banner_description),
            iconResId = R.drawable.banner_note_migration,
            buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
                text = resourceReference(R.string.wallet_promo_banner_button_title),
                onClick = onClick,
            ),
        ),
    )

    data class AddFunds(val onClick: () -> Unit) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(CoreResR.string.main_add_funds_promo_title),
            subtitle = resourceReference(CoreResR.string.main_add_funds_promo_description),
            iconResId = CoreUiR.drawable.ic_coins_swap_24,
            iconTint = IconTint.Accent,
            buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
                text = resourceReference(CoreResR.string.common_add_funds),
                onClick = onClick,
            ),
        ),
    )

    data object UsedOutdatedData : WalletNotification(
        config = NotificationConfig(
            subtitle = resourceReference(R.string.warning_some_token_balances_not_updated),
            iconResId = R.drawable.ic_error_sync_24,
        ),
    )

    data class FinishWalletActivation(
        val type: WalletActivationBannerType,
        val buttonsState: ButtonsState,
        val isBackupExists: Boolean,
    ) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(R.string.hw_activation_need_title),
            subtitle = if (isBackupExists) {
                resourceReference(R.string.hw_activation_need_warning_description)
            } else {
                resourceReference(R.string.hw_activation_need_description)
            },
            iconResId = R.drawable.img_knight_shield_32,
            iconTint = when (type) {
                WalletActivationBannerType.Attention -> IconTint.Attention
                WalletActivationBannerType.Warning -> IconTint.Warning
            },
            buttonsState = buttonsState,
        ),
    )

    data class PushNotifications(
        val onCloseClick: () -> Unit,
        val onEnabledClick: () -> Unit,
    ) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(R.string.user_push_notification_banner_title),
            subtitle = resourceReference(R.string.user_push_notification_banner_subtitle),
            iconResId = R.drawable.img_push_reminder,
            onCloseClick = onCloseClick,
            buttonsState = NotificationConfig.ButtonsState.PairButtonsConfig(
                primaryText = resourceReference(id = R.string.common_enable),
                onPrimaryClick = onEnabledClick,
                secondaryText = resourceReference(id = R.string.common_later),
                onSecondaryClick = onCloseClick,
            ),
            iconSize = 54.dp,
        ),
    )

    data class CloreMigration(
        val onStartMigrationClick: () -> Unit,
    ) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(com.tangem.core.res.R.string.warning_clore_migration_title),
            subtitle = resourceReference(com.tangem.core.res.R.string.warning_clore_migration_description),
            iconResId = R.drawable.img_attention_20,
            buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
                text = resourceReference(com.tangem.core.res.R.string.warning_clore_migration_button),
                onClick = onStartMigrationClick,
            ),
        ),
    )

    data class UpgradeHotWalletPromo(
        val onLaterClick: () -> Unit,
        val onUpgradeClick: () -> Unit,
    ) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(R.string.hw_upgrade_to_cold_banner_title),
            subtitle = resourceReference(R.string.hw_upgrade_to_cold_banner_description),
            iconResId = R.drawable.img_tangem_wallet_72,
            buttonsState = ButtonsState.PairButtonsConfig(
                primaryText = resourceReference(R.string.hw_upgrade),
                onPrimaryClick = onUpgradeClick,
                secondaryText = resourceReference(R.string.common_later),
                onSecondaryClick = onLaterClick,
            ),
            iconSize = 72.dp,
        ),
    )

    data class YieldBoostPromo(
        val onClick: () -> Unit,
        val onCloseClick: () -> Unit,
    ) : WalletNotification(
        config = NotificationConfig(
            title = com.tangem.core.ui.extensions.combinedReference(
                resourceReference(com.tangem.core.res.R.string.yield_apy_boost_banner_title),
                stringReference(" · "),
                resourceReference(com.tangem.core.res.R.string.yield_apy_boost_banner_title_apy_multiplied),
            ),
            subtitle = resourceReference(com.tangem.core.res.R.string.yield_apy_boost_banner_subtitle),
            iconResId = com.tangem.core.ui.R.drawable.ic_analytics_up_24,
            iconTint = IconTint.Accent,
            onCloseClick = onCloseClick,
            buttonsState = ButtonsState.PrimaryButtonConfig(
                text = resourceReference(com.tangem.core.res.R.string.yield_apy_boost_banner_button_title),
                onClick = onClick,
            ),
        ),
    )

    data class AssetsDiscoveryCompleted(
        val onCloseClick: () -> Unit,
        val onManageTokensClick: () -> Unit,
    ) : WalletNotification(
        config = NotificationConfig(
            title = resourceReference(R.string.initial_wallet_sync_banner_title),
            subtitle = resourceReference(R.string.initial_wallet_sync_banner_description),
            iconResId = R.drawable.ic_check_circle_24,
            iconTint = IconTint.Accent,
            onCloseClick = onCloseClick,
            buttonsState = ButtonsState.SecondaryButtonConfig(
                text = resourceReference(R.string.main_manage_tokens),
                onClick = onManageTokensClick,
            ),
        ),
    )

    data class CreateTangemPayAccount(val onClick: () -> Unit, val onCloseClick: () -> Unit) : WalletNotification(
        config = NotificationConfig(
            subtitle = resourceReference(R.string.tangempay_onboarding_banner_description),
            iconResId = R.drawable.img_tangem_pay_visa_banner,
        ),
    )
}