package com.craigvg.lichun_android.ui.screens.retention import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.Diamond import androidx.compose.material.icons.filled.EmojiEvents import androidx.compose.material.icons.filled.Link import androidx.compose.material.icons.filled.LocalFireDepartment import androidx.compose.material.icons.filled.Schedule import androidx.compose.material.icons.filled.Star import androidx.compose.material3.* import androidx.compose.runtime.Composable 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.graphics.vector.ImageVector import androidx.compose.ui.unit.dp import com.craigvg.lichun_android.domain.models.QuestEngagementSnapshot import com.craigvg.lichun_android.domain.models.WeeklyChallenge import com.craigvg.lichun_android.ui.theme.AppColors import com.craigvg.lichun_android.ui.theme.AppSpacing import com.craigvg.lichun_android.ui.theme.AppTypography /** * Wave 2: the deeper quest loop surface — full-clear streak (+ N-day bonus * progress), the rolled weekly challenge with its larger payoff, and a short * explainer of quest chains. Read-only status (rewards auto-awarded server-side). * * Android parity with iOS QuestDepthSection.swift. */ @Composable fun QuestDepthSection(engagement: QuestEngagementSnapshot?) { val streak = engagement?.fullClearStreak ?: 0 val daysToBonus = engagement?.daysToNextBonus ?: QuestEngagementSnapshot.STREAK_BONUS_THRESHOLD val weekly = engagement?.weekly Column(verticalArrangement = Arrangement.spacedBy(AppSpacing.sm)) { FullClearStreakCard(streak = streak, daysToBonus = daysToBonus) weekly?.let { WeeklyChallengeCard(it) } QuestChainsExplainer() } } @Composable private fun FullClearStreakCard(streak: Int, daysToBonus: Int) { val reward = QuestEngagementSnapshot.STREAK_BONUS_REWARD val subtitle = when { streak == 0 -> "Clear all daily quests to start a streak. Reward at ${QuestEngagementSnapshot.STREAK_BONUS_THRESHOLD} days." daysToBonus <= 1 -> "1 more full-clear day for a $reward diamond bonus!" else -> "$daysToBonus more full-clear days for a $reward diamond bonus." } Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors(containerColor = AppColors.surfaceElevated), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { Row( modifier = Modifier.padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically ) { Box( modifier = Modifier .size(48.dp) .background(AppColors.warning.copy(alpha = 0.15f), CircleShape), contentAlignment = Alignment.Center ) { Icon(Icons.Default.LocalFireDepartment, null, tint = AppColors.warning, modifier = Modifier.size(24.dp)) } Spacer(Modifier.width(AppSpacing.md)) Column(modifier = Modifier.weight(1f)) { Text("Full-Clear Streak", style = AppTypography.bodyBold, color = AppColors.primaryText) Text(subtitle, style = AppTypography.caption, color = AppColors.secondaryText) } Spacer(Modifier.width(AppSpacing.sm)) Column(horizontalAlignment = Alignment.CenterHorizontally) { Text("$streak", style = AppTypography.title2, color = AppColors.warning) Text(if (streak == 1) "day" else "days", style = AppTypography.caption, color = AppColors.secondaryText) } } } } @Composable private fun WeeklyChallengeCard(challenge: WeeklyChallenge) { Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors(containerColor = AppColors.surfaceElevated), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { Column(modifier = Modifier.padding(AppSpacing.md)) { Row(verticalAlignment = Alignment.CenterVertically) { Box( modifier = Modifier .size(44.dp) .background(AppColors.intelligence.copy(alpha = 0.15f), CircleShape), contentAlignment = Alignment.Center ) { Icon(Icons.Default.EmojiEvents, null, tint = AppColors.intelligence, modifier = Modifier.size(20.dp)) } Spacer(Modifier.width(AppSpacing.sm)) Column(modifier = Modifier.weight(1f)) { Text("Weekly Challenge", style = AppTypography.bodyBold, color = AppColors.primaryText) Text(challenge.description, style = AppTypography.caption, color = AppColors.secondaryText, maxLines = 2) } Spacer(Modifier.width(AppSpacing.sm)) WeeklyStatusBadge(challenge) } if (!challenge.claimed) { Spacer(Modifier.height(AppSpacing.sm)) Row(verticalAlignment = Alignment.CenterVertically) { Text(challenge.progressText, style = AppTypography.captionBold, color = AppColors.primaryText) Spacer(Modifier.weight(1f)) Text("${(challenge.progressFraction * 100).toInt()}%", style = AppTypography.caption, color = AppColors.secondaryText) } Spacer(Modifier.height(AppSpacing.xxs)) Box( modifier = Modifier .fillMaxWidth() .height(8.dp) .clip(RoundedCornerShape(4.dp)) .background(AppColors.intelligence.copy(alpha = 0.2f)) ) { Box( modifier = Modifier .fillMaxWidth(challenge.progressFraction) .fillMaxHeight() .clip(RoundedCornerShape(4.dp)) .background(AppColors.intelligence) ) } } Spacer(Modifier.height(AppSpacing.sm)) Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Default.Diamond, null, tint = AppColors.diamond, modifier = Modifier.size(14.dp)) Spacer(Modifier.width(4.dp)) Text("${challenge.diamondReward} diamonds", style = AppTypography.captionBold, color = AppColors.primaryText) Spacer(Modifier.width(4.dp)) Text("• bigger weekly payoff", style = AppTypography.caption, color = AppColors.secondaryText) } } } } @Composable private fun WeeklyStatusBadge(challenge: WeeklyChallenge) { val (text, icon, color) = when { challenge.claimed -> Triple("Earned", Icons.Default.CheckCircle, AppColors.success) challenge.completed -> Triple("Complete", Icons.Default.Star, AppColors.accent) else -> Triple("Active", Icons.Default.Schedule, AppColors.info) } Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .clip(RoundedCornerShape(AppSpacing.smallCornerRadius)) .background(color.copy(alpha = 0.15f)) .padding(horizontal = AppSpacing.sm, vertical = 4.dp) ) { Icon(icon, null, tint = color, modifier = Modifier.size(12.dp)) Spacer(Modifier.width(4.dp)) Text(text, style = AppTypography.caption, color = color) } } @Composable private fun QuestChainsExplainer() { Row( modifier = Modifier .fillMaxWidth() .clip(RoundedCornerShape(AppSpacing.smallCornerRadius)) .background(AppColors.primary.copy(alpha = 0.08f)) .padding(AppSpacing.sm), verticalAlignment = Alignment.CenterVertically ) { Icon(Icons.Default.Link, null, tint = AppColors.primary, modifier = Modifier.size(16.dp)) Spacer(Modifier.width(AppSpacing.sm)) Text( "Complete a daily quest to unlock a bonus follow-up quest in the same category.", style = AppTypography.caption, color = AppColors.secondaryText ) } }