

/*
 * *
 *  * Created by admin on 29/03/22, 4:08 PM
 *  * Copyright (c) 2022 . All rights reserved.
 *  * Last modified 29/03/22, 4:05 PM
 *
 */

package com.cscodetech.movers.ui;

import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.widget.Toast;

import com.cscodetech.movers.databinding.ActivityPaystackBinding;
import com.cscodetech.movers.model.PaymentdataItem;
import com.cscodetech.movers.model.UserLogin;
import com.cscodetech.movers.retrofit.APIClient;
import com.cscodetech.movers.utils.CustPrograssbar;
import com.cscodetech.movers.utils.Utility;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;

public class PaystackActivity extends BaseActivity {

    private ActivityPaystackBinding binding;
    private static final int CARD_NUMBER_TOTAL_SYMBOLS = 19; // size of pattern 0000-0000-0000-0000
    private static final int CARD_NUMBER_TOTAL_DIGITS = 16; // max numbers of digits in pattern: 0000 x 4
    private static final int CARD_NUMBER_DIVIDER_MODULO = 5; // means divider position is every 5th symbol beginning with 1
    private static final int CARD_NUMBER_DIVIDER_POSITION = CARD_NUMBER_DIVIDER_MODULO - 1; // means divider position is every 4th symbol beginning with 0
    private static final char CARD_NUMBER_DIVIDER = '-';

    private static final int CARD_DATE_TOTAL_SYMBOLS = 5; // size of pattern MM/YY
    private static final int CARD_DATE_TOTAL_DIGITS = 4; // max numbers of digits in pattern: MM + YY
    private static final int CARD_DATE_DIVIDER_MODULO = 3; // means divider position is every 3rd symbol beginning with 1
    private static final int CARD_DATE_DIVIDER_POSITION = CARD_DATE_DIVIDER_MODULO - 1; // means divider position is every 2nd symbol beginning with 0
    private static final char CARD_DATE_DIVIDER = '/';

    private static final int CARD_CVC_TOTAL_SYMBOLS = 3;

    int amount = 0;
    UserLogin user;
    PaymentdataItem paymentItem;
    CustPrograssbar custPrograssbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityPaystackBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        custPrograssbar = new CustPrograssbar();

        user = sessionmanager.getUserDetails();
        amount = getIntent().getIntExtra("amount", 0);
        paymentItem = (PaymentdataItem) getIntent().getSerializableExtra("detail");
        List<String> elephantList = Arrays.asList(paymentItem.getAttributes().split(","));
        Log.e("key", "--> " + elephantList.get(0));
        co.paystack.android.PaystackSdk.initialize(getApplicationContext());
        co.paystack.android.PaystackSdk.setPublicKey(elephantList.get(0));
        amount = amount * 100;
        binding.imgBack.setOnClickListener(view -> finish());
        binding.txtSubmit.setOnClickListener(v -> onClick());
        binding.cardNumberEditText.addTextChangedListener(new android.text.TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {}
            @Override
            public void afterTextChanged(android.text.Editable s) {
                if (!isInputCorrect(s, CARD_NUMBER_TOTAL_SYMBOLS, CARD_NUMBER_DIVIDER_MODULO, CARD_NUMBER_DIVIDER)) {
                    s.replace(0, s.length(), concatString(getDigitArray(s, CARD_NUMBER_TOTAL_DIGITS), CARD_NUMBER_DIVIDER_POSITION, CARD_NUMBER_DIVIDER));
                }
            }
        });
        binding.cardDateEditText.addTextChangedListener(new android.text.TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {}
            @Override
            public void afterTextChanged(android.text.Editable s) {
                if (!isInputCorrect(s, CARD_DATE_TOTAL_SYMBOLS, CARD_DATE_DIVIDER_MODULO, CARD_DATE_DIVIDER)) {
                    s.replace(0, s.length(), concatString(getDigitArray(s, CARD_DATE_TOTAL_DIGITS), CARD_DATE_DIVIDER_POSITION, CARD_DATE_DIVIDER));
                }
            }
        });
        binding.cardCVCEditText.addTextChangedListener(new android.text.TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {}
            @Override
            public void afterTextChanged(android.text.Editable s) {
                if (s.length() > CARD_CVC_TOTAL_SYMBOLS) {
                    s.delete(CARD_CVC_TOTAL_SYMBOLS, s.length());
                }
            }
        });
    }

    public void performCharge(co.paystack.android.model.Card card) {
        custPrograssbar.prograssCreate(PaystackActivity.this);
        //create a Charge object
        co.paystack.android.model.Charge charge = new co.paystack.android.model.Charge();
        charge.setCard(card); //sets the card to charge
        charge.setEmail(user.getEmail());
        charge.setAmount(amount);
        co.paystack.android.PaystackSdk.chargeCard(PaystackActivity.this, charge, new co.paystack.android.Paystack.TransactionCallback() {
            @Override
            public void onSuccess(co.paystack.android.Transaction transaction) {
                // This is called only after transaction is deemed successful.
                // Retrieve the transaction, and send its reference to your server
                // for verification.
                Log.e("Paystack response", "" + transaction.getReference());
                new VerifyOnServer().execute(transaction.getReference());

            }

            @Override
            public void beforeValidate(co.paystack.android.Transaction transaction) {
                // This is called only before requesting OTP.
                // Save reference so you may send to server. If
                // error occurs with OTP, you should still verify on server.
                Log.e("Paystack Opt", "" + transaction.toString());
                custPrograssbar.closePrograssBar();
            }
            @Override
            public void onError(Throwable error, co.paystack.android.Transaction transaction) {
                //handle error here
                custPrograssbar.closePrograssBar();

                Log.e("Paystack Error", "" + transaction.toString());
                Toast.makeText(PaystackActivity.this, error.toString(), Toast.LENGTH_LONG).show();
                Log.e("Paystack Error1", "" + error.toString());
            }
        });
    }

    public void onClick() {

        if (binding.cardDateEditText.getText().toString().length() == 5) {
            int mounth = Integer.parseInt(binding.cardDateEditText.getText().toString().substring(0, 2));
            int year = Integer.parseInt(binding.cardDateEditText.getText().toString().substring(3, 5));
            co.paystack.android.model.Card card = new co.paystack.android.model.Card(binding.cardNumberEditText.getText().toString(), mounth, year, binding.cardCVCEditText.getText().toString());
            if (card.isValid()) {
                // charge card
                performCharge(card);
            } else {
                Toast.makeText(PaystackActivity.this, "Please check your card details and try again", Toast.LENGTH_LONG).show();
                //do something
            }
        } else {
            Toast.makeText(PaystackActivity.this, "Please check your card details and try again", Toast.LENGTH_LONG).show();

        }

    }


    private class VerifyOnServer extends AsyncTask<String, Void, String> {
        private String reference;
        private String error;

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            custPrograssbar.closePrograssBar();
            if (result != null) {
                Log.e("result", "-->" + result);
                if (result.equalsIgnoreCase("Transaction was successful")) {

                    Utility.getInstance().tragectionID = reference;
                    Utility.getInstance().paymentsucsses = 1;
                    finish();
                } else {
                    Toast.makeText(PaystackActivity.this, "" + result, Toast.LENGTH_LONG).show();
                }
            } else {
                Toast.makeText(PaystackActivity.this, String.format("There was a problem verifying %s on the backend: %s ", this.reference, error), Toast.LENGTH_LONG).show();
            }
        }

        @Override
        protected String doInBackground(String... reference) {
            try {
                this.reference = reference[0];
                String json = String.format("{\"reference\":\"%s\"}", this.reference);
                String url1 = APIClient.BASE_URL + "/eapi/e_verify.php?details=" + URLEncoder.encode(json, "UTF-8");

                URL url = new URL(url1);
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

                try (InputStream in = new BufferedInputStream(urlConnection.getInputStream());
                     InputStreamReader read = new InputStreamReader(in);
                     BufferedReader buff = new BufferedReader(read)) {

                    StringBuilder dta = new StringBuilder();
                    String chunks;
                    while ((chunks = buff.readLine()) != null) {
                        dta.append(chunks);
                    }

                    return dta.toString();
                } finally {
                    urlConnection.disconnect();
                }
            } catch (IOException e) {
                custPrograssbar.closePrograssBar();
                e.printStackTrace();
            }
            return null;
        }
    }


    private boolean isInputCorrect(Editable s, int size, int dividerPosition, char divider) {
        boolean isCorrect = s.length() <= size;
        for (int i = 0; i < s.length(); i++) {
            if (i > 0 && (i + 1) % dividerPosition == 0) {
                isCorrect &= divider == s.charAt(i);
            } else {
                isCorrect &= Character.isDigit(s.charAt(i));
            }
        }
        return isCorrect;
    }

    private String concatString(char[] digits, int dividerPosition, char divider) {
        final StringBuilder formatted = new StringBuilder();

        for (int i = 0; i < digits.length; i++) {
            if (digits[i] != 0) {
                formatted.append(digits[i]);
                if ((i > 0) && (i < (digits.length - 1)) && (((i + 1) % dividerPosition) == 0)) {
                    formatted.append(divider);
                }
            }
        }

        return formatted.toString();
    }

    private char[] getDigitArray(final Editable s, final int size) {
        char[] digits = new char[size];
        int index = 0;
        for (int i = 0; i < s.length() && index < size; i++) {
            char current = s.charAt(i);
            if (Character.isDigit(current)) {
                digits[index] = current;
                index++;
            }
        }
        return digits;
    }
}
