package com.example.bdkipoc.transaction.managers;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

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

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.UUID;

/**
 * PostTransactionBackendManager - Handles backend transaction posting
 * 
 * This manager handles the communication with the backend service for transaction posting
 * and provides the transaction_uuid needed for Midtrans integration.
 */
public class PostTransactionBackendManager {
    private static final String TAG = "PostTransactionBackend";
    
    // Backend Configuration
    private static final String BACKEND_BASE_URL = "https://be-edc.msvc.app";
    private static final String TRANSACTIONS_ENDPOINT = BACKEND_BASE_URL + "/transactions";
    
    // Default values
    private static final String DEFAULT_DEVICE_CODE = "PB4K252T00021";
    private static final int DEFAULT_DEVICE_ID = 1;
    private static final String DEFAULT_CASHFLOW = "MONEY_IN";
    private static final String DEFAULT_CHANNEL_CATEGORY = "RETAIL_OUTLET";
    
    // ✅ NEW: Static merchant data
    private static final String DEFAULT_MERCHANT_NAME = "BUDIAJAIB123";
    private static final String DEFAULT_MID = "542531513";
    private static final String DEFAULT_TID = "535151521";
    
    private Context context;
    private PostTransactionCallback callback;
    
    public interface PostTransactionCallback {
        void onPostTransactionSuccess(JSONObject response, String transactionUuid);
        void onPostTransactionError(String errorMessage);
        void onPostTransactionProgress(String message);
    }
    
    public PostTransactionBackendManager(Context context, PostTransactionCallback callback) {
        this.context = context;
        this.callback = callback;
    }
    
    /**
     * Post transaction to backend service
     */
    public void postTransaction(String paymentType, String referenceId, long amount, String status) {
        String channelCode = mapPaymentTypeToChannelCode(paymentType);
        String transactionUuid = generateUUID();
        
        Log.d(TAG, "=== POSTING TRANSACTION TO BACKEND ===");
        Log.d(TAG, "Payment Type: " + paymentType);
        Log.d(TAG, "Channel Code: " + channelCode);
        Log.d(TAG, "Reference ID: " + referenceId);
        Log.d(TAG, "Amount: " + amount);
        Log.d(TAG, "Status: " + status);
        Log.d(TAG, "Transaction UUID: " + transactionUuid);
        Log.d(TAG, "=====================================");
        
        if (callback != null) {
            callback.onPostTransactionProgress("Posting transaction to backend...");
        }
        
        new PostTransactionTask(paymentType, channelCode, referenceId, amount, status, transactionUuid).execute();
    }
    
    /**
     * Post transaction with INIT status (for pre-authorization)
     */
    public void postInitTransaction(String paymentType, String referenceId, long amount) {
        postTransaction(paymentType, referenceId, amount, "INIT");
    }
    
    /**
     * Post transaction with SUCCESS status (for completed transactions)
     */
    public void postSuccessTransaction(String paymentType, String referenceId, long amount) {
        postTransaction(paymentType, referenceId, amount, "SUCCESS");
    }
    
    /**
     * Update existing transaction status
     */
    public void updateTransactionStatus(String transactionUuid, String newStatus) {
        Log.d(TAG, "Updating transaction " + transactionUuid + " to status: " + newStatus);
        // TODO: Implement update endpoint if available
        // For now, we'll create a new transaction with updated status
    }
    
    /**
     * Map payment type to channel code for backend
     */
    private String mapPaymentTypeToChannelCode(String paymentType) {
        if (paymentType == null) {
            return "CREDIT_CARD"; // Default
        }
        
        switch (paymentType.toLowerCase()) {
            case "credit_card":
                return "CREDIT_CARD";
            case "debit_card":
                return "DEBIT_CARD";
            case "e_money":
                return "E_MONEY";
            case "qris":
                return "QRIS";
            default:
                Log.w(TAG, "Unknown payment type: " + paymentType + ", using CREDIT_CARD");
                return "CREDIT_CARD";
        }
    }
    
    /**
     * Generate UUID v4 for transaction
     */
    private String generateUUID() {
        return UUID.randomUUID().toString();
    }
    
    /**
     * Get device serial number (Sunmi device code)
     */
    private String getDeviceCode() {
        try {
            // Try to get actual device serial number
            // For Sunmi devices, this might be available through system properties
            String serialNumber = android.os.Build.SERIAL;
            if (serialNumber != null && !serialNumber.equals("unknown") && !serialNumber.equals(android.os.Build.UNKNOWN)) {
                return serialNumber;
            }
        } catch (Exception e) {
            Log.w(TAG, "Could not get device serial number: " + e.getMessage());
        }
        
        // Fallback to default device code
        return DEFAULT_DEVICE_CODE;
    }
    
    /**
     * AsyncTask for posting transaction to backend
     */
    private class PostTransactionTask extends AsyncTask<Void, Void, Boolean> {
        private String paymentType;
        private String channelCode;
        private String referenceId;
        private long amount;
        private String status;
        private String transactionUuid;
        private String errorMessage;
        private JSONObject responseData;
        
        public PostTransactionTask(String paymentType, String channelCode, String referenceId, 
                                 long amount, String status, String transactionUuid) {
            this.paymentType = paymentType;
            this.channelCode = channelCode;
            this.referenceId = referenceId;
            this.amount = amount;
            this.status = status;
            this.transactionUuid = transactionUuid;
        }
        
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                // Build transaction payload
                JSONObject payload = buildTransactionPayload();
                
                Log.d(TAG, "Backend payload: " + payload.toString());
                
                // Make HTTP request
                return makeBackendRequest(payload);
                
            } catch (Exception e) {
                Log.e(TAG, "Backend transaction exception: " + e.getMessage(), e);
                errorMessage = "Backend transaction error: " + e.getMessage();
                return false;
            }
        }
        
        @Override
        protected void onPostExecute(Boolean success) {
            if (success && responseData != null && callback != null) {
                try {
                    // Extract transaction_uuid from response
                    JSONObject data = responseData.optJSONObject("data");
                    String returnedUuid = null;
                    
                    if (data != null) {
                        returnedUuid = data.optString("transaction_uuid", transactionUuid);
                    }
                    
                    Log.d(TAG, "✅ Backend transaction successful!");
                    Log.d(TAG, "Original UUID: " + transactionUuid);
                    Log.d(TAG, "Returned UUID: " + returnedUuid);
                    
                    callback.onPostTransactionSuccess(responseData, returnedUuid != null ? returnedUuid : transactionUuid);
                    
                } catch (Exception e) {
                    Log.e(TAG, "Error processing backend response: " + e.getMessage());
                    if (callback != null) {
                        callback.onPostTransactionError("Error processing backend response: " + e.getMessage());
                    }
                }
            } else if (callback != null) {
                callback.onPostTransactionError(errorMessage != null ? errorMessage : "Unknown backend error");
            }
        }
        
        private JSONObject buildTransactionPayload() throws JSONException {
            JSONObject payload = new JSONObject();
            
            // Required fields
            payload.put("type", "PAYMENT");
            payload.put("channel_category", DEFAULT_CHANNEL_CATEGORY);
            payload.put("channel_code", channelCode);
            payload.put("reference_id", referenceId);
            payload.put("amount", amount);
            payload.put("cashflow", DEFAULT_CASHFLOW);
            payload.put("status", status);
            payload.put("device_id", DEFAULT_DEVICE_ID);
            payload.put("transaction_uuid", transactionUuid);
            payload.put("transaction_time_seconds", 2.2); // Default value as mentioned
            payload.put("device_code", getDeviceCode());
            
            // ✅ NEW: Static merchant data (no longer null)
            payload.put("merchant_name", DEFAULT_MERCHANT_NAME);
            payload.put("mid", DEFAULT_MID);
            payload.put("tid", DEFAULT_TID);
            
            return payload;
        }
        
        private Boolean makeBackendRequest(JSONObject payload) {
            try {
                URL url = new URI(TRANSACTIONS_ENDPOINT).toURL();
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                
                // Set request properties
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Accept", "*/*");
                conn.setRequestProperty("Content-Type", "application/json");
                conn.setDoOutput(true);
                conn.setConnectTimeout(30000);
                conn.setReadTimeout(30000);
                
                // Send payload
                try (OutputStream os = conn.getOutputStream()) {
                    byte[] input = payload.toString().getBytes("utf-8");
                    os.write(input, 0, input.length);
                }
                
                // Get response
                int responseCode = conn.getResponseCode();
                Log.d(TAG, "Backend response code: " + responseCode);
                
                BufferedReader br;
                StringBuilder response = new StringBuilder();
                String responseLine;
                
                if (responseCode >= 200 && responseCode < 300) {
                    br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
                } else {
                    br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"));
                }
                
                while ((responseLine = br.readLine()) != null) {
                    response.append(responseLine.trim());
                }
                
                String responseString = response.toString();
                Log.d(TAG, "Backend response: " + responseString);
                
                // Parse response
                try {
                    responseData = new JSONObject(responseString);
                    
                    // Check if response indicates success
                    int status = responseData.optInt("status", 0);
                    String message = responseData.optString("message", "");
                    
                    if (status == 200 && "Successfully".equals(message)) {
                        return true;
                    } else {
                        errorMessage = "Backend error: " + message + " (Status: " + status + ")";
                        return false;
                    }
                    
                } catch (JSONException e) {
                    Log.e(TAG, "Error parsing backend response: " + e.getMessage());
                    errorMessage = "Invalid backend response format";
                    return false;
                }
                
            } catch (Exception e) {
                Log.e(TAG, "Backend request exception: " + e.getMessage(), e);
                errorMessage = "Network error: " + e.getMessage();
                return false;
            }
        }
    }
    
    /**
     * Utility method to generate reference ID
     */
    public static String generateReferenceId() {
        return "ref" + System.currentTimeMillis() + (int)(Math.random() * 10000);
    }
    
    /**
     * Utility method to map card menu ID to payment type
     */
    public static String mapCardMenuToPaymentType(int cardMenuId) {
        // Based on MainActivity.java card IDs
        switch (cardMenuId) {
            case 2131296346: // R.id.card_kartu_kredit
                return "credit_card";
            case 2131296344: // R.id.card_kartu_debit  
                return "debit_card";
            case 2131296360: // R.id.card_uang_elektronik
                return "e_money";
            case 2131296352: // R.id.card_qris
                return "qris";
            default:
                Log.w(TAG, "Unknown card menu ID: " + cardMenuId + ", defaulting to credit_card");
                return "credit_card";
        }
    }
    
    /**
     * Debug method to log transaction details
     */
    public void debugTransactionData(String paymentType, String referenceId, long amount, String status) {
        Log.d(TAG, "=== TRANSACTION DEBUG INFO ===");
        Log.d(TAG, "Payment Type: " + paymentType);
        Log.d(TAG, "Channel Code: " + mapPaymentTypeToChannelCode(paymentType));
        Log.d(TAG, "Reference ID: " + referenceId);
        Log.d(TAG, "Amount: " + amount);
        Log.d(TAG, "Status: " + status);
        Log.d(TAG, "Device Code: " + getDeviceCode());
        Log.d(TAG, "Device ID: " + DEFAULT_DEVICE_ID);
        Log.d(TAG, "Merchant Name: " + DEFAULT_MERCHANT_NAME);
        Log.d(TAG, "MID: " + DEFAULT_MID);
        Log.d(TAG, "TID: " + DEFAULT_TID);
        Log.d(TAG, "==============================");
    }
}