package com.craigvg.lichun_android.ui.screens.character import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color 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 androidx.lifecycle.compose.collectAsStateWithLifecycle import com.craigvg.lichun_android.domain.models.FamilyTreeEntry 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 kotlin.math.abs import kotlin.math.roundToLong /** * Legacy / family-tree screen. Renders the persisted lineage history * (`player.familyTree`) — one card per ancestor, oldest generation first — plus * the compounding family prestige. Reachable from the death recap's legacy card * and (later) from the More menu. * * Tier 2 Wave 1. Mirrors the iOS legacy/family-tree surface. */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun FamilyTreeScreen( gameStateViewModel: GameStateViewModel = hiltViewModel(), onBack: () -> Unit = {} ) { val player by gameStateViewModel.player.collectAsStateWithLifecycle() val familyTree = player.familyTree.sortedBy { it.generation } val familyPrestige = player.familyPrestige Scaffold( topBar = { TopAppBar( title = { Text("Family Legacy", style = AppTypography.title2) }, navigationIcon = { IconButton(onClick = onBack) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back", tint = AppColors.primaryText ) } }, colors = TopAppBarDefaults.topAppBarColors( containerColor = AppColors.background, titleContentColor = AppColors.primaryText ) ) }, containerColor = AppColors.background ) { innerPadding -> LazyColumn( modifier = Modifier .fillMaxSize() .padding(innerPadding) .padding(horizontal = AppSpacing.md), verticalArrangement = Arrangement.spacedBy(AppSpacing.sm) ) { item { Spacer(modifier = Modifier.height(AppSpacing.sm)) FamilyPrestigeBanner(prestige = familyPrestige) Spacer(modifier = Modifier.height(AppSpacing.sm)) } if (familyTree.isEmpty()) { item { Box( modifier = Modifier.fillMaxWidth().padding(vertical = AppSpacing.xxl), contentAlignment = Alignment.Center ) { Text( text = "No ancestors yet. Your lineage begins with this life.", style = AppTypography.body, color = AppColors.secondaryText, textAlign = TextAlign.Center ) } } } else { items(familyTree, key = { "${it.generation}-${it.name}" }) { entry -> AncestorCard(entry) } } item { Spacer(modifier = Modifier.height(AppSpacing.lg)) } } } } @Composable private fun FamilyPrestigeBanner(prestige: Double) { Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors(containerColor = AppColors.prestige.copy(alpha = 0.25f)) ) { Column( modifier = Modifier.padding(AppSpacing.md), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Family Prestige", style = AppTypography.caption, color = AppColors.secondaryText ) Text( text = formatNumber(prestige), fontSize = 32.sp, fontWeight = FontWeight.Bold, color = AppColors.primaryText ) Text( text = "Compounds across generations", style = AppTypography.caption, color = AppColors.secondaryText ) } } } @Composable private fun AncestorCard(entry: FamilyTreeEntry) { Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors(containerColor = AppColors.surfaceElevated) ) { Row( modifier = Modifier.padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically ) { // Generation badge Box( modifier = Modifier .size(AppSpacing.avatarSmall) .background(AppColors.prestige.copy(alpha = 0.4f), CircleShape), contentAlignment = Alignment.Center ) { Text( text = "G${entry.generation}", style = AppTypography.captionBold, color = AppColors.primaryText ) } Spacer(modifier = Modifier.width(AppSpacing.sm)) Column(modifier = Modifier.weight(1f)) { Text( text = entry.name.ifBlank { "Unknown" }, style = AppTypography.bodyBold, color = AppColors.primaryText ) Text( text = buildString { append("Lived to ${entry.finalAge}") entry.peakCareer?.takeIf { it.isNotBlank() }?.let { append(" · $it") } }, style = AppTypography.caption, color = AppColors.secondaryText ) Text( text = "Score ${formatNumber(entry.score.toDouble())} · Net worth $${formatNumber(entry.netWorth)}", style = AppTypography.caption, color = AppColors.secondaryText ) } } } } /** Compact money/score formatting (e.g. 1.2K, 3.4M). */ private fun formatNumber(value: Double): String { val a = abs(value) return when { a >= 1_000_000 -> "${roundTo1(value / 1_000_000)}M" a >= 1_000 -> "${roundTo1(value / 1_000)}K" else -> value.roundToLong().toString() } } private fun roundTo1(v: Double): String { val r = (v * 10).roundToLong() / 10.0 return if (r == r.toLong().toDouble()) r.toLong().toString() else r.toString() }