package com.craigvg.lichun_android.ui.screens.onboarding import androidx.compose.animation.core.* import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState 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.alpha import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel 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 kotlinx.coroutines.launch import kotlin.math.cos import kotlin.math.sin /** * Confirmation screen before starting the game * Ported from iOS ConfirmationView.swift */ @Composable fun ConfirmationScreen( name: String, age: Int, sex: String, gameStateViewModel: GameStateViewModel = hiltViewModel(), onStartJourney: () -> Unit = {} ) { var isLoaded by remember { mutableStateOf(false) } var loading by remember { mutableStateOf(false) } var errorMessage by remember { mutableStateOf(null) } val coroutineScope = rememberCoroutineScope() // Animation states val infiniteTransition = rememberInfiniteTransition(label = "confirmation") val celebrationScale by infiniteTransition.animateFloat( initialValue = 0.8f, targetValue = 1.2f, animationSpec = infiniteRepeatable( animation = tween(2000, easing = EaseInOut), repeatMode = RepeatMode.Reverse ), label = "celebration" ) val sparkleRotation by infiniteTransition.animateFloat( initialValue = 0f, targetValue = 360f, animationSpec = infiniteRepeatable( animation = tween(20000, easing = LinearEasing), repeatMode = RepeatMode.Restart ), label = "sparkle" ) val iconRotation by animateFloatAsState( targetValue = if (isLoaded) 0f else -180f, animationSpec = spring(dampingRatio = 0.65f, stiffness = 200f), label = "iconRotation" ) val iconScale by animateFloatAsState( targetValue = if (isLoaded) 1f else 0.3f, animationSpec = spring(dampingRatio = 0.65f, stiffness = 200f), label = "iconScale" ) LaunchedEffect(Unit) { delay(100) isLoaded = true } Box( modifier = Modifier .fillMaxSize() .background( Brush.linearGradient( colors = listOf( AppColors.background, AppColors.background ) ) ) ) { Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .padding(horizontal = AppSpacing.xl), horizontalAlignment = Alignment.CenterHorizontally ) { Spacer(modifier = Modifier.height(AppSpacing.xl)) // Celebration icon with sparkles Box( modifier = Modifier.height(150.dp), contentAlignment = Alignment.Center ) { // Sparkle effects for (index in 0 until 8) { val angle = (index * 45.0 + sparkleRotation) * Math.PI / 180 val offsetX = (cos(angle) * 60).toFloat() val offsetY = (sin(angle) * 60).toFloat() Icon( imageVector = Icons.Default.AutoAwesome, contentDescription = null, tint = AppColors.accent.copy(alpha = 0.6f), modifier = Modifier .size(20.dp) .offset(x = offsetX.dp, y = offsetY.dp) .scale(celebrationScale) .alpha(if (isLoaded) 1f else 0f) .rotate(sparkleRotation + index * 45f) ) } // Main success icon Icon( imageVector = Icons.Default.Verified, contentDescription = "Success", tint = AppColors.primary, modifier = Modifier .size(80.dp) .scale(iconScale) .rotate(iconRotation) ) } // Success message Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.alpha(if (isLoaded) 1f else 0f) ) { Text( text = "All Set!", fontSize = 40.sp, fontWeight = FontWeight.Bold, color = AppColors.primary ) Spacer(modifier = Modifier.height(AppSpacing.sm)) Text( text = "Your adventure is about to begin", style = AppTypography.body, color = AppColors.secondaryText, textAlign = TextAlign.Center ) } Spacer(modifier = Modifier.height(AppSpacing.xl)) // Character summary card Card( modifier = Modifier .fillMaxWidth() .alpha(if (isLoaded) 1f else 0f), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors(containerColor = AppColors.surfaceElevated) ) { Column( modifier = Modifier .fillMaxWidth() .padding(AppSpacing.md), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "YOUR CHARACTER", style = AppTypography.caption, color = AppColors.secondaryText, letterSpacing = 1.sp ) Spacer(modifier = Modifier.height(AppSpacing.md)) InfoRow( icon = Icons.Default.Person, label = "Name", value = name, useGradient = true ) Spacer(modifier = Modifier.height(AppSpacing.sm)) InfoRow( icon = Icons.Default.CalendarMonth, label = "Age", value = "$age years" ) Spacer(modifier = Modifier.height(AppSpacing.sm)) InfoRow( icon = if (sex == "Male") Icons.Default.Man else Icons.Default.Woman, label = "Gender", value = sex ) } } Spacer(modifier = Modifier.height(AppSpacing.md)) // Encouraging message card Card( modifier = Modifier .fillMaxWidth() .alpha(if (isLoaded) 1f else 0f), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors( containerColor = AppColors.primary.copy(alpha = 0.15f) ) ) { Row( modifier = Modifier.padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.Lightbulb, contentDescription = null, tint = AppColors.primary, modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(AppSpacing.md)) Text( text = "Every choice you make will shape your character's unique journey. Have fun!", style = AppTypography.caption, color = AppColors.primaryText ) } } Spacer(modifier = Modifier.height(AppSpacing.xl)) // Error message errorMessage?.let { error -> Card( modifier = Modifier .fillMaxWidth() .padding(bottom = AppSpacing.md), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors( containerColor = AppColors.health.copy(alpha = 0.15f) ) ) { Row( modifier = Modifier.padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.Warning, contentDescription = null, tint = AppColors.health, modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(AppSpacing.sm)) Text( text = error, style = AppTypography.caption, color = AppColors.primaryText ) } } } // Start button Button( onClick = { loading = true errorMessage = null coroutineScope.launch { try { gameStateViewModel.setupCharacter(name, age, sex) onStartJourney() } catch (e: Exception) { loading = false errorMessage = "Failed to create character. Please try again." } } }, modifier = Modifier .fillMaxWidth() .height(AppSpacing.buttonHeight) .alpha(if (isLoaded) 1f else 0f), enabled = !loading, colors = ButtonDefaults.buttonColors( containerColor = AppColors.primary ), shape = RoundedCornerShape(AppSpacing.cornerRadius) ) { if (loading) { CircularProgressIndicator( modifier = Modifier.size(24.dp), color = Color.White, strokeWidth = 2.dp ) Spacer(modifier = Modifier.width(AppSpacing.sm)) Text( text = "Preparing Your World...", style = AppTypography.button ) } else { Text( text = "Start Your Journey!", style = AppTypography.button ) } } Spacer(modifier = Modifier.height(AppSpacing.xl)) } } } @Composable private fun InfoRow( icon: ImageVector, label: String, value: String, useGradient: Boolean = false ) { Row( modifier = Modifier .fillMaxWidth() .background( AppColors.background.copy(alpha = 0.5f), RoundedCornerShape(AppSpacing.cornerRadius) ) .padding(AppSpacing.sm), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = icon, contentDescription = null, tint = if (useGradient) AppColors.primary else AppColors.secondaryText, modifier = Modifier.size(20.dp) ) Spacer(modifier = Modifier.width(AppSpacing.md)) Text( text = label, style = AppTypography.caption, color = AppColors.secondaryText, modifier = Modifier.width(70.dp) ) Spacer(modifier = Modifier.weight(1f)) Text( text = value, style = AppTypography.bodyBold, color = AppColors.primaryText ) } }