package sh.sar.gridflow import android.content.Intent import android.net.Uri import android.os.Bundle import android.util.Log import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.coroutines.launch import sh.sar.gridflow.data.OutstandingBill import sh.sar.gridflow.data.PaymentDetails import sh.sar.gridflow.data.PaymentGateway import sh.sar.gridflow.data.PaymentItem import sh.sar.gridflow.data.PaymentRequest import sh.sar.gridflow.databinding.ActivityPaymentReviewBinding import sh.sar.gridflow.network.ApiResult import sh.sar.gridflow.network.FenakaApiService import sh.sar.gridflow.ui.payment.BillSummaryAdapter import sh.sar.gridflow.ui.payment.PaymentConfirmationDialog import sh.sar.gridflow.ui.payment.PaymentMethodAdapter import sh.sar.gridflow.utils.SecureStorage class PaymentReviewActivity : AppCompatActivity() { private lateinit var binding: ActivityPaymentReviewBinding private lateinit var secureStorage: SecureStorage private lateinit var apiService: FenakaApiService private lateinit var billSummaryAdapter: BillSummaryAdapter private lateinit var paymentMethodAdapter: PaymentMethodAdapter private var outstandingBills: List = emptyList() private var isSingleBillMode: Boolean = false private var singleBillData: SingleBillData? = null data class SingleBillData( val billId: Long, val amount: String, val billNumber: String, val subscriptionId: Long ) companion object { private const val TAG = "PaymentReviewActivity" } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Force system theme (follows device dark mode setting) AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) binding = ActivityPaymentReviewBinding.inflate(layoutInflater) setContentView(binding.root) secureStorage = SecureStorage(this) apiService = FenakaApiService() // Check if this is single bill mode checkForSingleBillMode() setupViews() loadData() } private fun checkForSingleBillMode() { val billId = intent.getLongExtra("SINGLE_BILL_ID", -1L) if (billId != -1L) { isSingleBillMode = true singleBillData = SingleBillData( billId = billId, amount = intent.getStringExtra("SINGLE_BILL_AMOUNT") ?: "0.00", billNumber = intent.getStringExtra("SINGLE_BILL_NUMBER") ?: "", subscriptionId = intent.getLongExtra("SINGLE_BILL_SUBSCRIPTION_ID", -1L) ) Log.d(TAG, "Single bill mode activated for bill: ${singleBillData?.billNumber}") } } private fun setupViews() { // Setup bills RecyclerView billSummaryAdapter = BillSummaryAdapter() binding.recyclerBills.apply { layoutManager = LinearLayoutManager(this@PaymentReviewActivity) adapter = billSummaryAdapter } // Setup payment methods RecyclerView paymentMethodAdapter = PaymentMethodAdapter { paymentMethod -> onPaymentMethodSelected(paymentMethod) } binding.recyclerPaymentMethods.apply { layoutManager = LinearLayoutManager(this@PaymentReviewActivity) adapter = paymentMethodAdapter } } private fun loadData() { val cookie = secureStorage.getCookie() if (cookie == null) { Toast.makeText(this, "Authentication required", Toast.LENGTH_SHORT).show() finish() return } if (isSingleBillMode) { loadSingleBillMode(cookie) } else { loadOutstandingBillsMode(cookie) } } private fun loadSingleBillMode(cookie: String) { singleBillData?.let { billData -> // Create fake OutstandingBill for single bill mode val fakeOutstandingBill = OutstandingBill( id = billData.billId, branchName = "", subscriptionId = billData.subscriptionId, subscriptionStatus = "active", subscriptionNumber = billData.billNumber, outstandingBillCount = "1", billAmount = billData.amount, paidAmount = "0", outstandingAmount = billData.amount ) outstandingBills = listOf(fakeOutstandingBill) updateBillsUI() } showLoading(true) lifecycleScope.launch { // Load payment methods when (val gatewaysResult = apiService.getPaymentGateways("connect.sid=$cookie")) { is ApiResult.Success -> { paymentMethodAdapter.updatePaymentMethods(gatewaysResult.data) showLoading(false) } is ApiResult.Error -> { Log.e(TAG, "Failed to load payment gateways: ${gatewaysResult.message}") showLoading(false) Toast.makeText(this@PaymentReviewActivity, "Failed to load payment methods", Toast.LENGTH_SHORT).show() } } } } private fun loadOutstandingBillsMode(cookie: String) { showLoading(true) lifecycleScope.launch { // Load outstanding bills first when (val billsResult = apiService.getOutstandingBills("connect.sid=$cookie")) { is ApiResult.Success -> { outstandingBills = billsResult.data updateBillsUI() // Then load payment methods when (val gatewaysResult = apiService.getPaymentGateways("connect.sid=$cookie")) { is ApiResult.Success -> { paymentMethodAdapter.updatePaymentMethods(gatewaysResult.data) showLoading(false) } is ApiResult.Error -> { Log.e(TAG, "Failed to load payment gateways: ${gatewaysResult.message}") showLoading(false) Toast.makeText(this@PaymentReviewActivity, "Failed to load payment methods", Toast.LENGTH_SHORT).show() } } } is ApiResult.Error -> { Log.e(TAG, "Failed to load outstanding bills: ${billsResult.message}") showLoading(false) Toast.makeText(this@PaymentReviewActivity, "Failed to load bills", Toast.LENGTH_SHORT).show() } } } } private fun updateBillsUI() { billSummaryAdapter.updateBills(outstandingBills) // Calculate total bills count val totalBillCount = outstandingBills.sumOf { bill -> try { bill.outstandingBillCount.toInt() } catch (e: NumberFormatException) { 0 } } // Calculate total amount val totalAmount = outstandingBills.sumOf { bill -> try { bill.outstandingAmount.toDouble() } catch (e: NumberFormatException) { 0.0 } } binding.textBillCount.text = "You are paying a total of $totalBillCount bills" binding.textTotalAmount.text = "MVR ${String.format("%.2f", totalAmount)}" } private fun showLoading(show: Boolean) { binding.layoutLoading.visibility = if (show) View.VISIBLE else View.GONE binding.recyclerPaymentMethods.visibility = if (show) View.GONE else View.VISIBLE } private fun onPaymentMethodSelected(paymentMethod: PaymentGateway) { Log.d(TAG, "Payment method selected: ${paymentMethod.name} (${paymentMethod.code})") // Show payment confirmation dialog PaymentConfirmationDialog.show( context = this, paymentGateway = paymentMethod, onContinue = { dialog -> if (paymentMethod.code == "bml") { processBmlPayment(dialog) } else { Toast.makeText(this, "Not yet implemented.. use BML", Toast.LENGTH_SHORT).show() dialog.dismiss() } }, onCancel = { Log.d(TAG, "Payment cancelled by user") } ) } private fun processBmlPayment(dialog: PaymentConfirmationDialog) { val cookie = secureStorage.getCookie() if (cookie == null) { Toast.makeText(this, "Authentication required", Toast.LENGTH_SHORT).show() dialog.dismiss() return } Log.d(TAG, "Processing BML payment...") dialog.showLoading(true) lifecycleScope.launch { try { // Create payment items from outstanding bills val paymentItems = outstandingBills.map { bill -> PaymentItem( id = bill.subscriptionId, type = "subscription", amount = bill.outstandingAmount.toDoubleOrNull() ?: 0.0 ) } val paymentRequest = PaymentRequest( gateway = "bml", details = PaymentDetails(items = paymentItems) ) // Step 1: Initiate payment when (val paymentResult = apiService.initiatePayment(paymentRequest, "connect.sid=$cookie")) { is ApiResult.Success -> { val paymentResponse = paymentResult.data Log.d(TAG, "Payment initiated successfully. ID: ${paymentResponse.id}") // Calculate total amount val totalAmount = paymentItems.sumOf { it.amount } // Step 2: Get redirect URL when (val redirectResult = apiService.getPaymentRedirectUrl( gateway = "bml", reference = paymentResponse.id, amount = totalAmount, cookie = "connect.sid=$cookie" )) { is ApiResult.Success -> { val redirectUrl = redirectResult.data Log.d(TAG, "Got redirect URL: $redirectUrl") // Open browser with redirect URL openBrowser(redirectUrl) dialog.dismiss() // Take user back (finish activity) finish() } is ApiResult.Error -> { Log.e(TAG, "Failed to get redirect URL: ${redirectResult.message}") dialog.showLoading(false) Toast.makeText(this@PaymentReviewActivity, "Failed to get payment URL", Toast.LENGTH_SHORT).show() } } } is ApiResult.Error -> { Log.e(TAG, "Failed to initiate payment: ${paymentResult.message}") dialog.showLoading(false) Toast.makeText(this@PaymentReviewActivity, "Failed to initiate payment", Toast.LENGTH_SHORT).show() } } } catch (e: Exception) { Log.e(TAG, "Error processing BML payment", e) dialog.showLoading(false) Toast.makeText(this@PaymentReviewActivity, "Payment processing error", Toast.LENGTH_SHORT).show() } } } private fun openBrowser(url: String) { try { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) startActivity(intent) Log.d(TAG, "Opened browser with URL: $url") } catch (e: Exception) { Log.e(TAG, "Failed to open browser", e) Toast.makeText(this, "Failed to open browser", Toast.LENGTH_SHORT).show() } } }