package com.craigvg.lichun_android.ui.screens.monetization import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import com.craigvg.lichun_android.domain.models.EnergyRefillTier import com.craigvg.lichun_android.ui.theme.AppColors import com.craigvg.lichun_android.ui.theme.AppSpacing import com.craigvg.lichun_android.ui.theme.AppTypography import com.craigvg.lichun_android.viewmodel.GameStateViewModel import kotlinx.coroutines.delay import java.util.concurrent.TimeUnit import androidx.lifecycle.compose.collectAsStateWithLifecycle /** * Energy refill purchase modal with cozy UI design * Ported from iOS EnergyRefillModal.swift */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun EnergyRefillModal( gameStateViewModel: GameStateViewModel = hiltViewModel(), onDismiss: () -> Unit = {} ) { val energy by gameStateViewModel.energy.collectAsStateWithLifecycle() val diamonds by gameStateViewModel.diamonds.collectAsStateWithLifecycle() val energyRefillTiers by gameStateViewModel.energyRefillTiers.collectAsStateWithLifecycle() val unlimitedEnergyUntil by gameStateViewModel.unlimitedEnergyUntil.collectAsStateWithLifecycle() var selectedTier by remember { mutableStateOf(null) } var showingConfirmation by remember { mutableStateOf(false) } LaunchedEffect(Unit) { gameStateViewModel.fetchEnergyRefillTiers() } Scaffold( topBar = { TopAppBar( title = { }, navigationIcon = { }, actions = { IconButton(onClick = onDismiss) { Icon( imageVector = Icons.Default.Close, contentDescription = "Close", tint = AppColors.secondaryText ) } }, colors = TopAppBarDefaults.topAppBarColors( containerColor = AppColors.background ) ) }, containerColor = AppColors.background ) { paddingValues -> Column( modifier = Modifier .fillMaxSize() .padding(paddingValues) .verticalScroll(rememberScrollState()) ) { // Header with icon and title Column( modifier = Modifier .fillMaxWidth() .padding(horizontal = AppSpacing.md), horizontalAlignment = Alignment.CenterHorizontally ) { // Icon Box( modifier = Modifier .size(90.dp) .clip(CircleShape) .background( Brush.linearGradient( colors = listOf( AppColors.energyRefillGradientStart, AppColors.energyRefillGradientEnd ) ) ) .shadow(12.dp, CircleShape), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.Bolt, contentDescription = null, tint = Color.White, modifier = Modifier.size(45.dp) ) } Spacer(modifier = Modifier.height(AppSpacing.md)) Text( text = "Energy Refill", style = AppTypography.title, color = AppColors.primaryText ) Spacer(modifier = Modifier.height(AppSpacing.xs)) Text( text = "Restore your energy to keep playing", style = AppTypography.body, color = AppColors.secondaryText ) } Spacer(modifier = Modifier.height(AppSpacing.lg)) // Current Stats Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = AppSpacing.md), horizontalArrangement = Arrangement.spacedBy(AppSpacing.md) ) { StatCard( icon = Icons.Default.Bolt, label = "Current", value = "$energy", color = AppColors.energy, modifier = Modifier.weight(1f) ) StatCard( icon = Icons.Default.Diamond, label = "Diamonds", value = "$diamonds", color = AppColors.diamond, modifier = Modifier.weight(1f) ) } Spacer(modifier = Modifier.height(AppSpacing.md)) // Unlimited Energy Banner (if active) unlimitedEnergyUntil?.let { expiresAt -> if (expiresAt > System.currentTimeMillis()) { UnlimitedEnergyBanner( expiresAt = expiresAt, modifier = Modifier.padding(horizontal = AppSpacing.md) ) Spacer(modifier = Modifier.height(AppSpacing.md)) } } // Refill Tiers Column( modifier = Modifier.padding(horizontal = AppSpacing.md), verticalArrangement = Arrangement.spacedBy(AppSpacing.md) ) { energyRefillTiers.forEach { tier -> RefillTierCard( tier = tier, canAfford = diamonds >= tier.diamonds, onPurchase = { selectedTier = tier showingConfirmation = true } ) } } Spacer(modifier = Modifier.height(AppSpacing.xl)) } } // Confirmation dialog if (showingConfirmation && selectedTier != null) { AlertDialog( onDismissRequest = { showingConfirmation = false selectedTier = null }, title = { Text("Confirm Purchase") }, text = { Text("Purchase ${selectedTier?.displayName} for ${selectedTier?.diamonds} diamonds?") }, confirmButton = { TextButton( onClick = { selectedTier?.let { tier -> gameStateViewModel.purchaseEnergyRefill(tier.type) } showingConfirmation = false selectedTier = null onDismiss() } ) { Text("Purchase") } }, dismissButton = { TextButton( onClick = { showingConfirmation = false selectedTier = null } ) { Text("Cancel") } } ) } } @Composable private fun StatCard( icon: androidx.compose.ui.graphics.vector.ImageVector, label: String, value: String, color: Color, modifier: Modifier = Modifier ) { Card( modifier = modifier, shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors( containerColor = color.copy(alpha = 0.1f) ) ) { Column( modifier = Modifier .fillMaxWidth() .padding(AppSpacing.md), horizontalAlignment = Alignment.CenterHorizontally ) { Icon( imageVector = icon, contentDescription = null, tint = color, modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.height(AppSpacing.xs)) Text( text = value, fontSize = 22.sp, fontWeight = FontWeight.Bold, color = AppColors.primaryText ) Text( text = label, style = AppTypography.caption, color = AppColors.secondaryText ) } } } @Composable private fun UnlimitedEnergyBanner( expiresAt: Long, modifier: Modifier = Modifier ) { var timeRemaining by remember { mutableStateOf("") } LaunchedEffect(expiresAt) { while (true) { val remaining = expiresAt - System.currentTimeMillis() if (remaining > 0) { val hours = TimeUnit.MILLISECONDS.toHours(remaining) val minutes = TimeUnit.MILLISECONDS.toMinutes(remaining) % 60 timeRemaining = "${hours}h ${minutes}m" } else { timeRemaining = "Expired" } delay(60000) // Update every minute } } Card( modifier = modifier.fillMaxWidth(), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors( containerColor = AppColors.energy.copy(alpha = 0.15f) ) ) { Row( modifier = Modifier.padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.AllInclusive, contentDescription = null, tint = AppColors.energy, modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(AppSpacing.sm)) Column { Text( text = "Unlimited Energy Active", style = AppTypography.headline, color = AppColors.primaryText ) Text( text = "Expires in $timeRemaining", style = AppTypography.caption, color = AppColors.secondaryText ) } } } } @Composable private fun RefillTierCard( tier: EnergyRefillTier, canAfford: Boolean, onPurchase: () -> Unit ) { Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(20.dp), colors = CardDefaults.cardColors( containerColor = AppColors.surfaceElevated ), elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) ) { Row( modifier = Modifier .fillMaxWidth() .padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically ) { // Icon Box( modifier = Modifier .size(60.dp) .clip(CircleShape) .background( AppColors.energyRefillIconBg.copy(alpha = 0.4f) ), contentAlignment = Alignment.Center ) { Icon( imageVector = when (tier.type) { "small" -> Icons.Default.BatteryChargingFull "medium" -> Icons.Default.Battery5Bar "full" -> Icons.Default.BatteryFull else -> Icons.Default.AllInclusive }, contentDescription = null, tint = AppColors.energyRefillIconTint, modifier = Modifier.size(28.dp) ) } Spacer(modifier = Modifier.width(AppSpacing.md)) // Details Column(modifier = Modifier.weight(1f)) { Text( text = tier.displayName, style = AppTypography.headline, color = AppColors.primaryText ) Text( text = tier.description, style = AppTypography.body, color = AppColors.secondaryText ) } // Price button Button( onClick = onPurchase, enabled = canAfford, colors = ButtonDefaults.buttonColors( containerColor = AppColors.energyRefillButton, disabledContainerColor = AppColors.disabledText ), shape = RoundedCornerShape(AppSpacing.pillCornerRadius), contentPadding = PaddingValues(horizontal = AppSpacing.md, vertical = AppSpacing.sm) ) { Text( text = "${tier.diamonds}", fontSize = 18.sp, fontWeight = FontWeight.Bold, color = Color.White ) Spacer(modifier = Modifier.width(4.dp)) Icon( imageVector = Icons.Default.Diamond, contentDescription = null, tint = Color.White, modifier = Modifier.size(14.dp) ) } } } }