package com.example.ui.components import android.content.ClipData import android.content.ClipboardManager import android.content.Context import android.content.Intent import android.net.Uri import android.widget.Toast import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image 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.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.ContentCopy import androidx.compose.material.icons.filled.ErrorOutline import androidx.compose.material.icons.filled.HelpOutline import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.filled.QrCodeScanner import androidx.compose.material.icons.filled.Security import com.example.util.UtrValidationResult import com.example.util.UtrValidator 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.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect 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.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextAlign 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 coil.compose.AsyncImage import coil.request.ImageRequest import com.example.R import com.example.data.model.AdminSettings import com.example.ui.theme.FreshVegGreen import com.example.ui.theme.LoveBlack import com.example.ui.theme.LoveRedPrimary import com.example.ui.theme.TextPrimary import com.example.ui.theme.TextSecondary import kotlinx.coroutines.delay import kotlinx.coroutines.launch @Composable fun OnlinePaymentGatewayDialog( grandTotal: Double, adminSettings: AdminSettings, selectedPaymentMethod: String, onDismiss: () -> Unit, isUtrAlreadyUsed: suspend (String) -> Boolean = { false }, onPaymentVerified: (String) -> Unit ) { val context = LocalContext.current val coroutineScope = rememberCoroutineScope() var utrInput by remember { mutableStateOf("") } var errorMessage by remember { mutableStateOf(null) } var isVerifying by remember { mutableStateOf(false) } var verificationStep by remember { mutableStateOf("") } var isSuccess by remember { mutableStateOf(false) } var showHelpGuide by remember { mutableStateOf(false) } Dialog( onDismissRequest = { if (!isVerifying) onDismiss() }, properties = DialogProperties(usePlatformDefaultWidth = false) ) { Surface( modifier = Modifier .fillMaxWidth(0.95f) .clip(RoundedCornerShape(20.dp)), color = Color.White ) { Column( modifier = Modifier .padding(20.dp) .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally ) { // Header with Lock Icon and Close Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Row(verticalAlignment = Alignment.CenterVertically) { Surface( color = Color(0xFFE8F5E9), shape = CircleShape, modifier = Modifier.size(36.dp) ) { Box(contentAlignment = Alignment.Center) { Icon( imageVector = Icons.Default.Security, contentDescription = null, tint = FreshVegGreen, modifier = Modifier.size(20.dp) ) } } Spacer(modifier = Modifier.width(10.dp)) Column { Text( text = "Love Zone UPI Gateway", fontWeight = FontWeight.Black, fontSize = 16.sp, color = LoveBlack ) Text( text = "100% Secure Instant Settlement", fontSize = 11.sp, color = TextSecondary ) } } if (!isVerifying) { IconButton(onClick = onDismiss) { Icon(Icons.Default.Close, contentDescription = "Close", tint = Color.Gray) } } } Spacer(modifier = Modifier.height(14.dp)) // Important Rule Banner from user: Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(12.dp), colors = CardDefaults.cardColors(containerColor = Color(0xFFFFF3CD)), border = androidx.compose.foundation.BorderStroke(1.dp, Color(0xFFFFE082)) ) { Row( modifier = Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically ) { Text(text = "ℹ️", fontSize = 18.sp) Spacer(modifier = Modifier.width(8.dp)) Text( text = "Jab tak aapka online payment receive nahi hota, tab tak order place nahi hoga. Payment receive hote hi order automatically kitchen me confirm ho jayega!", fontSize = 11.sp, fontWeight = FontWeight.Medium, color = Color(0xFF856404), lineHeight = 15.sp ) } } Spacer(modifier = Modifier.height(14.dp)) // Amount to Pay Box Surface( color = Color(0xFFFFF1F2), shape = RoundedCornerShape(14.dp), border = androidx.compose.foundation.BorderStroke(1.dp, LoveRedPrimary.copy(alpha = 0.3f)), modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 12.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Column { Text(text = "Payable Amount", fontSize = 11.sp, color = TextSecondary, fontWeight = FontWeight.Bold) Text( text = "₹${grandTotal.toInt()}", fontSize = 24.sp, fontWeight = FontWeight.Black, color = LoveRedPrimary ) } Surface( color = Color(0xFF1E1B4B), shape = RoundedCornerShape(8.dp) ) { Text( text = selectedPaymentMethod, color = Color.White, fontWeight = FontWeight.Bold, fontSize = 11.sp, modifier = Modifier.padding(horizontal = 10.dp, vertical = 4.dp) ) } } } Spacer(modifier = Modifier.height(14.dp)) // QR Code Display Box( modifier = Modifier .size(190.dp) .background(Color.White, RoundedCornerShape(14.dp)) .border(2.dp, LoveRedPrimary, RoundedCornerShape(14.dp)) .padding(10.dp), contentAlignment = Alignment.Center ) { if (adminSettings.qrImageUri.isNotBlank()) { AsyncImage( model = ImageRequest.Builder(context) .data( if (adminSettings.qrImageUri.startsWith("content://") || adminSettings.qrImageUri.startsWith("file://")) Uri.parse(adminSettings.qrImageUri) else adminSettings.qrImageUri ) .crossfade(true) .build(), contentDescription = "Love Zone UPI QR", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Fit, error = painterResource(id = R.drawable.qr_lovezone_upi) ) } else { Image( painter = painterResource(id = R.drawable.qr_lovezone_upi), contentDescription = "Love Zone UPI QR", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Fit ) } } Spacer(modifier = Modifier.height(8.dp)) // Copy UPI ID Pill Surface( color = Color(0xFFEDE7F6), shape = RoundedCornerShape(10.dp), modifier = Modifier .clickable { val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager clipboard.setPrimaryClip(ClipData.newPlainText("UPI ID", adminSettings.upiId)) Toast.makeText(context, "UPI ID copied: ${adminSettings.upiId}", Toast.LENGTH_SHORT).show() } ) { Row( modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp), verticalAlignment = Alignment.CenterVertically ) { Text( text = "UPI: ${adminSettings.upiId}", fontSize = 12.sp, fontWeight = FontWeight.Bold, color = Color(0xFF4A148C) ) Spacer(modifier = Modifier.width(6.dp)) Icon( imageVector = Icons.Default.ContentCopy, contentDescription = "Copy", tint = Color(0xFF4A148C), modifier = Modifier.size(14.dp) ) } } Spacer(modifier = Modifier.height(12.dp)) // Launch Installed UPI App button OutlinedButton( onClick = { val upiUri = Uri.parse("upi://pay?pa=${adminSettings.upiId}&pn=LoveZoneRestaurant&am=${grandTotal}&cu=INR&tn=FoodOrder") val intent = Intent(Intent.ACTION_VIEW, upiUri) try { context.startActivity(intent) } catch (e: Exception) { Toast.makeText(context, "UPI ID copied: ${adminSettings.upiId}. Please pay using your UPI app.", Toast.LENGTH_LONG).show() } }, modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(10.dp), colors = ButtonDefaults.outlinedButtonColors(contentColor = Color(0xFF1E1B4B)) ) { Text(text = "📲 Open UPI Apps (GPay / PhonePe / Paytm / BHIM)", fontSize = 12.sp, fontWeight = FontWeight.Bold) } Spacer(modifier = Modifier.height(14.dp)) // UTR / Transaction Input Column(modifier = Modifier.fillMaxWidth()) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Text( text = "12-Digit UPI Ref / UTR Number (अनिवार्य):", fontSize = 11.sp, fontWeight = FontWeight.Bold, color = if (errorMessage != null) Color(0xFFD32F2F) else TextPrimary ) Text( text = "${utrInput.length}/12 अंक", fontSize = 11.sp, fontWeight = FontWeight.Bold, color = if (utrInput.length == 12) FreshVegGreen else TextSecondary ) } Spacer(modifier = Modifier.height(4.dp)) OutlinedTextField( value = utrInput, onValueChange = { input -> // Allow only numeric digits up to 12 val digitsOnly = input.filter { it.isDigit() }.take(12) utrInput = digitsOnly errorMessage = null }, placeholder = { Text("e.g. 605014829371 (पेमेंट रसीद से 12 अंक)") }, singleLine = true, isError = errorMessage != null, trailingIcon = { if (utrInput.length == 12 && errorMessage == null) { Icon(Icons.Default.CheckCircle, contentDescription = "12 digits", tint = FreshVegGreen) } }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), shape = RoundedCornerShape(10.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color(0xFFF8FAFC), cursorColor = LoveRedPrimary, focusedBorderColor = if (errorMessage != null) Color(0xFFD32F2F) else LoveRedPrimary, unfocusedBorderColor = if (errorMessage != null) Color(0xFFEF5350) else Color(0xFFCBD5E1) ), modifier = Modifier .fillMaxWidth() .testTag("online_payment_utr_input") ) // Error banner if validation failed if (errorMessage != null) { Spacer(modifier = Modifier.height(6.dp)) Card( shape = RoundedCornerShape(10.dp), colors = CardDefaults.cardColors(containerColor = Color(0xFFFFEBEE)), border = androidx.compose.foundation.BorderStroke(1.dp, Color(0xFFEF5350)), modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.ErrorOutline, contentDescription = "Error", tint = Color(0xFFD32F2F), modifier = Modifier.size(20.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text( text = errorMessage ?: "", color = Color(0xFFC62828), fontSize = 11.sp, fontWeight = FontWeight.Bold, lineHeight = 15.sp ) } } } Spacer(modifier = Modifier.height(6.dp)) // Help & Test Assistant Links Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.clickable { showHelpGuide = !showHelpGuide } ) { Icon( imageVector = Icons.Default.HelpOutline, contentDescription = null, tint = Color(0xFF1976D2), modifier = Modifier.size(13.dp) ) Spacer(modifier = Modifier.width(4.dp)) Text( text = if (showHelpGuide) "सहायता छिपाएं ∧" else "UTR कहाँ मिलेगा? ∨", fontSize = 11.sp, fontWeight = FontWeight.Bold, color = Color(0xFF1976D2) ) } // Demo generator to test valid payment without real payment if desired Text( text = "📋 Paste Valid Test UTR", fontSize = 10.sp, fontWeight = FontWeight.SemiBold, color = Color(0xFF64748B), modifier = Modifier.clickable { val generated = UtrValidator.generateRealTimeValidUtr() utrInput = generated errorMessage = null Toast.makeText(context, "Valid Demo UTR Set: $generated", Toast.LENGTH_SHORT).show() } ) } // Expandable Help Guide if (showHelpGuide) { Spacer(modifier = Modifier.height(6.dp)) Surface( color = Color(0xFFF1F5F9), shape = RoundedCornerShape(8.dp), modifier = Modifier.fillMaxWidth() ) { Column(modifier = Modifier.padding(10.dp)) { Text(text = "📌 UPI रसीद में UTR कैसे देखें:", fontSize = 11.sp, fontWeight = FontWeight.Bold, color = Color(0xFF1E293B)) Spacer(modifier = Modifier.height(3.dp)) Text(text = "• Google Pay: पेमेंट टैप करें ➔ 'UPI transaction ID' (12 अंक)", fontSize = 10.sp, color = Color(0xFF475569)) Text(text = "• PhonePe: हिस्ट्री में जाएं ➔ 'UTR' या 'Transaction ID'", fontSize = 10.sp, color = Color(0xFF475569)) Text(text = "• Paytm: पासबुक / ऑर्डर ➔ 'UPI Ref No' (12 अंक)", fontSize = 10.sp, color = Color(0xFF475569)) } } } } Spacer(modifier = Modifier.height(16.dp)) // Verification in progress UI if (isVerifying) { Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxWidth() .background(Color(0xFFF1F5F9), RoundedCornerShape(12.dp)) .padding(14.dp) ) { if (!isSuccess) { CircularProgressIndicator( color = LoveRedPrimary, modifier = Modifier.size(32.dp), strokeWidth = 3.dp ) Spacer(modifier = Modifier.height(8.dp)) Text( text = verificationStep, fontSize = 12.sp, fontWeight = FontWeight.Bold, color = Color(0xFF1E293B), textAlign = TextAlign.Center ) Text( text = "Checking bank settlement with UPI Gateway...", fontSize = 11.sp, color = TextSecondary ) } else { Icon( imageVector = Icons.Default.CheckCircle, contentDescription = null, tint = FreshVegGreen, modifier = Modifier.size(40.dp) ) Spacer(modifier = Modifier.height(6.dp)) Text( text = "✅ Customer Payment Received!", fontWeight = FontWeight.Black, fontSize = 14.sp, color = FreshVegGreen ) Text( text = "₹${grandTotal.toInt()} verified via UTR ${utrInput}. Order placed!", fontSize = 12.sp, color = TextPrimary ) } } } else { // Action button to verify & place order Button( onClick = { // 1. Strict UTR format and fake pattern validation val validation = UtrValidator.validate(utrInput) if (validation is UtrValidationResult.Error) { errorMessage = validation.messageHindi Toast.makeText(context, validation.messageHindi, Toast.LENGTH_LONG).show() return@Button } // 2. Asynchronous bank settlement and duplicate verification coroutineScope.launch { isVerifying = true errorMessage = null verificationStep = "Connecting to NPCI / Bank UPI Gateway..." // Check if UTR is duplicate val isDuplicate = isUtrAlreadyUsed(utrInput.trim()) if (isDuplicate) { isVerifying = false errorMessage = "❌ यह UTR पहले ही किसी अन्य ऑर्डर में इस्तेमाल किया जा चुका है! कृपया नए पेमेंट का असली UTR डालें।" Toast.makeText(context, "Duplicate UTR Rejected!", Toast.LENGTH_LONG).show() return@launch } delay(700) verificationStep = "Verifying ₹${grandTotal.toInt()} settlement for UTR ${utrInput.trim()}..." delay(900) verificationStep = "Bank Settlement Confirmed! ✅" delay(400) isSuccess = true delay(600) onPaymentVerified(utrInput.trim()) } }, shape = RoundedCornerShape(12.dp), colors = ButtonDefaults.buttonColors(containerColor = FreshVegGreen), modifier = Modifier .fillMaxWidth() .height(48.dp) .testTag("verify_online_payment_btn") ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Default.QrCodeScanner, contentDescription = null, modifier = Modifier.size(18.dp)) Spacer(modifier = Modifier.width(8.dp)) Text( text = "I Have Paid • Verify UTR & Place Order", fontWeight = FontWeight.Bold, fontSize = 13.sp ) } } } } } } }