package com.craigvg.lichun_android.ui.screens.settings 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.automirrored.filled.ArrowBack 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.graphics.Color 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 androidx.lifecycle.compose.collectAsStateWithLifecycle /** * Deletion state */ enum class DeletionState { CONFIRM, PROCESSING, SCHEDULED, ERROR } /** * Account deletion screen with confirmation */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun AccountDeletionScreen( gameStateViewModel: GameStateViewModel = hiltViewModel(), onBack: () -> Unit = {}, onConfirmDelete: () -> Unit = {} ) { val accountDeletionUpdate by gameStateViewModel.accountDeletionUpdate.collectAsStateWithLifecycle() val currentError by gameStateViewModel.currentError.collectAsStateWithLifecycle() var deletionState by remember { mutableStateOf(DeletionState.CONFIRM) } var statusMessage by remember { mutableStateOf(null) } var errorMessage by remember { mutableStateOf(null) } var confirmText by remember { mutableStateOf("") } val confirmWord = "DELETE" Scaffold( topBar = { TopAppBar( title = { Text("Delete Account", style = AppTypography.headline) }, navigationIcon = { IconButton(onClick = onBack) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back", tint = AppColors.primaryText ) } }, colors = TopAppBarDefaults.topAppBarColors( containerColor = AppColors.surfaceElevated ) ) }, containerColor = AppColors.background ) { paddingValues -> Column( modifier = Modifier .fillMaxSize() .padding(paddingValues) .verticalScroll(rememberScrollState()) .padding(AppSpacing.lg), horizontalAlignment = Alignment.CenterHorizontally ) { when (deletionState) { DeletionState.CONFIRM -> { ConfirmationContent( confirmText = confirmText, confirmWord = confirmWord, onConfirmTextChange = { confirmText = it }, onDelete = { deletionState = DeletionState.PROCESSING statusMessage = null errorMessage = null gameStateViewModel.clearAccountDeletionUpdate() gameStateViewModel.requestAccountDeletion() onConfirmDelete() }, canDelete = confirmText.equals(confirmWord, ignoreCase = true) ) } DeletionState.PROCESSING -> { ProcessingContent() } DeletionState.SCHEDULED -> { ScheduledContent( message = statusMessage, onDone = onBack ) } DeletionState.ERROR -> { ErrorContent( message = errorMessage, onRetry = { deletionState = DeletionState.CONFIRM } ) } } } } LaunchedEffect(accountDeletionUpdate, deletionState) { if (deletionState == DeletionState.PROCESSING) { accountDeletionUpdate?.let { update -> if (update.scheduled) { statusMessage = update.message deletionState = DeletionState.SCHEDULED } else { errorMessage = update.message deletionState = DeletionState.ERROR } } } } LaunchedEffect(currentError, deletionState) { if (deletionState == DeletionState.PROCESSING) { currentError?.let { errorMessage = it.userMessage deletionState = DeletionState.ERROR } } } } @Composable private fun ConfirmationContent( confirmText: String, confirmWord: String, onConfirmTextChange: (String) -> Unit, onDelete: () -> Unit, canDelete: Boolean ) { // Warning icon Box( modifier = Modifier .size(80.dp) .clip(CircleShape) .background(AppColors.error.copy(alpha = 0.15f)), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.Warning, contentDescription = null, tint = AppColors.error, modifier = Modifier.size(40.dp) ) } Spacer(modifier = Modifier.height(AppSpacing.lg)) Text( text = "Are you sure?", style = AppTypography.title, color = AppColors.error ) Spacer(modifier = Modifier.height(AppSpacing.sm)) Text( text = "This action cannot be undone. All your data will be permanently deleted.", style = AppTypography.body, color = AppColors.secondaryText, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.height(AppSpacing.xl)) // What will be deleted Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors( containerColor = AppColors.error.copy(alpha = 0.08f) ) ) { Column( modifier = Modifier.padding(AppSpacing.md), verticalArrangement = Arrangement.spacedBy(AppSpacing.sm) ) { Text( text = "What will be deleted:", style = AppTypography.bodyBold, color = AppColors.primaryText ) DeletionItem("Your character and progress") DeletionItem("All relationships and messages") DeletionItem("Achievements and rewards") DeletionItem("Purchase history (non-refundable)") } } Spacer(modifier = Modifier.height(AppSpacing.xl)) // Confirmation input Text( text = "Type \"$confirmWord\" to confirm:", style = AppTypography.caption, color = AppColors.secondaryText ) Spacer(modifier = Modifier.height(AppSpacing.xs)) OutlinedTextField( value = confirmText, onValueChange = onConfirmTextChange, placeholder = { Text(confirmWord, color = AppColors.disabledText) }, modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = OutlinedTextFieldDefaults.colors( focusedBorderColor = AppColors.error, unfocusedBorderColor = AppColors.surfaceSubtle ), singleLine = true ) Spacer(modifier = Modifier.height(AppSpacing.xl)) // Delete button Button( onClick = onDelete, modifier = Modifier .fillMaxWidth() .height(AppSpacing.buttonHeight), enabled = canDelete, shape = RoundedCornerShape(AppSpacing.pillCornerRadius), colors = ButtonDefaults.buttonColors( containerColor = AppColors.error, disabledContainerColor = AppColors.disabledText ) ) { Icon( imageVector = Icons.Default.DeleteForever, contentDescription = null, modifier = Modifier.size(20.dp) ) Spacer(modifier = Modifier.width(AppSpacing.sm)) Text( text = "Delete My Account", style = AppTypography.bodyBold, color = Color.White ) } } @Composable private fun DeletionItem(text: String) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.Default.Close, contentDescription = null, tint = AppColors.error, modifier = Modifier.size(16.dp) ) Spacer(modifier = Modifier.width(AppSpacing.sm)) Text( text = text, style = AppTypography.body, color = AppColors.primaryText ) } } @Composable private fun ProcessingContent() { Spacer(modifier = Modifier.height(AppSpacing.xxl)) CircularProgressIndicator( color = AppColors.error, modifier = Modifier.size(60.dp), strokeWidth = 4.dp ) Spacer(modifier = Modifier.height(AppSpacing.lg)) Text( text = "Processing Request...", style = AppTypography.headline, color = AppColors.primaryText ) Spacer(modifier = Modifier.height(AppSpacing.sm)) Text( text = "Please wait while we process your deletion request.", style = AppTypography.body, color = AppColors.secondaryText, textAlign = TextAlign.Center ) } @Composable private fun ScheduledContent( message: String?, onDone: () -> Unit ) { Spacer(modifier = Modifier.height(AppSpacing.xl)) Box( modifier = Modifier .size(80.dp) .clip(CircleShape) .background(AppColors.success.copy(alpha = 0.15f)), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.Schedule, contentDescription = null, tint = AppColors.success, modifier = Modifier.size(40.dp) ) } Spacer(modifier = Modifier.height(AppSpacing.lg)) Text( text = "Deletion Scheduled", style = AppTypography.title, color = AppColors.success ) Spacer(modifier = Modifier.height(AppSpacing.sm)) Text( text = message ?: "Your account will be permanently deleted in 30 days. You can cancel this by logging back in before then.", style = AppTypography.body, color = AppColors.secondaryText, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.height(AppSpacing.xl)) // Grace period notice Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors( containerColor = AppColors.surfaceElevated ) ) { Row( modifier = Modifier.padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.Info, contentDescription = null, tint = AppColors.primary, modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(AppSpacing.sm)) Text( text = "30-day grace period: Log back in anytime to cancel the deletion.", style = AppTypography.caption, color = AppColors.primaryText ) } } Spacer(modifier = Modifier.height(AppSpacing.xl)) Button( onClick = onDone, modifier = Modifier .fillMaxWidth() .height(AppSpacing.buttonHeight), shape = RoundedCornerShape(AppSpacing.pillCornerRadius), colors = ButtonDefaults.buttonColors( containerColor = AppColors.primary ) ) { Text( text = "Done", style = AppTypography.bodyBold ) } } @Composable private fun ErrorContent( message: String?, onRetry: () -> Unit ) { Spacer(modifier = Modifier.height(AppSpacing.xl)) Box( modifier = Modifier .size(80.dp) .clip(CircleShape) .background(AppColors.error.copy(alpha = 0.15f)), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.Error, contentDescription = null, tint = AppColors.error, modifier = Modifier.size(40.dp) ) } Spacer(modifier = Modifier.height(AppSpacing.lg)) Text( text = "Something Went Wrong", style = AppTypography.title, color = AppColors.error ) Spacer(modifier = Modifier.height(AppSpacing.sm)) Text( text = message ?: "We couldn't process your request. Please try again later.", style = AppTypography.body, color = AppColors.secondaryText, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.height(AppSpacing.xl)) Button( onClick = onRetry, modifier = Modifier .fillMaxWidth() .height(AppSpacing.buttonHeight), shape = RoundedCornerShape(AppSpacing.pillCornerRadius), colors = ButtonDefaults.buttonColors( containerColor = AppColors.primary ) ) { Text( text = "Try Again", style = AppTypography.bodyBold ) } }