package com.example.ui.screens import androidx.compose.foundation.BorderStroke 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.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.filled.VerifiedUser 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.platform.LocalFocusManager import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.example.data.BookingEntity import com.example.data.LiveChatEntity import com.example.ui.PortalViewModel import com.example.ui.theme.* import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.text.SimpleDateFormat import java.util.* @OptIn(ExperimentalMaterial3Api::class) @Composable fun Private1vs1ChatDialog( booking: BookingEntity, viewModel: PortalViewModel, senderType: String, // "USER" or "MODEL" onDismiss: () -> Unit ) { val coroutineScope = rememberCoroutineScope() val focusManager = LocalFocusManager.current // Fetch private chats flow val chats by viewModel.getPrivateChats(booking.id).collectAsState(initial = emptyList()) var textInput by remember { mutableStateOf("") } val listState = rememberLazyListState() val interlocutorName = if (senderType == "USER") booking.modelName else booking.userName val senderId = if (senderType == "USER") booking.userId else "model_${booking.modelId}" val senderName = if (senderType == "USER") booking.userName else booking.modelName // Auto-scroll on new messages LaunchedEffect(chats.size) { if (chats.isNotEmpty()) { listState.animateScrollToItem(chats.size - 1) } } Dialog( onDismissRequest = onDismiss, properties = DialogProperties( usePlatformDefaultWidth = false ) ) { Card( shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Obsidian), modifier = Modifier .fillMaxWidth(0.95f) .fillMaxHeight(0.85f), border = BorderStroke(1.dp, BrandGold.copy(0.2f)) ) { Column(modifier = Modifier.fillMaxSize()) { // Header Bar Surface( color = DarkGreyGlassElevated, modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier .fillMaxWidth() .padding(14.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Row(verticalAlignment = Alignment.CenterVertically) { // Avatar Circle Box( modifier = Modifier .size(40.dp) .clip(CircleShape) .background(BrandGold), contentAlignment = Alignment.Center ) { Text( text = interlocutorName.take(1).uppercase(), color = Color.White, fontWeight = FontWeight.Bold, fontSize = 18.sp ) } Spacer(modifier = Modifier.width(12.dp)) Column { Text( text = interlocutorName, style = MaterialTheme.typography.titleMedium, color = TextPrimary, fontWeight = FontWeight.Bold ) Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.Default.VerifiedUser, contentDescription = null, tint = CyanAccent, modifier = Modifier.size(12.dp) ) Spacer(modifier = Modifier.width(4.dp)) Text( text = "Secure Escrow Chat • Contract #${booking.id}", style = MaterialTheme.typography.labelSmall, color = TextSecondary ) } } } IconButton( onClick = onDismiss, modifier = Modifier.testTag("private_chat_dismiss_btn") ) { Icon( imageVector = Icons.Default.Close, contentDescription = "Close Chat", tint = TextSecondary ) } } } // Security Notice Banner Surface( color = LightGold, modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier.padding(horizontal = 14.dp, vertical = 6.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { Icon( imageVector = Icons.Default.Lock, contentDescription = null, tint = BrandGold, modifier = Modifier.size(12.dp) ) Spacer(modifier = Modifier.width(6.dp)) Text( text = "Escrow locked chats are encrypted & verified for professional workplace security.", fontSize = 11.sp, color = BrandGold, fontWeight = FontWeight.Medium ) } } // Chat Messages List Box( modifier = Modifier .weight(1f) .fillMaxWidth() .background(Color.White) .padding(horizontal = 14.dp) ) { if (chats.isEmpty()) { Column( modifier = Modifier.align(Alignment.Center), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "💬 Start 1-on-1 Contract Chat", style = MaterialTheme.typography.titleSmall, color = TextSecondary, fontWeight = FontWeight.Bold ) Spacer(modifier = Modifier.height(4.dp)) Text( text = "Perfect! Coordinate meeting schedules & session details securely.", style = MaterialTheme.typography.bodySmall, color = TextSecondary ) } } else { LazyColumn( state = listState, modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues(vertical = 12.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { items(chats) { chat -> val isMe = chat.senderId == senderId val alignment = if (isMe) Alignment.End else Alignment.Start val bubbleBg = if (isMe) BrandGold else DarkGreyGlassElevated val textColor = if (isMe) Color.White else TextPrimary val bubbleShape = if (isMe) { RoundedCornerShape(12.dp, 12.dp, 0.dp, 12.dp) } else { RoundedCornerShape(12.dp, 12.dp, 12.dp, 0.dp) } Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = alignment ) { Surface( color = bubbleBg, shape = bubbleShape, border = if (isMe) null else BorderStroke(1.dp, Color.LightGray.copy(0.2f)) ) { Column(modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp)) { Text( text = chat.message, color = textColor, style = MaterialTheme.typography.bodyMedium ) } } Spacer(modifier = Modifier.height(2.dp)) Text( text = formatTime(chat.timestamp), style = MaterialTheme.typography.labelSmall, color = TextSecondary, modifier = Modifier.padding(horizontal = 4.dp) ) } } } } } // Chat Input Panel Surface( color = DarkGreyGlassElevated, modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier .fillMaxWidth() .padding(10.dp), verticalAlignment = Alignment.CenterVertically ) { TextField( value = textInput, onValueChange = { textInput = it }, placeholder = { Text("Write secured message...", fontSize = 14.sp) }, modifier = Modifier .weight(1f) .testTag("private_msg_input"), colors = TextFieldDefaults.colors( focusedContainerColor = Color.White, unfocusedContainerColor = Color.White, focusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent ), shape = RoundedCornerShape(20.dp), singleLine = true, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Send), keyboardActions = KeyboardActions(onSend = { if (textInput.isNotBlank()) { val msg = textInput viewModel.sendPrivateMessage( bookingId = booking.id, senderId = senderId, senderName = senderName, senderType = senderType, message = msg ) textInput = "" focusManager.clearFocus() // Simulated Auto-Reply logic for reactive feel coroutineScope.launch { delay(1500) val reply = generateAutoReply(senderType, msg, booking) viewModel.sendPrivateMessage( bookingId = booking.id, senderId = if (senderType == "USER") "model_${booking.modelId}" else booking.userId, senderName = if (senderType == "USER") booking.modelName else booking.userName, senderType = if (senderType == "USER") "MODEL" else "USER", message = reply ) } } }) ) Spacer(modifier = Modifier.width(8.dp)) IconButton( onClick = { if (textInput.isNotBlank()) { val msg = textInput viewModel.sendPrivateMessage( bookingId = booking.id, senderId = senderId, senderName = senderName, senderType = senderType, message = msg ) textInput = "" focusManager.clearFocus() // Simulated Auto-Reply logic for reactive feel coroutineScope.launch { delay(1500) val reply = generateAutoReply(senderType, msg, booking) viewModel.sendPrivateMessage( bookingId = booking.id, senderId = if (senderType == "USER") "model_${booking.modelId}" else booking.userId, senderName = if (senderType == "USER") booking.modelName else booking.userName, senderType = if (senderType == "USER") "MODEL" else "USER", message = reply ) } } }, modifier = Modifier .clip(CircleShape) .background(BrandGold) .size(40.dp) .testTag("private_msg_send_btn") ) { Icon( imageVector = Icons.AutoMirrored.Filled.Send, contentDescription = "Send", tint = Color.White, modifier = Modifier.size(18.dp) ) } } } } } } } private fun formatTime(timestamp: Long): String { val sdf = SimpleDateFormat("hh:mm a", Locale.getDefault()) return sdf.format(Date(timestamp)) } private fun generateAutoReply(myRole: String, msgEntered: String, booking: BookingEntity): String { val lowercaseMsg = msgEntered.lowercase() if (myRole == "USER") { // Model responds to user return when { lowercaseMsg.contains("hello") || lowercaseMsg.contains("hi") || lowercaseMsg.contains("hey") -> { "Hey! Super excited for our shoot. 📸 Everything is ready on my side. Let's make it an amazing session!" } lowercaseMsg.contains("where") || lowercaseMsg.contains("address") || lowercaseMsg.contains("location") || lowercaseMsg.contains("venue") -> { "The venue at '${booking.location}' is perfect for the concept. I'll reach there safely on time." } lowercaseMsg.contains("time") || lowercaseMsg.contains("schedule") || lowercaseMsg.contains("when") || lowercaseMsg.contains("date") -> { "Yes! Confirmed for ${booking.dateString} at ${booking.bookingTime}. See you then!" } lowercaseMsg.contains("rate") || lowercaseMsg.contains("price") || lowercaseMsg.contains("money") || lowercaseMsg.contains("pay") -> { "Perfect! The secure escrow amount of ৳${String.format(Locale.US, "%,.0f", booking.totalPrice)} is locked and safe. No other fee is needed." } lowercaseMsg.contains("ok") || lowercaseMsg.contains("yes") || lowercaseMsg.contains("perfect") || lowercaseMsg.contains("cool") -> { "Sweet! Text me anytime here if you have safehouse guidelines or references." } else -> { "Received! I'm coordinating my travel schedule right now. I'll message you here as soon as I head out. 🚀" } } } else { // User responds to model return when { lowercaseMsg.contains("hello") || lowercaseMsg.contains("hi") || lowercaseMsg.contains("hey") -> { "Hello! Yes, checking in. Glad we're locked for the job." } else -> { "Perfect, thanks for keeping in touch! Looking forward to the coordination of model dispatch." } } } }