package com.craigvg.lichun_android.ui.screens.dating import androidx.compose.foundation.background import androidx.compose.foundation.clickable 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.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.layout.ContentScale import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import coil3.compose.AsyncImage import com.craigvg.lichun_android.domain.models.Person 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.PlayerViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle private enum class CharacterFilter(val label: String) { All("All"), Family("Family"), Friends("Friends"), Colleagues("Colleagues"), Classmates("Classmates") } /** * Characters screen showing all known characters with filter tabs * Ported from iOS RelationshipsView.swift */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun RelationshipsScreen( playerViewModel: PlayerViewModel = hiltViewModel(), onBack: () -> Unit = {}, onRelationshipClick: (Person) -> Unit = {} ) { val relationships by playerViewModel.relationships.collectAsStateWithLifecycle() var selectedFilter by remember { mutableStateOf(CharacterFilter.All) } val filteredCharacters = when (selectedFilter) { CharacterFilter.All -> relationships CharacterFilter.Family -> relationships.filter { person -> person.relationships.any { it.equals("family", ignoreCase = true) } } CharacterFilter.Friends -> relationships.filter { person -> person.relationships.any { it.equals("friend", ignoreCase = true) } } CharacterFilter.Colleagues -> relationships.filter { person -> person.relationships.any { it.equals("coworker", ignoreCase = true) || it.equals("colleague", ignoreCase = true) } } CharacterFilter.Classmates -> relationships.filter { person -> person.relationships.any { it.equals("classmate", ignoreCase = true) } } } Scaffold( topBar = { TopAppBar( title = { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(AppSpacing.xs) ) { Icon( imageVector = Icons.Default.People, contentDescription = null, tint = AppColors.secondary, modifier = Modifier.size(22.dp) ) Text("Characters", style = AppTypography.largeTitle) Spacer(modifier = Modifier.weight(1f)) // Count badge Surface( shape = RoundedCornerShape(50), color = AppColors.secondary ) { Text( text = "${filteredCharacters.size}", style = AppTypography.bodyBold, color = Color.White, modifier = Modifier.padding(horizontal = AppSpacing.sm, vertical = AppSpacing.xs) ) } } }, 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) ) { // Filter tabs ScrollableTabRow( selectedTabIndex = selectedFilter.ordinal, containerColor = AppColors.surfaceElevated, contentColor = AppColors.primaryText, edgePadding = AppSpacing.md, divider = {} ) { CharacterFilter.entries.forEach { filter -> Tab( selected = selectedFilter == filter, onClick = { selectedFilter = filter }, text = { Text( text = filter.label, style = AppTypography.bodyBold, color = if (selectedFilter == filter) AppColors.primary else AppColors.secondaryText ) } ) } } // Character list LazyColumn( modifier = Modifier .fillMaxSize() .padding(horizontal = AppSpacing.md), verticalArrangement = Arrangement.spacedBy(AppSpacing.sm), contentPadding = PaddingValues(vertical = AppSpacing.sm) ) { if (filteredCharacters.isEmpty()) { item { Box( modifier = Modifier .fillMaxWidth() .padding(vertical = AppSpacing.xxl), contentAlignment = Alignment.Center ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Icon( imageVector = Icons.Default.People, contentDescription = null, tint = AppColors.disabledText, modifier = Modifier.size(64.dp) ) Spacer(modifier = Modifier.height(AppSpacing.md)) Text( text = if (relationships.isEmpty()) "No characters yet" else "No ${selectedFilter.label.lowercase()} found", style = AppTypography.headline, color = AppColors.secondaryText ) if (relationships.isEmpty()) { Text( text = "Meet people as you live your life!", style = AppTypography.body, color = AppColors.disabledText ) } } } } } items(filteredCharacters) { person -> RelationshipCard( person = person, onClick = { onRelationshipClick(person) } ) } item { Spacer(modifier = Modifier.height(AppSpacing.lg)) } } } } } @Composable fun RelationshipCard( person: Person, onClick: () -> Unit ) { val affinityColor = when { person.affinity >= 70 -> AppColors.primary person.affinity >= 40 -> AppColors.accent else -> AppColors.disabledText } Card( modifier = Modifier .fillMaxWidth() .clickable(onClick = onClick), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors(containerColor = AppColors.surfaceElevated) ) { Row( modifier = Modifier .fillMaxWidth() .padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically ) { // Avatar with colored border (matches iOS) Box( modifier = Modifier .size(56.dp) .clip(CircleShape) .background(affinityColor.copy(alpha = 0.3f)) .padding(2.dp) .clip(CircleShape) .background(AppColors.surfaceElevated) ) { AsyncImage( model = person.image, contentDescription = person.firstname, modifier = Modifier .fillMaxSize() .clip(CircleShape), contentScale = ContentScale.Crop ) } Spacer(modifier = Modifier.width(AppSpacing.md)) // Info: name + relationship tags Column(modifier = Modifier.weight(1f)) { Text( text = "${person.firstname} ${person.lastname}", style = AppTypography.headline, color = AppColors.primaryText ) // Relationship tag chips (show first 2) if (person.relationships.isNotEmpty()) { Spacer(modifier = Modifier.height(AppSpacing.xs)) Row(horizontalArrangement = Arrangement.spacedBy(AppSpacing.xs)) { person.relationships.take(2).forEach { tag -> RelationshipTagChip(tag = tag) } } } } Spacer(modifier = Modifier.width(AppSpacing.sm)) // Affinity badge (matches iOS right-side badge) Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .background( affinityColor.copy(alpha = 0.15f), RoundedCornerShape(AppSpacing.sm) ) .padding(horizontal = AppSpacing.sm, vertical = AppSpacing.xs) ) { Icon( imageVector = Icons.Default.Favorite, contentDescription = null, tint = affinityColor, modifier = Modifier.size(14.dp) ) Text( text = "${person.affinity}", style = AppTypography.captionBold, color = affinityColor ) } } } } @Composable private fun RelationshipTagChip(tag: String) { val chipColor = when (tag.lowercase()) { "family" -> AppColors.accent "friend" -> AppColors.secondary "coworker", "colleague" -> AppColors.intelligence "classmate" -> AppColors.energy else -> AppColors.disabledText } val chipIcon = when (tag.lowercase()) { "family" -> Icons.Default.Home "friend" -> Icons.Default.People "coworker", "colleague" -> Icons.Default.Work "classmate" -> Icons.Default.MenuBook else -> Icons.Default.Person } Surface( shape = RoundedCornerShape(AppSpacing.xs), color = chipColor.copy(alpha = 0.15f) ) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(horizontal = AppSpacing.xs, vertical = 2.dp) ) { Icon( imageVector = chipIcon, contentDescription = null, tint = chipColor, modifier = Modifier.size(10.dp) ) Spacer(modifier = Modifier.width(2.dp)) Text( text = tag.replaceFirstChar { it.uppercase() }, style = AppTypography.caption, color = AppColors.secondaryText ) } } }