package com.tangem.features.details.utils

import com.tangem.common.routing.AppRoute
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.ui.components.block.model.BlockUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.settings.HotWalletRestrictionManager
import com.tangem.features.details.entity.DetailsItemUM
import com.tangem.features.details.impl.R
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
import javax.inject.Inject

private const val TANGEM_PAY_ITEM_ID = "get_tangem_pay"
private const val VIRTUAL_ACCOUNT_ITEM_ID = "get_virtual_account"

@ModelScoped
internal class ItemsBuilder @Inject constructor(
    private val router: Router,
    private val hotWalletRestrictionManager: HotWalletRestrictionManager,
) {

    @Suppress("LongParameterList")
    fun buildAll(
        isWalletConnectAvailable: Boolean,
        isAddressBookAvailable: Boolean,
        hasAnyMobileWallet: Boolean,
        userWalletId: UserWalletId,
        onSupportClick: () -> Unit,
        onBuyClick: () -> Unit,
    ): ImmutableList<DetailsItemUM> = buildList {
        if (isAddressBookAvailable) {
            buildWalletActionBlock(isWalletConnectAvailable, userWalletId)
        } else {
            buildWalletConnectBlock(isWalletConnectAvailable, userWalletId)?.let(::add)
        }
        buildUserWalletListBlock().let(::add)

        if (hotWalletRestrictionManager.isCreationEnabledSync() && hasAnyMobileWallet) {
            DetailsItemUM.UnderSectionText(
                id = "only_one_mobile_wallet_explanation",
                text = resourceReference(R.string.only_one_mobile_wallet_explanation),
            ).let(::add)
        }

        buildShopBlock(onBuyClick).let(::add)
        buildSettingsBlock().let(::add)
        buildSupportBlock(onSupportClick = onSupportClick).let(::add)
    }.toImmutableList()

    fun addTangemPayItem(items: ImmutableList<DetailsItemUM>, onClick: () -> Unit): ImmutableList<DetailsItemUM> {
        return items.toMutableList().map { block ->
            if (block.id == "shop" && block is DetailsItemUM.Basic) {
                val newItems = block
                    .items
                    .toMutableList()
                    .apply { add(getTangemPayItem(onClick = onClick)) }
                block.copy(items = newItems.toImmutableList())
            } else {
                block
            }
        }.toImmutableList()
    }

    fun removeTangemPayItem(items: ImmutableList<DetailsItemUM>): ImmutableList<DetailsItemUM> {
        return items.map { block ->
            if (block is DetailsItemUM.Basic && block.items.any { it.id == TANGEM_PAY_ITEM_ID }) {
                block.copy(items = block.items.filter { it.id != TANGEM_PAY_ITEM_ID }.toImmutableList())
            } else {
                block
            }
        }.toImmutableList()
    }

    fun addVirtualAccountItem(items: ImmutableList<DetailsItemUM>, onClick: () -> Unit): ImmutableList<DetailsItemUM> {
        return items.map { block ->
            if (block.id == "shop" && block is DetailsItemUM.Basic) {
                val newItems = block
                    .items
                    .toMutableList()
                    .apply { add(getVirtualAccountItem(onClick = onClick)) }
                block.copy(items = newItems.toImmutableList())
            } else {
                block
            }
        }.toImmutableList()
    }

    fun removeVirtualAccountItem(items: ImmutableList<DetailsItemUM>): ImmutableList<DetailsItemUM> {
        return items.map { block ->
            if (block is DetailsItemUM.Basic && block.items.any { it.id == VIRTUAL_ACCOUNT_ITEM_ID }) {
                block.copy(items = block.items.filter { it.id != VIRTUAL_ACCOUNT_ITEM_ID }.toImmutableList())
            } else {
                block
            }
        }.toImmutableList()
    }

    private fun buildWalletConnectBlock(isWalletConnectAvailable: Boolean, userWalletId: UserWalletId): DetailsItemUM? {
        return if (isWalletConnectAvailable) {
            DetailsItemUM.WalletConnect(
                onClick = { router.push(AppRoute.WalletConnectSessions(userWalletId)) },
            )
        } else {
            null
        }
    }

    private fun MutableList<DetailsItemUM>.buildWalletActionBlock(
        isWalletConnectAvailable: Boolean,
        userWalletId: UserWalletId,
    ) {
        val walletActionItems = buildList {
            if (isWalletConnectAvailable) add(buildWalletConnectButton(userWalletId))
            add(buildAddressBookButton())
        }.toImmutableList()
        if (walletActionItems.isNotEmpty()) {
            add(DetailsItemUM.WalletActionBlock(walletActionItems))
        }
    }

    private fun buildWalletConnectButton(
        userWalletId: UserWalletId,
    ): DetailsItemUM.WalletActionBlock.Item.WalletConnect {
        return DetailsItemUM.WalletActionBlock.Item.WalletConnect(
            onClick = { router.push(AppRoute.WalletConnectSessions(userWalletId)) },
        )
    }

    private fun buildAddressBookButton(): DetailsItemUM.WalletActionBlock.Item.AddressBook {
        return DetailsItemUM.WalletActionBlock.Item.AddressBook(
            onClick = { router.push(AppRoute.AddressBook()) },
        )
    }

    private fun buildUserWalletListBlock(): DetailsItemUM = DetailsItemUM.UserWalletList

    private fun buildShopBlock(onBuyClick: () -> Unit): DetailsItemUM = DetailsItemUM.Basic(
        id = "shop",
        items = persistentListOf(
            DetailsItemUM.Basic.Item(
                id = "buy_tangem_wallet",
                block = BlockUM(
                    text = resourceReference(R.string.details_buy_wallet),
                    iconRes = R.drawable.ic_tangem_24,
                    onClick = onBuyClick,
                ),
            ),
        ),
    )

    private fun buildSettingsBlock(): DetailsItemUM = DetailsItemUM.Basic(
        id = "settings",
        items = buildList {
            DetailsItemUM.Basic.Item(
                id = "app_settings",
                block = BlockUM(
                    text = resourceReference(R.string.app_settings_title),
                    iconRes = R.drawable.ic_settings_24,
                    onClick = { router.push(AppRoute.AppSettings) },
                ),
            ).let(::add)
        }.toImmutableList(),
    )

    private fun buildSupportBlock(onSupportClick: () -> Unit): DetailsItemUM = DetailsItemUM.Basic(
        id = "support",
        items = buildList {
            DetailsItemUM.Basic.Item(
                id = "contact_support",
                block = BlockUM(
                    text = resourceReference(R.string.common_contact_support),
                    iconRes = R.drawable.ic_comment_24,
                    onClick = onSupportClick,
                ),
            ).let(::add)

            DetailsItemUM.Basic.Item(
                id = "disclaimer",
                block = BlockUM(
                    text = resourceReference(R.string.disclaimer_title),
                    iconRes = R.drawable.ic_text_24,
                    onClick = { router.push(AppRoute.Disclaimer(isTosAccepted = true)) },
                ),
            ).let(::add)
        }.toPersistentList(),
    )

    private fun getTangemPayItem(onClick: () -> Unit): DetailsItemUM.Basic.Item = DetailsItemUM.Basic.Item(
        id = TANGEM_PAY_ITEM_ID,
        block = BlockUM(
            text = resourceReference(R.string.tangempay_get_tangem_pay),
            iconRes = R.drawable.ic_tangem_pay_24,
            onClick = onClick,
        ),
    )

    private fun getVirtualAccountItem(onClick: () -> Unit): DetailsItemUM.Basic.Item = DetailsItemUM.Basic.Item(
        id = VIRTUAL_ACCOUNT_ITEM_ID,
        block = BlockUM(
            text = resourceReference(R.string.virtual_account_title),
            iconRes = R.drawable.ic_tangem_pay_24,
            onClick = onClick,
        ),
    )
}