package com.aistudio.bonjuteri.jwlry.ui.screens import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width 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.Add import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.LocationOn import androidx.compose.material.icons.filled.Payment import androidx.compose.material.icons.outlined.Info import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.aistudio.bonjuteri.jwlry.data.CartRepository import com.aistudio.bonjuteri.jwlry.model.Address import com.aistudio.bonjuteri.jwlry.model.CartItem import com.aistudio.bonjuteri.jwlry.model.Order import com.aistudio.bonjuteri.jwlry.model.Product import com.aistudio.bonjuteri.jwlry.ui.theme.GoldPrimary import com.aistudio.bonjuteri.jwlry.ui.theme.GoldSubtle import com.aistudio.bonjuteri.jwlry.ui.theme.InfoBlue import com.aistudio.bonjuteri.jwlry.ui.theme.MutedGrey import com.aistudio.bonjuteri.jwlry.ui.theme.OffWhite import com.aistudio.bonjuteri.jwlry.ui.theme.PrimaryBlack import com.aistudio.bonjuteri.jwlry.ui.theme.PureWhite import com.aistudio.bonjuteri.jwlry.ui.theme.SuccessGreen import com.aistudio.bonjuteri.jwlry.ui.theme.SurfaceBorder import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable fun CheckoutScreen( cartItems: List, addresses: List
, onBackClick: () -> Unit, onSaveNewAddress: suspend (Address) -> Result
, onCreateOrder: suspend (Address, String) -> Result, onOrderSuccess: (Order) -> Unit, modifier: Modifier = Modifier ) { val subtotal = cartItems.sumOf { it.totalPrice } val isFreeShipping = subtotal >= CartRepository.FREE_SHIPPING_THRESHOLD val shippingCost = if (isFreeShipping) 0.0 else CartRepository.STANDARD_SHIPPING_COST val totalAmount = subtotal + shippingCost var selectedAddressId by remember(addresses) { mutableStateOf(addresses.firstOrNull()?.id ?: "") } var isAddingNewAddress by remember { mutableStateOf(addresses.isEmpty()) } var newAddressTitle by remember { mutableStateOf("Evim") } var newFullName by remember { mutableStateOf("") } var newPhone by remember { mutableStateOf("") } var newCity by remember { mutableStateOf("İstanbul") } var newDistrict by remember { mutableStateOf("") } var newNeighborhood by remember { mutableStateOf("") } var newFullAddress by remember { mutableStateOf("") } var newPostalCode by remember { mutableStateOf("") } var selectedPaymentMethod by remember { mutableStateOf("Havale / EFT & Kapıda Ödeme") } var isSubmitting by remember { mutableStateOf(false) } var errorMessage by remember { mutableStateOf(null) } val scope = rememberCoroutineScope() Scaffold( topBar = { TopAppBar( title = { Text("Siparişi Tamamla", fontWeight = FontWeight.Bold) }, navigationIcon = { IconButton(onClick = onBackClick) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Geri") } }, colors = TopAppBarDefaults.topAppBarColors(containerColor = PureWhite) ) }, bottomBar = { Surface( color = PureWhite, shadowElevation = 8.dp, modifier = Modifier.fillMaxWidth() ) { Column(modifier = Modifier.padding(16.dp)) { if (errorMessage != null) { Text( text = errorMessage!!, color = MaterialTheme.colorScheme.error, fontSize = 12.sp, modifier = Modifier.padding(bottom = 8.dp) ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Column { Text("Ödenecek Tutar", color = MutedGrey, fontSize = 11.sp) Text( text = Product.formatCurrency(totalAmount), fontWeight = FontWeight.Black, fontSize = 18.sp, color = PrimaryBlack ) } Button( onClick = { scope.launch { isSubmitting = true errorMessage = null var chosenAddress = addresses.firstOrNull { it.id == selectedAddressId } // If adding new address inline if (chosenAddress == null || isAddingNewAddress) { val newAddr = Address( title = newAddressTitle, fullName = newFullName, phone = newPhone, city = newCity, district = newDistrict, neighborhood = newNeighborhood, fullAddress = newFullAddress, postalCode = newPostalCode ) val saveResult = onSaveNewAddress(newAddr) if (saveResult.isFailure) { errorMessage = saveResult.exceptionOrNull()?.message ?: "Adres kaydedilemedi." isSubmitting = false return@launch } chosenAddress = saveResult.getOrNull() } if (chosenAddress == null) { errorMessage = "Lütfen bir teslimat adresi seçiniz veya ekleyiniz." isSubmitting = false return@launch } val orderResult = onCreateOrder(chosenAddress, selectedPaymentMethod) isSubmitting = false if (orderResult.isSuccess) { onOrderSuccess(orderResult.getOrThrow()) } else { errorMessage = orderResult.exceptionOrNull()?.message ?: "Sipariş oluşturulamadı." } } }, enabled = !isSubmitting, modifier = Modifier .height(48.dp) .testTag("confirm_order_button"), shape = RoundedCornerShape(10.dp), colors = ButtonDefaults.buttonColors( containerColor = PrimaryBlack, contentColor = PureWhite ) ) { if (isSubmitting) { CircularProgressIndicator(color = PureWhite, modifier = Modifier.size(20.dp)) } else { Text("Siparişi Onayla", fontWeight = FontWeight.Bold, fontSize = 14.sp) } } } } } } ) { padding -> Column( modifier = modifier .fillMaxSize() .padding(padding) .background(OffWhite) .verticalScroll(rememberScrollState()) .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { // Address Section Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = PureWhite), shape = RoundedCornerShape(12.dp) ) { Column(modifier = Modifier.padding(14.dp)) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Filled.LocationOn, contentDescription = null, tint = GoldPrimary, modifier = Modifier.size(20.dp)) Spacer(modifier = Modifier.width(8.dp)) Text("Teslimat Adresi", fontWeight = FontWeight.Bold, fontSize = 15.sp) } if (addresses.isNotEmpty()) { Text( text = if (isAddingNewAddress) "Kayıtlı Adresler" else "+ Yeni Adres", color = GoldPrimary, fontWeight = FontWeight.Bold, fontSize = 12.sp, modifier = Modifier.clickable { isAddingNewAddress = !isAddingNewAddress } ) } } Spacer(modifier = Modifier.height(10.dp)) if (!isAddingNewAddress && addresses.isNotEmpty()) { addresses.forEach { addr -> val isSelected = addr.id == selectedAddressId Row( modifier = Modifier .fillMaxWidth() .padding(vertical = 4.dp) .border( width = if (isSelected) 1.5.dp else 1.dp, color = if (isSelected) GoldPrimary else SurfaceBorder, shape = RoundedCornerShape(8.dp) ) .clickable { selectedAddressId = addr.id } .padding(10.dp), verticalAlignment = Alignment.CenterVertically ) { Box( modifier = Modifier .size(20.dp) .border(2.dp, if (isSelected) GoldPrimary else MutedGrey, CircleShape), contentAlignment = Alignment.Center ) { if (isSelected) { Box(modifier = Modifier.size(10.dp).background(GoldPrimary, CircleShape)) } } Spacer(modifier = Modifier.width(10.dp)) Column { Text("${addr.title} - ${addr.fullName}", fontWeight = FontWeight.Bold, fontSize = 13.sp) Text(addr.fullDisplayAddress, color = MutedGrey, fontSize = 12.sp) Text(addr.phone, color = MutedGrey, fontSize = 11.sp) } } } } else { // New Address Input Form Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { OutlinedTextField( value = newAddressTitle, onValueChange = { newAddressTitle = it }, label = { Text("Adres Başlığı (Ev, İş vb.)") }, modifier = Modifier.fillMaxWidth(), singleLine = true ) OutlinedTextField( value = newFullName, onValueChange = { newFullName = it }, label = { Text("Ad Soyad") }, modifier = Modifier.fillMaxWidth().testTag("checkout_name_input"), singleLine = true ) OutlinedTextField( value = newPhone, onValueChange = { newPhone = it }, label = { Text("Telefon") }, modifier = Modifier.fillMaxWidth().testTag("checkout_phone_input"), singleLine = true ) Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { OutlinedTextField( value = newCity, onValueChange = { newCity = it }, label = { Text("İl") }, modifier = Modifier.weight(1f), singleLine = true ) OutlinedTextField( value = newDistrict, onValueChange = { newDistrict = it }, label = { Text("İlçe") }, modifier = Modifier.weight(1f).testTag("checkout_district_input"), singleLine = true ) } OutlinedTextField( value = newNeighborhood, onValueChange = { newNeighborhood = it }, label = { Text("Mahalle") }, modifier = Modifier.fillMaxWidth(), singleLine = true ) OutlinedTextField( value = newFullAddress, onValueChange = { newFullAddress = it }, label = { Text("Açık Adres (Cadde, Sokak, No, Daire)") }, modifier = Modifier.fillMaxWidth().testTag("checkout_address_input"), maxLines = 3 ) OutlinedTextField( value = newPostalCode, onValueChange = { newPostalCode = it }, label = { Text("Posta Kodu") }, modifier = Modifier.fillMaxWidth(), singleLine = true ) } } } } // Payment Notice Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = PureWhite), shape = RoundedCornerShape(12.dp) ) { Column(modifier = Modifier.padding(14.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Filled.Payment, contentDescription = null, tint = GoldPrimary, modifier = Modifier.size(20.dp)) Spacer(modifier = Modifier.width(8.dp)) Text("Ödeme Yöntemi", fontWeight = FontWeight.Bold, fontSize = 15.sp) } Spacer(modifier = Modifier.height(10.dp)) Card( colors = CardDefaults.cardColors(containerColor = GoldSubtle), shape = RoundedCornerShape(8.dp), modifier = Modifier.fillMaxWidth() ) { Row(modifier = Modifier.padding(12.dp), verticalAlignment = Alignment.Top) { Icon(Icons.Outlined.Info, contentDescription = null, tint = GoldPrimary, modifier = Modifier.size(18.dp)) Spacer(modifier = Modifier.width(8.dp)) Text( text = "Ödeme Yöntemi: Havale / EFT & Kapıda Ödeme\nSiparişiniz 'Ödeme Bekleniyor' olarak sisteme kaydedilecek, BONJUTERİ müşteri temsilcimiz sizinle irtibata geçecektir.", fontSize = 12.sp, color = PrimaryBlack, lineHeight = 16.sp ) } } } } // Order Summary Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = PureWhite), shape = RoundedCornerShape(12.dp) ) { Column(modifier = Modifier.padding(14.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { Text("Sipariş Özeti", fontWeight = FontWeight.Bold, fontSize = 15.sp) Text("${cartItems.sumOf { it.quantity }} Ürün", color = MutedGrey, fontSize = 12.sp) HorizontalDivider(color = SurfaceBorder) Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { Text("Ara Toplam", color = MutedGrey, fontSize = 13.sp) Text(Product.formatCurrency(subtotal), fontWeight = FontWeight.SemiBold, fontSize = 13.sp) } Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { Text("Kargo", color = MutedGrey, fontSize = 13.sp) Text( text = if (isFreeShipping) "ÜCRETSİZ" else Product.formatCurrency(shippingCost), fontWeight = FontWeight.SemiBold, color = if (isFreeShipping) SuccessGreen else PrimaryBlack, fontSize = 13.sp ) } HorizontalDivider(color = SurfaceBorder) Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { Text("Toplam", fontWeight = FontWeight.Bold, fontSize = 15.sp) Text(Product.formatCurrency(totalAmount), fontWeight = FontWeight.Black, fontSize = 16.sp) } } } } } }