package com.tangem.features.onramp.main.ui

import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemThemeRedesign
import com.tangem.core.ui.test.OnrampOffersBlockTestTags
import com.tangem.domain.onramp.model.OnrampPaymentMethod
import com.tangem.domain.onramp.model.PaymentMethodType
import com.tangem.features.marketing.api.MarketingBannerComponent
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.main.entity.*
import kotlinx.collections.immutable.persistentListOf

@Composable
internal fun OnrampOffersContent(state: OnrampOffersBlockUM, linkedMarketingBannerComponent: MarketingBannerComponent) {
    when (state) {
        is OnrampOffersBlockUM.Content -> {
            Column(modifier = Modifier.fillMaxWidth()) {
                state.recentOffer?.let { recentOffer ->
                    Column {
                        Text(
                            modifier = Modifier.padding(start = 12.dp),
                            text = stringResourceSafe(R.string.onramp_recently_used_title),
                            style = TangemTheme.typography.subtitle2,
                            color = TangemTheme.colors.text.tertiary,
                        )

                        SpacerH(8.dp)

                        OfferWithLinkedBanner(recentOffer, linkedMarketingBannerComponent)

                        SpacerH(16.dp)
                    }
                }

                AnimatedVisibility(
                    visible = state.recommended.isNotEmpty(),
                ) {
                    if (state.recommended.isNotEmpty()) {
                        Text(
                            modifier = Modifier.padding(start = 12.dp),
                            text = stringResourceSafe(R.string.onramp_recommended_title),
                            style = TangemTheme.typography.subtitle2,
                            color = TangemTheme.colors.text.tertiary,
                        )
                        SpacerH(8.dp)
                    }
                }

                state.recommended.fastForEach { offer ->
                    key("${offer.paymentMethod.id} ${offer.providerName} ${offer.rate}") {
                        OfferWithLinkedBanner(offer, linkedMarketingBannerComponent)
                        SpacerH(8.dp)
                    }
                }

                if (state.onrampAllOffersButtonConfig != null) {
                    SpacerH(12.dp)
                    SecondaryButton(
                        modifier = Modifier.fillMaxWidth(),
                        text = state.onrampAllOffersButtonConfig.title.resolveReference(),
                        onClick = state.onrampAllOffersButtonConfig.onClick,
                    )
                }
            }
        }
        OnrampOffersBlockUM.Loading -> {
            Box(
                modifier = Modifier.fillMaxWidth(),
                contentAlignment = Alignment.Center,
            ) {
                LoadingBlock()
            }
        }
        OnrampOffersBlockUM.Empty -> Unit
    }
}

@Composable
private fun OfferWithLinkedBanner(offer: OnrampOfferUM, linkedMarketingBannerComponent: MarketingBannerComponent) {
    val hasBanner = linkedMarketingBannerComponent.hasLinkedBanner(offer.providerId)
    // Square the offer's bottom corners so the bottom-rounded banner glues to it as one card.
    Offer(offer, roundBottom = !hasBanner)
    if (hasBanner) {
        TangemThemeRedesign {
            linkedMarketingBannerComponent.LinkedContent(
                providerId = offer.providerId,
                modifier = Modifier.fillMaxWidth(),
            )
        }
    }
}

@Composable
internal fun Offer(onrampOfferUM: OnrampOfferUM, modifier: Modifier = Modifier, roundBottom: Boolean = true) {
    // Square the bottom corners when a linked marketing banner is glued below, so they read as one card.
    val shape = if (roundBottom) {
        RoundedCornerShape(14.dp)
    } else {
        RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp)
    }
    Column(
        modifier = modifier
            .fillMaxWidth()
            .background(
                color = TangemTheme.colors.background.action,
                shape = shape,
            )
            .padding(12.dp),
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
                OfferHeader(advantage = onrampOfferUM.advantages)
                RateBlock(
                    rate = onrampOfferUM.rate,
                    diff = onrampOfferUM.diff,
                    isOfferUnavailable = onrampOfferUM.advantages is OnrampOfferAdvantagesUM.Unavailable,
                )
            }
            SpacerWMax()
            PrimaryButton(
                size = TangemButtonSize.RoundedAction,
                text = stringResourceSafe(R.string.common_buy),
                onClick = onrampOfferUM.onBuyClicked,
                enabled = onrampOfferUM.advantages !is OnrampOfferAdvantagesUM.Unavailable,
            )
        }
        SpacerH(10.dp)
        HorizontalDivider(color = TangemTheme.colors.stroke.primary)
        SpacerH(12.dp)
        PaymentBlockInOffer(
            paymentMethod = onrampOfferUM.paymentMethod,
            providerName = onrampOfferUM.providerName,
        )
    }
}

@Composable
private fun OfferHeader(advantage: OnrampOfferAdvantagesUM) {
    when (advantage) {
        OnrampOfferAdvantagesUM.GreatRate -> {
            Text(
                text = stringResourceSafe(R.string.express_provider_great_rate),
                style = TangemTheme.typography.caption1,
                color = TangemTheme.colors.icon.accent,
                modifier = Modifier.testTag(OnrampOffersBlockTestTags.BEST_RATE_TITLE),
            )
        }
        OnrampOfferAdvantagesUM.Default -> {
            Text(
                text = stringResourceSafe(R.string.onramp_title_you_get),
                style = TangemTheme.typography.caption2,
                color = TangemTheme.colors.text.tertiary,
            )
        }
        OnrampOfferAdvantagesUM.BestRate -> {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(4.dp),
            ) {
                Icon(
                    imageVector = ImageVector.vectorResource(R.drawable.ic_best_rate_16),
                    tint = TangemTheme.colors.icon.accent,
                    contentDescription = null,
                    modifier = Modifier.testTag(OnrampOffersBlockTestTags.BEST_RATE_ICON),
                )
                Text(
                    text = stringResourceSafe(R.string.express_provider_best_rate),
                    style = TangemTheme.typography.caption1,
                    color = TangemTheme.colors.icon.accent,
                    modifier = Modifier.testTag(OnrampOffersBlockTestTags.BEST_RATE_TITLE),
                )
            }
        }
        OnrampOfferAdvantagesUM.Fastest -> {
            Text(
                text = stringResourceSafe(R.string.onramp_offer_type_fastet),
                style = TangemTheme.typography.caption1,
                color = TangemTheme.colors.icon.attention,
            )
        }
        is OnrampOfferAdvantagesUM.Unavailable -> {
            val textResId = when (advantage) {
                OnrampOfferAdvantagesUM.Unavailable.MinAmount -> R.string.onramp_provider_min_amount
                OnrampOfferAdvantagesUM.Unavailable.MaxAmount -> R.string.onramp_provider_max_amount
            }
            Text(
                text = stringResourceSafe(textResId, ""),
                style = TangemTheme.typography.caption1,
                color = TangemTheme.colors.text.tertiary,
            )
        }
    }
}

@Composable
private fun RateBlock(rate: String, diff: TextReference?, isOfferUnavailable: Boolean) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(4.dp),
    ) {
        Text(
            text = rate,
            style = TangemTheme.typography.subtitle1,
            color = if (isOfferUnavailable) TangemTheme.colors.text.tertiary else TangemTheme.colors.text.primary1,
            modifier = Modifier.testTag(OnrampOffersBlockTestTags.OFFER_TOKEN_AMOUNT),
        )

        if (diff != null) {
            Text(
                modifier = Modifier
                    .background(
                        color = TangemTheme.colors.text.warning.copy(alpha = 0.1f),
                        shape = RoundedCornerShape(4.dp),
                    )
                    .padding(horizontal = 4.dp),
                text = diff.resolveReference(),
                style = TangemTheme.typography.caption1,
                color = TangemTheme.colors.text.warning,
            )
        }
    }
}

@Composable
private fun PaymentBlockInOffer(paymentMethod: OnrampPaymentMethod, providerName: String) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Icon(
            modifier = Modifier
                .size(16.dp)
                .testTag(OnrampOffersBlockTestTags.TIMING_ICON),
            imageVector = ImageVector.vectorResource(R.drawable.ic_clock_24),
            tint = TangemTheme.colors.icon.informative,
            contentDescription = null,
        )

        SpacerW(2.dp)

        TimingBlock(speed = paymentMethod.type.getProcessingSpeed())

        SpacerW(6.dp)

        DrawDot(color = TangemTheme.colors.text.tertiary)

        SpacerW(6.dp)

        Text(
            text = stringResourceSafe(R.string.onramp_via_provider, providerName),
            style = TangemTheme.typography.caption2,
            color = TangemTheme.colors.text.tertiary,
            modifier = Modifier.testTag(OnrampOffersBlockTestTags.PROVIDER_NAME),
        )

        SpacerWMax()

        Text(
            text = stringResourceSafe(R.string.onramp_pay_with),
            style = TangemTheme.typography.caption2,
            color = TangemTheme.colors.text.tertiary,
            modifier = Modifier.testTag(OnrampOffersBlockTestTags.PAY_WITH),
        )

        SpacerW(4.dp)

        SubcomposeAsyncImage(
            modifier = Modifier
                .sizeIn(maxWidth = 38.dp, maxHeight = 16.dp)
                .testTag(OnrampOffersBlockTestTags.PAYMENT_METHOD_ICON),
            model = ImageRequest.Builder(context = LocalContext.current)
                .data(paymentMethod.imageUrl)
                .crossfade(enable = true)
                .allowHardware(false)
                .build(),
            loading = {
                TextShimmer(
                    style = TangemTheme.typography.body1,
                    modifier = Modifier.width(40.dp),
                )
            },
            contentDescription = null,
        )
    }
}

@Composable
internal fun TimingBlock(speed: PaymentMethodType.PaymentSpeed) {
    val timingText = when (speed) {
        PaymentMethodType.PaymentSpeed.Instant -> {
            stringResourceSafe(id = R.string.onramp_instant_status)
        }
        PaymentMethodType.PaymentSpeed.FewMin -> {
            stringResourceSafe(
                id = R.string.onramp_timing_minutes,
                FEW_MINS_VALUE,
            )
        }
        PaymentMethodType.PaymentSpeed.FewDays -> {
            pluralStringResourceSafe(
                id = R.plurals.onramp_timing_days,
                count = FEW_DAYS_VALUE,
                FEW_DAYS_VALUE,
            )
        }
        PaymentMethodType.PaymentSpeed.PlentyDays -> {
            pluralStringResourceSafe(
                id = R.plurals.onramp_timing_days,
                count = PLENTY_DAYS_VALUE,
                PLENTY_DAYS_VALUE,
            )
        }
        PaymentMethodType.PaymentSpeed.Unknown -> ""
    }

    Text(
        text = timingText,
        style = TangemTheme.typography.caption2,
        color = TangemTheme.colors.text.tertiary,
        modifier = Modifier.testTag(OnrampOffersBlockTestTags.TIMING_TEXT),
    )
}

@Composable
private fun DrawDot(color: Color) {
    Spacer(
        modifier = Modifier
            .size(4.dp)
            .drawWithCache {
                val radius = size.minDimension / 2f
                onDrawBehind {
                    drawCircle(
                        color = color,
                        radius = radius,
                    )
                }
            },
    )
}

@Composable
private fun LoadingBlock(modifier: Modifier = Modifier) {
    Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        SpacerH(100.dp)

        Text(
            text = stringResourceSafe(R.string.onramp_fetching_best_rates),
            style = TangemTheme.typography.subtitle2,
            color = TangemTheme.colors.text.tertiary,
        )

        SpacerH(8.dp)

        CircularProgressIndicator(
            modifier = Modifier.size(20.dp),
            color = TangemTheme.colors.icon.informative,
            strokeWidth = TangemTheme.dimens.size2,
        )
    }
}

// will be hardcoded till server will be ready to provide this values
private const val FEW_MINS_VALUE = "3-5"
private const val FEW_DAYS_VALUE = 3
private const val PLENTY_DAYS_VALUE = 5

@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun OnrampOffersContentPreview() {
    val state = OnrampOffersBlockUM.Content(
        recentOffer = OnrampOfferUM(
            category = OnrampOfferCategoryUM.RecentlyUsed,
            advantages = OnrampOfferAdvantagesUM.Default,
            paymentMethod = OnrampPaymentMethod(
                id = "card",
                name = "Card",
                imageUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/express/PaymentMethods/visa-mc.png",
                type = PaymentMethodType.CARD,
            ),
            providerId = "simplex",
            providerName = "Simplex",
            rate = "0,00045334 BTC",
            diff = stringReference("–27%"),
            onBuyClicked = {},
        ),
        recommended = persistentListOf(
            OnrampOfferUM(
                category = OnrampOfferCategoryUM.Recommended,
                advantages = OnrampOfferAdvantagesUM.GreatRate,
                paymentMethod = OnrampPaymentMethod(
                    id = "card",
                    name = "Card",
                    imageUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/express/PaymentMethods/visa-mc.png",
                    type = PaymentMethodType.CARD,
                ),
                providerId = "simplex",
                providerName = "Simplex",
                rate = "0,0245334 BTC",
                diff = null,
                onBuyClicked = {},
            ),
            OnrampOfferUM(
                category = OnrampOfferCategoryUM.Recommended,
                advantages = OnrampOfferAdvantagesUM.Fastest,
                paymentMethod = OnrampPaymentMethod(
                    id = "card",
                    name = "Card",
                    imageUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/express/PaymentMethods/visa-mc.png",
                    type = PaymentMethodType.CARD,
                ),
                providerId = "simplex",
                providerName = "Simplex",
                rate = "0,00145334 BTC",
                diff = stringReference("–0.07%"),
                onBuyClicked = {},
            ),
        ),
        onrampAllOffersButtonConfig = OnrampAllOffersButtonConfig(
            title = TextReference.Res(R.string.onramp_all_offers_button_title),
            onClick = { },
        ),
    )
    TangemThemePreview {
        OnrampOffersContent(state = state, linkedMarketingBannerComponent = object : MarketingBannerComponent {
            @Composable
            override fun Content(modifier: Modifier) = Unit
        })
    }
}

@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun OnrampOffersLoadingPreview() {
    TangemThemePreview {
        OnrampOffersContent(
            state = OnrampOffersBlockUM.Loading,
            linkedMarketingBannerComponent = object : MarketingBannerComponent {
                @Composable
                override fun Content(modifier: Modifier) = Unit
            },
        )
    }
}