package com.tangem.feature.wallet.child.organizetokens.model.converter.items

import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.format.bigdecimal.BigDecimalFormatConstants
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.staking.StakingBalance
import com.tangem.common.getTotalWithRewardsStakingBalance
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
import com.tangem.feature.wallet.child.organizetokens.model.common.getGroupHeaderId
import com.tangem.feature.wallet.child.organizetokens.model.common.getTokenItemId
import com.tangem.utils.converter.Converter
import com.tangem.utils.extensions.orZero
import java.math.BigDecimal

internal class CryptoCurrencyToDraggableItemConverter(
    private val appCurrency: AppCurrency,
) : Converter<AccountCryptoCurrencyStatus, DraggableItem.Token> {

    private val iconStateConverter = CryptoCurrencyToIconStateConverter()

    override fun convert(value: AccountCryptoCurrencyStatus): DraggableItem.Token {
        return createDraggableToken(value)
    }

    private fun createDraggableToken(accountCryptoCurrencyStatus: AccountCryptoCurrencyStatus): DraggableItem.Token {
        val (account, currencyStatus) = accountCryptoCurrencyStatus
        return DraggableItem.Token(
            tokenItemState = createTokenItemState(currencyStatus, appCurrency),
            groupId = getGroupHeaderId(currencyStatus.currency.network),
            accountId = account.accountId.value,
        )
    }

    private fun createTokenItemState(
        currencyStatus: CryptoCurrencyStatus,
        appCurrency: AppCurrency,
    ): TokenItemState.Draggable {
        val currency = currencyStatus.currency

        return TokenItemState.Draggable(
            id = getTokenItemId(currency.id),
            iconState = iconStateConverter.convert(currencyStatus),
            titleState = TokenItemState.TitleState.Content(text = stringReference(currency.name)),
            subtitle2State = if (currencyStatus.value.isError) {
                TokenItemState.Subtitle2State.Unreachable
            } else {
                TokenItemState.Subtitle2State.TextContent(text = getFormattedFiatAmount(currencyStatus, appCurrency))
            },
        )
    }

    private fun getFormattedFiatAmount(currency: CryptoCurrencyStatus, appCurrency: AppCurrency): String {
        val stakingBalance = currency.value.stakingBalance as? StakingBalance.Data
        val fiatRate = currency.value.fiatRate ?: BigDecimal.ZERO
        val fiatStakingBalance = stakingBalance?.getTotalWithRewardsStakingBalance(currency.currency.network.rawId)
            ?.multiply(fiatRate).orZero()

        val fiatAmount = currency.value.fiatAmount ?: return BigDecimalFormatConstants.EMPTY_BALANCE_SIGN
        return (fiatAmount + fiatStakingBalance).format { fiat(appCurrency.code, appCurrency.symbol) }
    }
}