package com.example.bdkipoc.transaction.managers;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;

import com.example.bdkipoc.MyApplication;
import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.sunmi.pay.hardware.aidlv2.bean.EMVCandidateV2;
import com.sunmi.pay.hardware.aidlv2.emv.EMVListenerV2;
import com.sunmi.pay.hardware.aidlv2.emv.EMVOptV2;

import java.util.List;

/**
 * EMVManager - Handles all EMV related operations
 */
public class EMVManager {
    private static final String TAG = "EMVManager";
    
    private EMVOptV2 mEMVOptV2;
    private EMVManagerCallback callback;
    
    // EMV Process Variables
    private int mCardType;
    private String mCardNo;
    private int mPinType;
    private String mCertInfo;
    private int mProcessStep;
    
    public interface EMVManagerCallback {
        void onAppSelect(String[] candidateNames);
        void onFinalAppSelect();
        void onConfirmCardNo(String cardNo);
        void onCertVerify(String certInfo);
        void onShowPinPad(int pinType);
        void onOnlineProcess();
        void onSignature();
        void onTransactionSuccess(int code, String desc);
        void onTransactionFailed(int code, String desc);
    }
    
    public EMVManager(EMVManagerCallback callback) {
        this.callback = callback;
        initEMVComponents();
    }
    
    private void initEMVComponents() {
        if (MyApplication.app != null) {
            mEMVOptV2 = MyApplication.app.emvOptV2;
            Log.d(TAG, "EMV components initialized");
        } else {
            Log.e(TAG, "MyApplication.app is null");
        }
    }
    
    public void initEMVData() {
        try {
            if (mEMVOptV2 != null) {
                mEMVOptV2.initEmvProcess();
                
                new Handler(Looper.getMainLooper()).postDelayed(() -> {
                    try {
                        initEmvTlvData();
                        Log.d(TAG, "EMV data initialized successfully");
                    } catch (Exception e) {
                        Log.e(TAG, "Error in delayed EMV init: " + e.getMessage());
                    }
                }, 500);
            }
        } catch (Exception e) {
            Log.e(TAG, "Error initializing EMV data: " + e.getMessage());
        }
    }
    
    private void initEmvTlvData() {
        try {
            // Set PayPass (MasterCard) TLV data
            String[] tagsPayPass = {"DF8117", "DF8118", "DF8119", "DF811F", "DF811E", "DF812C",
                    "DF8123", "DF8124", "DF8125", "DF8126", "DF811B", "DF811D", "DF8122", "DF8120", "DF8121"};
            String[] valuesPayPass = {"E0", "F8", "F8", "E8", "00", "00",
                    "000000000000", "000000100000", "999999999999", "000000100000",
                    "30", "02", "0000000000", "000000000000", "000000000000"};
            mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYPASS, tagsPayPass, valuesPayPass);

            // Set AMEX TLV data
            String[] tagsAE = {"9F6D", "9F6E", "9F33", "9F35", "DF8168", "DF8167", "DF8169", "DF8170"};
            String[] valuesAE = {"C0", "D8E00000", "E0E888", "22", "00", "00", "00", "60"};
            mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_AE, tagsAE, valuesAE);

            // Set JCB TLV data
            String[] tagsJCB = {"9F53", "DF8161"};
            String[] valuesJCB = {"708000", "7F00"};
            mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_JCB, tagsJCB, valuesJCB);

            // Set DPAS TLV data
            String[] tagsDPAS = {"9F66"};
            String[] valuesDPAS = {"B600C000"};
            mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_DPAS, tagsDPAS, valuesDPAS);

            // Set Flash TLV data
            String[] tagsFLASH = {"9F58", "9F59", "9F5A", "9F5D", "9F5E"};
            String[] valuesFLASH = {"03", "D88700", "00", "000000000000", "E000"};
            mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_FLASH, tagsFLASH, valuesFLASH);

            // Set Pure TLV data
            String[] tagsPURE = {"DF7F", "DF8134", "DF8133"};
            String[] valuesPURE = {"A0000007271010", "DF", "36006043F9"};
            mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PURE, tagsPURE, valuesPURE);

            Bundle bundle = new Bundle();
            bundle.putBoolean("optOnlineRes", true);
            mEMVOptV2.setTermParamEx(bundle);
            
        } catch (RemoteException e) {
            Log.e(TAG, "Error setting EMV TLV data: " + e.getMessage());
        }
    }
    
    public void startEMVTransaction(String transactionAmount, int cardType) {
        if (mProcessStep != 0) {
            Log.d(TAG, "EMV transaction already in progress (step: " + mProcessStep + ") - ignoring call");
            return;
        }
        
        Log.d(TAG, "Starting EMV transaction process");
        mProcessStep = 1;
        mCardType = cardType;
        
        try {
            mEMVOptV2.initEmvProcess();
            
            new Handler(Looper.getMainLooper()).postDelayed(() -> {
                try {
                    if (mProcessStep <= 0) {
                        Log.d(TAG, "EMV process was cancelled - not starting");
                        return;
                    }
                    
                    Bundle bundle = new Bundle();
                    bundle.putString("amount", transactionAmount);
                    bundle.putString("transType", "00");
                    bundle.putInt("flowType", AidlConstantsV2.EMV.FlowType.TYPE_EMV_STANDARD);
                    bundle.putInt("cardType", mCardType);
                    
                    Log.d(TAG, "Starting transactProcessEx with reset EMV");
                    mEMVOptV2.transactProcessEx(bundle, mEMVListener);
                    
                } catch (Exception e) {
                    Log.e(TAG, "Error in delayed EMV start: " + e.getMessage(), e);
                    if (callback != null) {
                        callback.onTransactionFailed(-1, "Error starting EMV: " + e.getMessage());
                    }
                }
            }, 300);
            
        } catch (Exception e) {
            Log.e(TAG, "Error starting EMV transaction: " + e.getMessage());
            if (callback != null) {
                callback.onTransactionFailed(-1, "Error starting EMV transaction: " + e.getMessage());
            }
        }
    }
    
    public void resetEMVProcess() {
        try {
            if (mEMVOptV2 != null) {
                mEMVOptV2.initEmvProcess();
            }
            mProcessStep = 0;
            mCardNo = null;
            Log.d(TAG, "EMV process reset");
        } catch (Exception e) {
            Log.e(TAG, "Error resetting EMV process: " + e.getMessage());
        }
    }
    
    // EMV Import Methods
    public void importAppSelect(int selectIndex) {
        try {
            mEMVOptV2.importAppSelect(selectIndex);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void importFinalAppSelectStatus(int status) {
        try {
            mEMVOptV2.importAppFinalSelectStatus(status);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    public void importCardNoStatus(int status) {
        try {
            mEMVOptV2.importCardNoStatus(status);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void importCertStatus(int status) {
        try {
            mEMVOptV2.importCertStatus(status);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void importPinInputStatus(int inputResult) {
        try {
            mEMVOptV2.importPinInputStatus(mPinType, inputResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void importSignatureStatus(int status) {
        try {
            mEMVOptV2.importSignatureStatus(status);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void mockOnlineProcess() {
        new Thread(() -> {
            try {
                Thread.sleep(2000);
                
                try {
                    String[] tags = {"71", "72", "91", "8A", "89"};
                    String[] values = {"", "", "", "", ""};
                    byte[] out = new byte[1024];
                    int len = mEMVOptV2.importOnlineProcStatus(0, tags, values, out);
                    if (len < 0) {
                        Log.e(TAG, "importOnlineProcessStatus error,code:" + len);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }
    
    // Getters
    public String getCardNo() {
        return mCardNo;
    }
    
    public int getCardType() {
        return mCardType;
    }
    
    public int getPinType() {
        return mPinType;
    }
    
    // Helper Methods
    public String maskCardNumber(String cardNo) {
        if (cardNo == null || cardNo.length() < 8) {
            return cardNo;
        }
        String first4 = cardNo.substring(0, 4);
        String last4 = cardNo.substring(cardNo.length() - 4);
        StringBuilder middle = new StringBuilder();
        for (int i = 0; i < cardNo.length() - 8; i++) {
            middle.append("*");
        }
        return first4 + middle.toString() + last4;
    }
    
    public String[] getCandidateNames(List<EMVCandidateV2> candiList) {
        if (candiList == null || candiList.size() == 0) return new String[0];
        String[] result = new String[candiList.size()];
        for (int i = 0; i < candiList.size(); i++) {
            EMVCandidateV2 candi = candiList.get(i);
            String name = candi.appPreName;
            name = TextUtils.isEmpty(name) ? candi.appLabel : name;
            name = TextUtils.isEmpty(name) ? candi.appName : name;
            name = TextUtils.isEmpty(name) ? "" : name;
            result[i] = name;
        }
        return result;
    }
    
    // EMV Listener
    private final EMVListenerV2 mEMVListener = new EMVListenerV2.Stub() {
        
        @Override
        public void onWaitAppSelect(List<EMVCandidateV2> appNameList, boolean isFirstSelect) throws RemoteException {
            Log.d(TAG, "onWaitAppSelect isFirstSelect:" + isFirstSelect);
            mProcessStep = 1; // EMV_APP_SELECT
            String[] candidateNames = getCandidateNames(appNameList);
            if (callback != null) {
                callback.onAppSelect(candidateNames);
            }
        }

        @Override
        public void onAppFinalSelect(String tag9F06Value) throws RemoteException {
            Log.d(TAG, "onAppFinalSelect tag9F06Value:" + tag9F06Value);
            mProcessStep = 2; // EMV_FINAL_APP_SELECT
            if (callback != null) {
                callback.onFinalAppSelect();
            }
        }

        @Override
        public void onConfirmCardNo(String cardNo) throws RemoteException {
            Log.d(TAG, "onConfirmCardNo cardNo:" + maskCardNumber(cardNo));
            mCardNo = cardNo;
            mProcessStep = 3; // EMV_CONFIRM_CARD_NO
            if (callback != null) {
                callback.onConfirmCardNo(cardNo);
            }
        }

        @Override
        public void onRequestShowPinPad(int pinType, int remainTime) throws RemoteException {
            Log.d(TAG, "onRequestShowPinPad pinType:" + pinType + " remainTime:" + remainTime);
            mPinType = pinType;
            mProcessStep = 5; // EMV_SHOW_PIN_PAD
            if (callback != null) {
                callback.onShowPinPad(pinType);
            }
        }

        @Override
        public void onRequestSignature() throws RemoteException {
            Log.d(TAG, "onRequestSignature");
            mProcessStep = 7; // EMV_SIGNATURE
            if (callback != null) {
                callback.onSignature();
            }
        }

        @Override
        public void onCertVerify(int certType, String certInfo) throws RemoteException {
            Log.d(TAG, "onCertVerify certType:" + certType + " certInfo:" + certInfo);
            mCertInfo = certInfo;
            mProcessStep = 4; // EMV_CERT_VERIFY
            if (callback != null) {
                callback.onCertVerify(certInfo);
            }
        }

        @Override
        public void onOnlineProc() throws RemoteException {
            Log.d(TAG, "onOnlineProcess");
            mProcessStep = 6; // EMV_ONLINE_PROCESS
            if (callback != null) {
                callback.onOnlineProcess();
            }
        }

        @Override
        public void onCardDataExchangeComplete() throws RemoteException {
            Log.d(TAG, "onCardDataExchangeComplete");
            if (mCardType == AidlConstantsV2.CardType.NFC.getValue()) {
                MyApplication.app.basicOptV2.buzzerOnDevice(1, 2750, 200, 0);
            }
        }

        @Override
        public void onTransResult(int code, String desc) throws RemoteException {
            Log.d(TAG, "onTransResult code:" + code + " desc:" + desc);
            
            if (code == 1 || code == 2 || code == 5 || code == 6) {
                if (callback != null) {
                    callback.onTransactionSuccess(code, desc);
                }
            } else {
                if (callback != null) {
                    callback.onTransactionFailed(code, desc);
                }
            }
        }

        @Override
        public void onConfirmationCodeVerified() throws RemoteException {
            Log.d(TAG, "onConfirmationCodeVerified");
        }

        @Override
        public void onRequestDataExchange(String cardNo) throws RemoteException {
            Log.d(TAG, "onRequestDataExchange,cardNo:" + cardNo);
            mEMVOptV2.importDataExchangeStatus(0);
        }

        @Override
        public void onTermRiskManagement() throws RemoteException {
            Log.d(TAG, "onTermRiskManagement");
            mEMVOptV2.importTermRiskManagementStatus(0);
        }

        @Override
        public void onPreFirstGenAC() throws RemoteException {
            Log.d(TAG, "onPreFirstGenAC");
            mEMVOptV2.importPreFirstGenACStatus(0);
        }

        @Override
        public void onDataStorageProc(String[] containerID, String[] containerContent) throws RemoteException {
            Log.d(TAG, "onDataStorageProc");
            String[] tags = new String[0];
            String[] values = new String[0];
            mEMVOptV2.importDataStorage(tags, values);
        }
    };
}