package com.example.bdkipoc;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Random;
import java.util.UUID;

public class QrisActivity extends AppCompatActivity {

    private ProgressBar progressBar;
    private Button initiatePaymentButton;
    private TextView statusTextView;
    private EditText editTextAmount;
    private TextView referenceIdTextView;
    private LinearLayout backNavigation;
    
    // Numpad buttons
    private TextView btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btn0, btn000, btnDelete;
    private TextView descriptionText;

    private String transactionId;
    private String transactionUuid;
    private String referenceId;
    private int amount;
    private JSONObject midtransResponse;
    
    private StringBuilder currentAmount = new StringBuilder();

    // ✅ FRONTEND DEDUPLICATION: Add SharedPreferences for tracking
    private SharedPreferences transactionPrefs;
    private static final String PREF_RECENT_REFERENCES = "recent_references";
    private static final String PREF_LAST_TRANSACTION_TIME = "last_transaction_time";
    private static final String PREF_CURRENT_REFERENCE = "current_reference";
    private static final String PREF_LAST_SUCCESSFUL_TX = "last_successful_tx";
    private static final long REFERENCE_COOLDOWN_MS = 60000; // 1 minute cooldown
    private static final long TRANSACTION_COOLDOWN_MS = 5000; // 5 second cooldown

    private static final String BACKEND_BASE = "https://be-edc.msvc.app";
    private static final String MIDTRANS_CHARGE_URL = "https://api.sandbox.midtrans.com/v2/charge";
    private static final String MIDTRANS_AUTH = "Basic U0ItTWlkLXNlcnZlci1JM2RJWXdIRzVuamVMeHJCMVZ5endWMUM="; // Replace with your actual key
    private static final String WEBHOOK_URL = "https://be-edc.msvc.app/webhooks/midtrans";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qris);

        // ✅ Initialize SharedPreferences for duplicate prevention
        transactionPrefs = getSharedPreferences("qris_transactions", MODE_PRIVATE);

        // Initialize views
        progressBar = findViewById(R.id.progressBar);
        initiatePaymentButton = findViewById(R.id.initiatePaymentButton);
        statusTextView = findViewById(R.id.statusTextView);
        editTextAmount = findViewById(R.id.editTextAmount);
        referenceIdTextView = findViewById(R.id.referenceIdTextView);
        backNavigation = findViewById(R.id.back_navigation);
        descriptionText = findViewById(R.id.descriptionText);

        // Initialize numpad buttons
        btn1 = findViewById(R.id.btn1);
        btn2 = findViewById(R.id.btn2);
        btn3 = findViewById(R.id.btn3);
        btn4 = findViewById(R.id.btn4);
        btn5 = findViewById(R.id.btn5);
        btn6 = findViewById(R.id.btn6);
        btn7 = findViewById(R.id.btn7);
        btn8 = findViewById(R.id.btn8);
        btn9 = findViewById(R.id.btn9);
        btn0 = findViewById(R.id.btn0);
        btn000 = findViewById(R.id.btn000);
        btnDelete = findViewById(R.id.btnDelete);
        
        // ✅ Generate unique reference ID with duplicate prevention
        referenceId = generateUniqueReferenceId();
        referenceIdTextView.setText(referenceId);

        // Set up click listeners
        initiatePaymentButton.setOnClickListener(v -> createTransaction());
        backNavigation.setOnClickListener(v -> finish());
        
        // Set up numpad listeners
        setupNumpadListeners();
        
        // Initially disable the button
        initiatePaymentButton.setEnabled(false);
    }

    /**
     * ✅ FRONTEND DEDUPLICATION: Generate unique reference ID with local tracking
     */
    private String generateUniqueReferenceId() {
        Log.d("QrisActivity", "🔄 Generating unique reference ID...");
        
        String baseRef = "ref-" + generateRandomString(8);
        
        // Check if this reference was recently created
        String recentRefs = transactionPrefs.getString(PREF_RECENT_REFERENCES, "");
        long currentTime = System.currentTimeMillis();
        
        // Clean up old references (older than cooldown period)
        StringBuilder validRefs = new StringBuilder();
        if (!recentRefs.isEmpty()) {
            String[] refs = recentRefs.split(",");
            
            for (String refEntry : refs) {
                if (refEntry.contains(":")) {
                    String[] parts = refEntry.split(":");
                    if (parts.length == 2) {
                        try {
                            long timestamp = Long.parseLong(parts[1]);
                            if (currentTime - timestamp < REFERENCE_COOLDOWN_MS) {
                                // Reference is still in cooldown period
                                if (validRefs.length() > 0) validRefs.append(",");
                                validRefs.append(refEntry);
                            }
                        } catch (NumberFormatException e) {
                            // Skip invalid entries
                            Log.w("QrisActivity", "Invalid reference entry: " + refEntry);
                        }
                    }
                }
            }
        }
        
        // Check if baseRef already exists in recent references
        if (validRefs.length() > 0) {
            String[] validRefArray = validRefs.toString().split(",");
            for (String refEntry : validRefArray) {
                if (refEntry.startsWith(baseRef + ":")) {
                    // Reference already exists, generate a new one
                    Log.w("QrisActivity", "⚠️ Reference " + baseRef + " recently used, generating new one");
                    return generateUniqueReferenceId(); // Recursive call with new random string
                }
            }
        }
        
        // Add this reference to recent references
        if (validRefs.length() > 0) validRefs.append(",");
        validRefs.append(baseRef).append(":").append(currentTime);
        
        // Save updated references
        transactionPrefs.edit()
            .putString(PREF_RECENT_REFERENCES, validRefs.toString())
            .apply();
        
        Log.d("QrisActivity", "✅ Generated unique reference: " + baseRef);
        return baseRef;
    }

    /**
     * ✅ FRONTEND DEDUPLICATION: Check if transaction is currently being processed
     */
    private boolean isTransactionInProgress() {
        long lastTransactionTime = transactionPrefs.getLong(PREF_LAST_TRANSACTION_TIME, 0);
        long currentTime = System.currentTimeMillis();
        
        // If last transaction was less than cooldown period, consider it in progress
        boolean inProgress = (currentTime - lastTransactionTime) < TRANSACTION_COOLDOWN_MS;
        
        if (inProgress) {
            Log.w("QrisActivity", "⏸️ Transaction in progress, cooldown active");
        }
        
        return inProgress;
    }

    /**
     * ✅ FRONTEND DEDUPLICATION: Mark transaction processing status
     */
    private void markTransactionInProgress(boolean inProgress) {
        SharedPreferences.Editor editor = transactionPrefs.edit();
        
        if (inProgress) {
            editor.putLong(PREF_LAST_TRANSACTION_TIME, System.currentTimeMillis())
                  .putString(PREF_CURRENT_REFERENCE, referenceId);
            Log.d("QrisActivity", "🔒 Marked transaction in progress: " + referenceId);
        } else {
            editor.remove(PREF_CURRENT_REFERENCE);
            Log.d("QrisActivity", "🔓 Cleared transaction progress status");
        }
        
        editor.apply();
    }

    /**
     * ✅ FRONTEND DEDUPLICATION: Save successful transaction for future reference
     */
    private void saveSuccessfulTransaction() {
        try {
            JSONObject txData = new JSONObject();
            txData.put("reference_id", referenceId);
            txData.put("transaction_uuid", transactionUuid);
            txData.put("amount", amount);
            txData.put("created_at", System.currentTimeMillis());
            
            // Save to SharedPreferences
            transactionPrefs.edit()
                .putString(PREF_LAST_SUCCESSFUL_TX, txData.toString())
                .putLong("last_success_time", System.currentTimeMillis())
                .apply();
                
            Log.d("QrisActivity", "💾 Saved successful transaction: " + referenceId);
        } catch (Exception e) {
            Log.w("QrisActivity", "Failed to save transaction data: " + e.getMessage());
        }
    }

    /**
     * ✅ FRONTEND DEDUPLICATION: Create client info for better backend tracking
     */
    private JSONObject createClientInfo() {
        try {
            JSONObject clientInfo = new JSONObject();
            clientInfo.put("app_version", "1.0.0");
            clientInfo.put("platform", "android");
            clientInfo.put("timestamp", System.currentTimeMillis());
            clientInfo.put("session_id", generateRandomString(16));
            clientInfo.put("reference_generation_time", System.currentTimeMillis());
            return clientInfo;
        } catch (JSONException e) {
            Log.w("QrisActivity", "Failed to create client info: " + e.getMessage());
            return new JSONObject();
        }
    }
    
    private void setupNumpadListeners() {
        View.OnClickListener numberClickListener = v -> {
            TextView button = (TextView) v;
            String number = button.getText().toString();
            appendNumber(number);
        };

        btn1.setOnClickListener(numberClickListener);
        btn2.setOnClickListener(numberClickListener);
        btn3.setOnClickListener(numberClickListener);
        btn4.setOnClickListener(numberClickListener);
        btn5.setOnClickListener(numberClickListener);
        btn6.setOnClickListener(numberClickListener);
        btn7.setOnClickListener(numberClickListener);
        btn8.setOnClickListener(numberClickListener);
        btn9.setOnClickListener(numberClickListener);
        btn0.setOnClickListener(numberClickListener);
        btn000.setOnClickListener(numberClickListener);
        
        btnDelete.setOnClickListener(v -> deleteLastDigit());
    }
    
    private void appendNumber(String number) {
        currentAmount.append(number);
        updateAmountDisplay();
    }
    
    private void deleteLastDigit() {
        if (currentAmount.length() > 0) {
            currentAmount.deleteCharAt(currentAmount.length() - 1);
            updateAmountDisplay();
        }
    }
    
    private void updateAmountDisplay() {
        String amountStr = currentAmount.toString();
        
        if (amountStr.isEmpty()) {
            editTextAmount.setVisibility(View.GONE);
            descriptionText.setText("Pastikan kembali nominal pembayaran pelanggan Anda");
            initiatePaymentButton.setEnabled(false);
        } else {
            editTextAmount.setVisibility(View.VISIBLE);
            editTextAmount.setText(formatAmount(amountStr));
            descriptionText.setText("Tekan Konfirmasi untuk melanjutkan");
            
            // Enable button if amount is valid
            try {
                int amt = Integer.parseInt(amountStr);
                initiatePaymentButton.setEnabled(amt >= 1000);
            } catch (NumberFormatException e) {
                initiatePaymentButton.setEnabled(false);
            }
        }
    }
    
    private String formatAmount(String amount) {
        if (amount.isEmpty()) return "";
        
        try {
            long num = Long.parseLong(amount);
            return String.format("%,d", num);
        } catch (NumberFormatException e) {
            return amount;
        }
    }

    /**
     * ✅ ENHANCED: Modified createTransaction with comprehensive duplicate prevention
     */
    private void createTransaction() {
        if (currentAmount.length() == 0) {
            Toast.makeText(this, "Masukkan jumlah pembayaran", Toast.LENGTH_SHORT).show();
            return;
        }
        
        // ✅ FRONTEND CHECK: Prevent rapid duplicate submissions
        if (isTransactionInProgress()) {
            Toast.makeText(this, "Transaksi sedang diproses, harap tunggu...", Toast.LENGTH_SHORT).show();
            return;
        }
        
        Log.d("QrisActivity", "🚀 Starting transaction creation process");
        Log.d("QrisActivity", "   Reference ID: " + referenceId);
        Log.d("QrisActivity", "   Amount: " + currentAmount.toString());
        
        progressBar.setVisibility(View.VISIBLE);
        initiatePaymentButton.setEnabled(false);
        statusTextView.setVisibility(View.VISIBLE);
        statusTextView.setText("Creating transaction...");
        
        // Mark transaction as in progress
        markTransactionInProgress(true);
        
        new CreateTransactionTask().execute();
    }

    private String generateRandomString(int length) {
        String chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(chars.length());
            sb.append(chars.charAt(index));
        }
        return sb.toString();
    }

    private String getServerKey() {
        try {
            // MIDTRANS_AUTH = 'Basic base64string'
            String base64 = MIDTRANS_AUTH.replace("Basic ", "");
            byte[] decoded = android.util.Base64.decode(base64, android.util.Base64.DEFAULT);
            String decodedString = new String(decoded);
            // Format is usually 'SB-Mid-server-xxxx:'. Remove trailing colon if present.
            return decodedString.replace(":", "");
        } catch (Exception e) {
            Log.e("MidtransCharge", "Error decoding server key: " + e.getMessage());
            return "";
        }
    }

    private boolean isValidServerKey(String serverKey) {
        return serverKey != null && 
               serverKey.startsWith("SB-Mid-server-") && 
               serverKey.length() > 20;
    }

    private String generateSignature(String orderId, String statusCode, String grossAmount, String serverKey) {
        String input = orderId + statusCode + grossAmount + serverKey;
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-512");
            byte[] messageDigest = md.digest(input.getBytes());
            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (java.security.NoSuchAlgorithmException e) {
            Log.e("MidtransCharge", "Error generating signature: " + e.getMessage());
            return "";
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            finish();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
    private class CreateTransactionTask extends AsyncTask<Void, Void, Boolean> {
        private String errorMessage;
        
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                // Generate a UUID for the transaction
                transactionUuid = UUID.randomUUID().toString();
                
                // ✅ ENHANCED LOGGING: Better tracking for debugging
                Log.d("MidtransCharge", "=== TRANSACTION CREATION START ===");
                Log.d("MidtransCharge", "Reference ID: " + referenceId);
                Log.d("MidtransCharge", "Transaction UUID: " + transactionUuid);
                Log.d("MidtransCharge", "Timestamp: " + System.currentTimeMillis());
                
                // Create transaction JSON payload
                JSONObject payload = new JSONObject();
                payload.put("type", "PAYMENT");
                payload.put("channel_category", "RETAIL_OUTLET");
                payload.put("channel_code", "QRIS");
                payload.put("reference_id", referenceId);
                
                // ✅ FRONTEND ENHANCEMENT: Add client-side metadata for better tracking
                payload.put("client_info", createClientInfo());
                payload.put("is_initial_creation", true); // Mark as initial creation
                
                // Get amount from current input
                String amountText = currentAmount.toString();
                Log.d("MidtransCharge", "Raw amount text: " + amountText);
                
                try {
                    // Parse amount - expecting integer in lowest denomination (Indonesian Rupiah)
                    amount = Integer.parseInt(amountText);
                    
                    // Validate minimum amount
                    if (amount < 1000) {
                        errorMessage = "Minimum amount is IDR 1,000";
                        return false;
                    }
                    
                    // Validate maximum amount for testing
                    if (amount > 10000000) {
                        errorMessage = "Maximum amount is IDR 10,000,000";
                        return false;
                    }
                    
                    Log.d("MidtransCharge", "Parsed amount: " + amount);
                } catch (NumberFormatException e) {
                    Log.e("MidtransCharge", "Amount parsing error: " + e.getMessage());
                    errorMessage = "Invalid amount format. Please enter numbers only.";
                    return false;
                }
                
                payload.put("amount", amount);
                payload.put("cashflow", "MONEY_IN");
                payload.put("status", "INIT");
                payload.put("device_id", 1);
                payload.put("transaction_uuid", transactionUuid);
                payload.put("transaction_time_seconds", 0.0);
                payload.put("device_code", "PB4K252T00021");
                payload.put("merchant_name", "Marcel Panjaitan");
                payload.put("mid", "71000026521");
                payload.put("tid", "73001500");
                
                Log.d("MidtransCharge", "Backend transaction payload: " + payload.toString());
                
                // Make the API call
                URL url = new URI(BACKEND_BASE + "/transactions").toURL();
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Content-Type", "application/json");
                conn.setRequestProperty("Accept", "application/json");
                conn.setRequestProperty("User-Agent", "BDKIPOCApp/1.0");
                
                // ✅ FRONTEND ENHANCEMENT: Add client headers for better backend tracking
                conn.setRequestProperty("X-Client-Reference", referenceId);
                conn.setRequestProperty("X-Client-Timestamp", String.valueOf(System.currentTimeMillis()));
                conn.setRequestProperty("X-Client-Version", "1.0.0");
                
                conn.setDoOutput(true);
                
                try (OutputStream os = conn.getOutputStream()) {
                    byte[] input = payload.toString().getBytes("utf-8");
                    os.write(input, 0, input.length);
                }
                
                int responseCode = conn.getResponseCode();
                Log.d("MidtransCharge", "Backend response code: " + responseCode);
                
                if (responseCode == 200 || responseCode == 201) {
                    // Success - process response
                    BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
                    StringBuilder response = new StringBuilder();
                    String responseLine;
                    while ((responseLine = br.readLine()) != null) {
                        response.append(responseLine.trim());
                    }
                    
                    Log.d("MidtransCharge", "Backend success response: " + response.toString());
                    
                    // Parse the response to get transaction ID
                    JSONObject jsonResponse = new JSONObject(response.toString());
                    JSONObject data = jsonResponse.getJSONObject("data");
                    transactionId = String.valueOf(data.getInt("id"));
                    
                    Log.d("MidtransCharge", "✅ Created transaction ID: " + transactionId);
                    
                    // ✅ FRONTEND SUCCESS: Save successful transaction info
                    saveSuccessfulTransaction();
                    
                    // Now generate QRIS via Midtrans
                    return generateQris(amount);
                    
                } else if (responseCode == 409 || responseCode == 400) {
                    // ✅ ENHANCED DUPLICATE HANDLING: Handle gracefully
                    Log.w("MidtransCharge", "⚠️ Potential duplicate detected (HTTP " + responseCode + ")");
                    
                    // Try to read and parse error response
                    try {
                        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"));
                        StringBuilder errorResponse = new StringBuilder();
                        String responseLine;
                        while ((responseLine = br.readLine()) != null) {
                            errorResponse.append(responseLine.trim());
                        }
                        
                        String errorResponseStr = errorResponse.toString();
                        Log.d("MidtransCharge", "Error response: " + errorResponseStr);
                        
                        // Check if it's actually a duplicate reference error
                        if (errorResponseStr.toLowerCase().contains("duplicate") || 
                            errorResponseStr.toLowerCase().contains("already exists") ||
                            errorResponseStr.toLowerCase().contains("reference") ||
                            responseCode == 409) {
                            
                            Log.i("MidtransCharge", "✅ Confirmed duplicate reference - proceeding with QRIS generation");
                            
                            // For duplicates, we can still generate QRIS with existing reference
                            return generateQris(amount);
                        }
                    } catch (Exception e) {
                        Log.w("MidtransCharge", "Could not parse error response: " + e.getMessage());
                    }
                    
                    // If we can't determine the exact error, try QRIS generation anyway
                    Log.i("MidtransCharge", "🔄 Proceeding with QRIS generation despite backend error");
                    return generateQris(amount);
                    
                } else {
                    // Other HTTP errors
                    BufferedReader br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"));
                    StringBuilder response = new StringBuilder();
                    String responseLine;
                    while ((responseLine = br.readLine()) != null) {
                        response.append(responseLine.trim());
                    }
                    
                    String errorResponse = response.toString();
                    Log.e("MidtransCharge", "❌ Backend error (HTTP " + responseCode + "): " + errorResponse);
                    errorMessage = "Backend error (" + responseCode + "): " + errorResponse;
                    return false;
                }
            } catch (Exception e) {
                Log.e("MidtransCharge", "❌ Backend transaction exception: " + e.getMessage(), e);
                errorMessage = "Network error: " + e.getMessage();
                return false;
            }
        }
        
        private boolean generateQris(int amount) {
            try {
                // Validate server key first
                String serverKey = getServerKey();
                if (!isValidServerKey(serverKey)) {
                    Log.e("MidtransCharge", "Invalid server key format");
                    errorMessage = "Invalid server key configuration";
                    return false;
                }
                
                Log.d("MidtransCharge", "Using server key: " + serverKey.substring(0, Math.min(20, serverKey.length())) + "...");
                
                // Create QRIS charge JSON payload
                JSONObject payload = new JSONObject();
                payload.put("payment_type", "qris");
                
                JSONObject transactionDetails = new JSONObject();
                transactionDetails.put("order_id", transactionUuid);
                transactionDetails.put("gross_amount", amount);
                payload.put("transaction_details", transactionDetails);
                
                // Add customer details (recommended for better success rate)
                JSONObject customerDetails = new JSONObject();
                customerDetails.put("first_name", "Test");
                customerDetails.put("last_name", "Customer");
                customerDetails.put("email", "test@example.com");
                customerDetails.put("phone", "081234567890");
                payload.put("customer_details", customerDetails);
                
                // Add item details (optional but recommended)
                JSONArray itemDetails = new JSONArray();
                JSONObject item = new JSONObject();
                item.put("id", "item1");
                item.put("price", amount);
                item.put("quantity", 1);
                item.put("name", "QRIS Payment - " + referenceId);
                itemDetails.put(item);
                payload.put("item_details", itemDetails);
                
                // ✅ FRONTEND ENHANCEMENT: Add tracking info for reference linkage
                JSONObject customField1 = new JSONObject();
                customField1.put("app_reference_id", referenceId);
                customField1.put("creation_time", new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new java.util.Date()));
                customField1.put("client_version", "1.0.0");
                payload.put("custom_field1", customField1.toString());
                
                // Log the request details
                Log.d("MidtransCharge", "=== MIDTRANS QRIS REQUEST ===");
                Log.d("MidtransCharge", "URL: " + MIDTRANS_CHARGE_URL);
                Log.d("MidtransCharge", "Authorization: " + MIDTRANS_AUTH);
                Log.d("MidtransCharge", "X-Override-Notification: " + WEBHOOK_URL);
                Log.d("MidtransCharge", "Reference ID: " + referenceId);
                Log.d("MidtransCharge", "Order ID: " + transactionUuid);
                Log.d("MidtransCharge", "Amount: " + amount);
                Log.d("MidtransCharge", "================================");

                // Make the API call to Midtrans
                URL url = new URI(MIDTRANS_CHARGE_URL).toURL();
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Accept", "application/json");
                conn.setRequestProperty("Content-Type", "application/json");
                conn.setRequestProperty("Authorization", MIDTRANS_AUTH); 
                conn.setRequestProperty("X-Override-Notification", WEBHOOK_URL);
                conn.setRequestProperty("User-Agent", "BDKIPOCApp/1.0");
                conn.setDoOutput(true);
                conn.setConnectTimeout(30000); // 30 seconds
                conn.setReadTimeout(30000); // 30 seconds
                
                try (OutputStream os = conn.getOutputStream()) {
                    byte[] input = payload.toString().getBytes("utf-8");
                    os.write(input, 0, input.length);
                }
                
                int responseCode = conn.getResponseCode();
                Log.d("MidtransCharge", "Midtrans HTTP Response Code: " + responseCode);
                
                if (responseCode == 200 || responseCode == 201) {
                    InputStream inputStream = conn.getInputStream();
                    if (inputStream != null) {
                        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
                        StringBuilder response = new StringBuilder();
                        String responseLine;
                        while ((responseLine = br.readLine()) != null) {
                            response.append(responseLine.trim());
                        }
                        
                        Log.d("MidtransCharge", "Midtrans Success Response: " + response.toString());
                        
                        // Parse the response
                        midtransResponse = new JSONObject(response.toString());
                        
                        // Check if response contains error within success response
                        if (midtransResponse.has("status_code")) {
                            String statusCode = midtransResponse.getString("status_code");
                            if (!statusCode.equals("201")) {
                                String statusMessage = midtransResponse.optString("status_message", "Unknown error");
                                Log.e("MidtransCharge", "Midtrans Error in response: " + statusCode + " - " + statusMessage);
                                errorMessage = "Midtrans Error: " + statusMessage + " (Code: " + statusCode + ")";
                                return false;
                            }
                        }
                        
                        // Validate response has required fields
                        if (!midtransResponse.has("actions") || 
                            !midtransResponse.has("transaction_id") ||
                            !midtransResponse.has("gross_amount")) {
                            Log.e("MidtransCharge", "Missing required fields in Midtrans response");
                            errorMessage = "Invalid response from Midtrans - missing required fields";
                            return false;
                        }
                        
                        Log.d("MidtransCharge", "✅ QRIS generation successful!");
                        return true;
                    } else {
                        Log.e("MidtransCharge", "HTTP " + responseCode + ": No input stream available");
                        errorMessage = "Error generating QRIS: HTTP " + responseCode + ": No input stream available";
                        return false;
                    }
                } else {
                    InputStream errorStream = conn.getErrorStream();
                    if (errorStream != null) {
                        BufferedReader br = new BufferedReader(new InputStreamReader(errorStream, "utf-8"));
                        StringBuilder errorResponse = new StringBuilder();
                        String responseLine;
                        while ((responseLine = br.readLine()) != null) {
                            errorResponse.append(responseLine.trim());
                        }
                        
                        Log.e("MidtransCharge", "Midtrans HTTP " + responseCode + ": " + errorResponse.toString());
                        
                        // Try to parse error JSON for better error message
                        try {
                            JSONObject errorJson = new JSONObject(errorResponse.toString());
                            
                            // Handle different error response formats
                            String errorMessage = "";
                            if (errorJson.has("error_messages")) {
                                errorMessage = errorJson.optString("error_messages", "Unknown error");
                            } else if (errorJson.has("status_message")) {
                                errorMessage = errorJson.optString("status_message", "Unknown error");
                            } else if (errorJson.has("message")) {
                                errorMessage = errorJson.optString("message", "Unknown error");
                            } else {
                                errorMessage = errorResponse.toString();
                            }
                            
                            this.errorMessage = "Midtrans Error: " + errorMessage;
                        } catch (JSONException e) {
                            this.errorMessage = "HTTP " + responseCode + ": " + errorResponse.toString();
                        }
                    } else {
                        Log.e("MidtransCharge", "HTTP " + responseCode + ": No error stream available");
                        this.errorMessage = "Error generating QRIS: HTTP " + responseCode + ": No error stream available";
                    }
                    return false;
                }
            } catch (Exception e) {
                Log.e("MidtransCharge", "Midtrans QRIS generation exception: " + e.getMessage(), e);
                errorMessage = "Network error: " + e.getMessage();
                return false;
            }
        }
        
        @Override
        protected void onPostExecute(Boolean success) {
            // ✅ FRONTEND CLEANUP: Always clear in-progress status
            markTransactionInProgress(false);
            
            if (success && midtransResponse != null) {
                try {
                    // Extract needed values from midtransResponse
                    JSONArray actionsArray = midtransResponse.getJSONArray("actions");
                    if (actionsArray.length() == 0) {
                        Log.e("MidtransCharge", "No actions found in Midtrans response");
                        Toast.makeText(QrisActivity.this, "Error: No QR code URL found in response", Toast.LENGTH_LONG).show();
                        initiatePaymentButton.setEnabled(true);
                        progressBar.setVisibility(View.GONE);
                        statusTextView.setVisibility(View.GONE);
                        return;
                    }
                    
                    JSONObject actions = actionsArray.getJSONObject(0);
                    String qrImageUrl = actions.getString("url");
                    
                    // Extract transaction_id
                    String transactionId = midtransResponse.getString("transaction_id");
                    String transactionTime = midtransResponse.getString("transaction_time");
                    String acquirer = midtransResponse.getString("acquirer");
                    String merchantId = midtransResponse.getString("merchant_id");
                    
                    // Send raw amount as string without decimal conversion
                    String rawAmountString = String.valueOf(amount); // Keep original integer amount
                    
                    // Log everything before launching activity
                    Log.d("MidtransCharge", "=== LAUNCHING QRIS RESULT ACTIVITY ===");
                    Log.d("MidtransCharge", "✅ Transaction created successfully!");
                    Log.d("MidtransCharge", "qrImageUrl: " + qrImageUrl);
                    Log.d("MidtransCharge", "amount (raw): " + amount);
                    Log.d("MidtransCharge", "rawAmountString: " + rawAmountString);
                    Log.d("MidtransCharge", "referenceId: " + referenceId);
                    Log.d("MidtransCharge", "transactionUuid (orderId): " + transactionUuid);
                    Log.d("MidtransCharge", "transaction_id: " + transactionId);
                    Log.d("MidtransCharge", "transactionTime: " + transactionTime);
                    Log.d("MidtransCharge", "acquirer: " + acquirer);
                    Log.d("MidtransCharge", "merchantId: " + merchantId);
                    Log.d("MidtransCharge", "========================================");
                    
                    // ✅ FINAL SUCCESS: Update transaction status in preferences
                    transactionPrefs.edit()
                        .putString("last_qris_url", qrImageUrl)
                        .putString("last_qris_reference", referenceId)
                        .putLong("last_qris_time", System.currentTimeMillis())
                        .apply();
                    
                    // Launch QrisResultActivity
                    Intent intent = new Intent(QrisActivity.this, QrisResultActivity.class);
                    intent.putExtra("qrImageUrl", qrImageUrl);
                    intent.putExtra("amount", amount); // Keep as int
                    intent.putExtra("referenceId", referenceId);
                    intent.putExtra("orderId", transactionUuid); // Order ID
                    intent.putExtra("transactionId", transactionId); // Actual Midtrans transaction_id
                    intent.putExtra("grossAmount", rawAmountString); // Raw amount as string (no decimals)
                    intent.putExtra("transactionTime", transactionTime); // For timestamp
                    intent.putExtra("acquirer", acquirer);
                    intent.putExtra("merchantId", merchantId);
                    
                    try {
                        startActivity(intent);
                        finish(); // Close QrisActivity
                        
                        Log.d("MidtransCharge", "🎉 Successfully launched QrisResultActivity");
                        
                    } catch (Exception e) {
                        Log.e("MidtransCharge", "Failed to start QrisResultActivity: " + e.getMessage(), e);
                        Toast.makeText(QrisActivity.this, "Error launching QR display: " + e.getMessage(), Toast.LENGTH_LONG).show();
                        
                        // Re-enable button on error
                        initiatePaymentButton.setEnabled(true);
                        progressBar.setVisibility(View.GONE);
                        statusTextView.setVisibility(View.GONE);
                    }
                    return;
                    
                } catch (JSONException e) {
                    Log.e("MidtransCharge", "QRIS response JSON error: " + e.getMessage(), e);
                    Toast.makeText(QrisActivity.this, "Error processing QRIS response: " + e.getMessage(), Toast.LENGTH_LONG).show();
                }
            } else {
                // Handle error case
                String message = (errorMessage != null && !errorMessage.isEmpty()) ? 
                    errorMessage : "Unknown error occurred. Please check your connection and try again.";
                    
                Log.e("MidtransCharge", "❌ Transaction failed: " + message);
                Toast.makeText(QrisActivity.this, message, Toast.LENGTH_LONG).show();
                
                // Re-enable button for retry
                initiatePaymentButton.setEnabled(true);
            }
            
            // Always hide progress indicators
            progressBar.setVisibility(View.GONE);
            statusTextView.setVisibility(View.GONE);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // ✅ CLEANUP: Clear any in-progress status when activity is destroyed
        markTransactionInProgress(false);
        Log.d("QrisActivity", "🧹 QrisActivity destroyed, cleared progress status");
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Keep progress status when paused (user might come back)
        Log.d("QrisActivity", "⏸️ QrisActivity paused");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("QrisActivity", "▶️ QrisActivity resumed");
        
        // Check if there's a recent successful transaction
        String lastSuccessfulTx = transactionPrefs.getString(PREF_LAST_SUCCESSFUL_TX, "");
        if (!lastSuccessfulTx.isEmpty()) {
            try {
                JSONObject txData = new JSONObject(lastSuccessfulTx);
                String lastRef = txData.getString("reference_id");
                long lastTime = txData.getLong("created_at");
                
                // If last successful transaction was recent (within 5 minutes) and same reference
                if (System.currentTimeMillis() - lastTime < 300000 && lastRef.equals(referenceId)) {
                    Log.d("QrisActivity", "🔄 Recent successful transaction detected for same reference");
                }
            } catch (Exception e) {
                Log.w("QrisActivity", "Could not parse last successful transaction: " + e.getMessage());
            }
        }
    }

    @Override
    public void onBackPressed() {
        // ✅ CLEANUP: Clear progress status when user goes back
        markTransactionInProgress(false);
        super.onBackPressed();
    }
}