package com.tangem.features.swap.v2.impl.amount.entity

import androidx.compose.runtime.Immutable
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.core.ui.components.atoms.text.TextEllipsis
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.express.models.ExpressRateType
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.swap.models.SwapAmountType
import com.tangem.domain.swap.models.SwapCurrencies
import com.tangem.domain.swap.models.SwapDirection
import com.tangem.domain.swap.models.SwapRateMode
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
import kotlinx.collections.immutable.ImmutableList

@Immutable
internal sealed class SwapAmountUM {

    abstract val isPrimaryButtonEnabled: Boolean
    abstract val primaryAmount: SwapAmountFieldUM
    abstract val secondaryAmount: SwapAmountFieldUM
    abstract val selectedAmountType: SwapAmountType
    abstract val swapDirection: SwapDirection

    data class Empty(
        override val swapDirection: SwapDirection,
    ) : SwapAmountUM() {
        override val isPrimaryButtonEnabled = false
        override val selectedAmountType = SwapAmountType.From
        override val primaryAmount = SwapAmountFieldUM.Empty(SwapAmountType.From)
        override val secondaryAmount = SwapAmountFieldUM.Empty(SwapAmountType.To)
    }

    data class Content(
        override val isPrimaryButtonEnabled: Boolean,
        override val swapDirection: SwapDirection,
        override val selectedAmountType: SwapAmountType,

        // two amount fields
        override val primaryAmount: SwapAmountFieldUM,
        override val secondaryAmount: SwapAmountFieldUM,
        val primaryCryptoCurrencyStatus: CryptoCurrencyStatus,
        val secondaryCryptoCurrencyStatus: CryptoCurrencyStatus?,

        // selected swap route
        val swapRateType: ExpressRateType,
        val swapRateMode: SwapRateMode,
        val priceImpact: PriceImpact?,

        // swap models
        val swapCurrencies: SwapCurrencies,
        val swapQuotes: ImmutableList<SwapQuoteUM>,
        val selectedQuote: SwapQuoteUM,
        val isShowFCAWarning: Boolean,

        // extra data
        val appCurrency: AppCurrency?,
        val isShowBestRateAnimation: Boolean,
    ) : SwapAmountUM()
}

@Immutable
sealed class SwapAmountFieldUM {
    abstract val amountType: SwapAmountType
    abstract val amountField: AmountState

    data class Empty(
        override val amountType: SwapAmountType,
    ) : SwapAmountFieldUM() {
        override val amountField: AmountState = AmountState.Empty
    }

    data class Loading(
        override val amountType: SwapAmountType,
    ) : SwapAmountFieldUM() {
        override val amountField: AmountState = AmountState.Empty
    }

    data class Content(
        override val amountType: SwapAmountType,
        override val amountField: AmountState,
        val title: TextReference,
        val subtitleLeft: TextReference,
        val subtitleRight: TextReference,
        val subtitleEllipsisLeft: TextEllipsis,
        val subtitleEllipsisRight: TextEllipsis,
        val isClickEnabled: Boolean,
        val shouldShowApproximatePrefix: Boolean,
        val sendSubtitle: SendSubtitleUM? = null,
    ) : SwapAmountFieldUM()
}

@Immutable
data class PriceImpact(
    val value: TextReference,
    val amountSignificance: AmountSignificance,
    val type: Type,
) {
    enum class Type {
        NONE, LOW, MEDIUM, HIGH
    }

    enum class AmountSignificance {
        LOW, MEDIUM, HIGH
    }

    fun shouldDisableButton(): Boolean {
        return type == Type.HIGH && amountSignificance == AmountSignificance.HIGH
    }

    fun shouldShowWarning(): Boolean {
        return type.ordinal > Type.LOW.ordinal && amountSignificance.ordinal > AmountSignificance.LOW.ordinal
    }

    companion object {
        val Empty = PriceImpact(
            value = TextReference.EMPTY,
            amountSignificance = AmountSignificance.LOW,
            type = Type.NONE,
        )
    }
}

@Immutable
data class SendSubtitleUM(
    val label: TextReference,
    val value: TextReference,
    val valueEllipsis: TextEllipsis,
)