package com.app.simplitend.cg_subscription;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.apputils.CaregiverDataCache;
import com.app.simplitend.caregiverdashboard.activities.CgProfileProgressActivity;
import com.app.simplitend.cg_subscription.mvp.CurrentPlan;
import com.app.simplitend.cg_subscription.mvp.SubscriptionContracts;
import com.app.simplitend.cg_subscription.mvp.SubscriptionCredentials;
import com.app.simplitend.cg_subscription.mvp.SubscriptionPresenter;
import com.app.simplitend.databinding.CgSubscriptionLayoutBinding;
import com.app.simplitend.welcome.welcomecg.mvvm.CareGiverData;
import com.stripe.android.PaymentConfiguration;
import com.stripe.android.paymentsheet.PaymentSheet;
import com.stripe.android.paymentsheet.PaymentSheetResult;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import okhttp3.MediaType;
import okhttp3.RequestBody;

public class CgSubscriptionActivity extends AppCompatActivity
        implements SubscriptionContracts.GetSubPlansCallback,
        SubscriptionContracts.PaySubscriptionCallback,
        SubscriptionContracts.CreateSubscriptionCallback, SubscriptionContracts.GetCurrentPlanCallback, SubscriptionContracts.CancelSubscriptionCallback {

    private static final String TAG = "CgSubscriptionActivity";

    private CgSubscriptionLayoutBinding binding;

    private ArrayList<SubscriptionPlan> subscriptionPlans;

    private ProgressDialog progressDialog;

    private SubscriptionPresenter presenter;

    private PaymentSheet paymentSheet;

    private CareGiverData careGiverData;

    private String current_subscription_plan_id;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = CgSubscriptionLayoutBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        presenter = SubscriptionPresenter.getPresenter();

        initViews();

        clickEvents();

        CaregiverDataCache.getCaregiverData(this, (careGiverData -> {
            this.careGiverData = careGiverData;

            if (careGiverData != null) {
                if (careGiverData.isCaregiverTakeSubscription != 1) {
                    // not subscribed thus, load plans
                    loadPlans();
                    paymentSheet = new PaymentSheet(this, this::onPaymentSheetResult);
                } else {
                    // Already subscribed thus, loading current plans
                    loadCurrentPlans();
                }
            } else {
                binding.plansView.setVisibility(View.GONE);
            }

        }), true);

        // selecting default yearly pack
        binding.yearCheck.setSelected(true);
    }

    @Override
    protected void attachBaseContext(Context newBase) {
        final Configuration configuration = new Configuration(newBase.getResources().getConfiguration());
        configuration.fontScale = Math.min(configuration.fontScale, 1.1f);
        applyOverrideConfiguration(configuration);
        super.attachBaseContext(newBase);
    }

    private void loadCurrentPlans() {
        CaregiverDataCache.getCaregiverData(this, (careGiverData1 -> {
            this.careGiverData = careGiverData1;

            if (careGiverData1 == null) {
                binding.plansView.setVisibility(View.GONE);
                return;
            }

            progressDialog.setTitle("Please wait....");
            progressDialog.setMessage("while we fetch your subscription details");
            progressDialog.setCancelable(false);
            progressDialog.show();

            String token = "Bearer " + AppUtil.getCgToken(this);
            presenter.getCurrentSubscriptionPlan(careGiverData.caregiver_xid,
                    token, this);

        }), true);
    }

    private void clickEvents() {
        binding.makePayment.setOnClickListener(view -> {
            CaregiverDataCache.getCaregiverData(this, (careGiverData1 -> {
                this.careGiverData = careGiverData1;
                if (careGiverData1 != null) {
                    if (careGiverData.isCaregiverTakeSubscription == 1) {
                        // no sub
                        if (current_subscription_plan_id != null){
                            AppUtil.showAlert(this,
                                    "Cancel subscription",
                                    "Are you sure you want to cancel the current subscribed plan?\nThis will stop the recurring payments.\nYou will be able to use the app until current plan expires.",
                                    getString(R.string.no),
                                    ((dialogInterface, i) -> {}),
                                    getString(R.string.yes),
                                    ((dialogInterface, i) -> {
                                        // yes click
                                        cancelSubscription();
                                    }));
                        }else{
                            Toast.makeText(this, "Please try again later.", Toast.LENGTH_SHORT).show();
                        }
                    } else {
                        payForSubscription(); // uses payment sheet
//                        showCardDetailsWidget(); // uses custom elements
                    }
                } else {
                    Toast.makeText(this, "Couldn't load data", Toast.LENGTH_SHORT).show();
                }
            }), true);
        });

        binding.backBtn.setOnClickListener(view -> {
            onBackPressed();
        });

        binding.contactAdmin.setOnClickListener(view -> {
            contactMail();
        });

        binding.retry.setOnClickListener(v -> {
            CaregiverDataCache.getCaregiverData(this, (careGiverData1 -> {
                this.careGiverData = careGiverData1;

                if (careGiverData != null) {
                    if (careGiverData.isCaregiverTakeSubscription != 1) {
                        // no sub
                        loadPlans();
                    } else {
                        loadCurrentPlans();
                    }
                } else {
                    Toast.makeText(this, "Couldn't load data", Toast.LENGTH_SHORT).show();
                }
            }), true);
        });

    }

    private void cancelSubscription() {
        if (current_subscription_plan_id == null){
            Toast.makeText(this, "Please try again later.", Toast.LENGTH_SHORT).show();
            return;
        }

        progressDialog.setTitle("Please wait...");
        progressDialog.setMessage("while we cancel your subscription");
        progressDialog.setCancelable(false);
        progressDialog.show();

        presenter.cancelSubscription(current_subscription_plan_id,
                AppUtil.getCgToken(this),
                this);
    }

    private void payForSubscription() {
        if (careGiverData == null || subscriptionPlans == null) {
            Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
            return;
        }

        if (!binding.monthCheck.isSelected() && !binding.yearCheck.isSelected()) {
            Toast.makeText(this, "Please select a plan", Toast.LENGTH_SHORT).show();
            return;
        }

        int position = 0;

        if (binding.yearCheck.isSelected()) {
            position = 1;
        }

        if (position >= subscriptionPlans.size()) {
            Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
            return;
        }

        progressDialog.setTitle("Please wait...");
        progressDialog.setMessage("while we take you to the payment gateway.");
        progressDialog.setCancelable(false);
        progressDialog.show();

        SubscriptionPlan plan = subscriptionPlans.get(position);

        Map<String, RequestBody> body = new HashMap<>();

        RequestBody name_body = RequestBody.create(careGiverData.first_name, MediaType.parse("text/plain"));
        body.put("name", name_body);

        RequestBody email_body = RequestBody.create(careGiverData.email, MediaType.parse("text/plain"));
        body.put("email", email_body);

        // important part
        String plan_price;
        try {
            BigDecimal plan_price_d = new BigDecimal(plan.plan_value);
            plan_price = plan_price_d.multiply(new BigDecimal(100)).toBigInteger().toString(); // converting to cents

            RequestBody price_body = RequestBody.create(plan_price, MediaType.parse("text/plain"));
            body.put("price", price_body);

            RequestBody price_id_body = RequestBody.create(plan.stripe_price_id, MediaType.parse("text/plain"));
            body.put("price_id", price_id_body);

            RequestBody subscription_xid_body = RequestBody.create(plan.id + "", MediaType.parse("text/plain"));
            body.put("subscription_xid", subscription_xid_body);

            RequestBody caregiver_xid_body = RequestBody.create("" + careGiverData.caregiver_xid, MediaType.parse("text/plain"));
            body.put("caregiver_xid", caregiver_xid_body);

            String token = "Bearer " + AppUtil.getCgToken(this);

            presenter.getPaymentCred(token, body, this);
        } catch (Exception e) {
            progressDialog.dismiss();
            Toast.makeText(this, "Invalid price", Toast.LENGTH_SHORT).show();
            return;
        }

    }

    private void initViews() {
        // loading subscription plans
        progressDialog = new ProgressDialog(this);

        binding.description.setText(getString(R.string.subscribe_description));

//        try {
//            String description = getString(R.string.subscribe_description);
//            String contact_email = getString(R.string.contact_email);
//
//            // setting display text
//            SpannableString ss = new SpannableString(description);
//            ClickableSpan cs = new ClickableSpan() {
//                @Override
//                public void onClick(@NonNull View view) {
//                    contactMail();
//                }
//            };
//            int start_index = description.indexOf(contact_email);
//            ss.setSpan(cs, start_index, start_index + contact_email.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
//
//            binding.description.setText(ss);
//            binding.description.setMovementMethod(LinkMovementMethod.getInstance());
//        } catch (Exception e) {
//            Log.e(TAG, "initViews: ", e);
//            binding.contactAdmin.setVisibility(View.VISIBLE);
//        }
    }

    private void loadPlans() {
        CaregiverDataCache.getCaregiverData(this, (careGiverData1 -> {
            this.careGiverData = careGiverData1;

            if (careGiverData1 == null) {
                binding.plansView.setVisibility(View.GONE);
                return;
            }

            progressDialog.setTitle("Please wait....");
            progressDialog.setMessage("while we fetch subscription plans for you.");
            progressDialog.setCancelable(false);
            progressDialog.show();

            String token = "Bearer " + AppUtil.getCgToken(this);
            presenter.getSubscriptionPlans(token, this);
        }), true);
    }

    private void contactMail() {
        String contact_email = getString(R.string.contact_email);

        Intent intent = new Intent(Intent.ACTION_SENDTO);
        intent.setData(Uri.fromParts("mailto", contact_email, null));

        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivity(intent);
        }
    }

    // payment callback
    public void onPaymentSheetResult(final PaymentSheetResult paymentSheetResult) {
        // implemented in the next steps
        if (paymentSheetResult instanceof PaymentSheetResult.Canceled) {
            Toast.makeText(this, "Payment canceled.", Toast.LENGTH_SHORT).show();
        } else if (paymentSheetResult instanceof PaymentSheetResult.Failed) {
            Log.e(TAG, "Got error: ", ((PaymentSheetResult.Failed) paymentSheetResult).getError());
            Toast.makeText(this, "Payment failed.", Toast.LENGTH_SHORT).show();
        } else if (paymentSheetResult instanceof PaymentSheetResult.Completed) {
            // Display for example, an order confirmation screen

            this.careGiverData.isCaregiverTakeSubscription = 1;
            CaregiverDataCache.setCareGiverData(this.careGiverData);

            Intent intent = new Intent(this, CgProfileProgressActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            finish();
        }

    }

//    private void createSubscription() {
//        if (this.stripe_price_id == null || this.payment_intent_id == null) {
//            // something went wrong
//            Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
//            return;
//        }
//
//        progressDialog.setTitle("Almost there...");
//        progressDialog.setMessage("We are verifying your payment.\nDon't leave the app screen.");
//        progressDialog.setCancelable(false);
//        progressDialog.show();
//
//        Map<String, RequestBody> bodyMap = new HashMap<>();
//
//        RequestBody pay_intent_id_body = RequestBody.create(this.payment_intent_id, MediaType.parse("text/plain"));
//        bodyMap.put("payment_intent_id", pay_intent_id_body);
//
//        RequestBody price_id_body = RequestBody.create(this.stripe_price_id, MediaType.parse("text/plain"));
//        bodyMap.put("price_id", price_id_body);
//
//        presenter.createSubscription(bodyMap,
//                "Bearer " + AppUtil.getCgToken(this),
//                this);
//
//    }

    private void inflateCurrentPlan(CurrentPlan currentPlan) {
        binding.datesView.setVisibility(View.VISIBLE); // to show expiry and cancelled dates

        binding.makePayment.setVisibility(View.VISIBLE);
        binding.makePayment.setText(R.string.cancel_subscription);

        if ("2".equals(currentPlan.is_subscription_completed)){
            // subscription is cancelled
            binding.makePayment.setVisibility(View.GONE);

            binding.description.setText(getString(R.string.subscribe_cancelled_description));

            String cancelled_date = AppUtil.formatDate("yyyy-mm-dd", "mm-dd-yyyy", currentPlan.ended_at);
            if (cancelled_date != null){
                binding.cancelledDate.setText(cancelled_date);
                binding.cancelledDate.setVisibility(View.VISIBLE);

                binding.cancelledDateText.setVisibility(View.VISIBLE);
            }else {
                binding.cancelledDateText.setVisibility(View.GONE);
                binding.cancelledDate.setVisibility(View.GONE);
            }
        }

        binding.yourPlan.setVisibility(View.VISIBLE);

        SubscriptionPlan plan = currentPlan.plan;

        String per_duration = null;

        // re-using per month card for showing current plan
        if (getString(R.string.monthly).equals(plan.plan_name)) {
            // monthly
            binding.monthlyName.setText(plan.plan_name);
            binding.monthCheck.setSelected(true);

            String price = "$" + plan.plan_value;
            binding.monthlyPrice.setText(price);

            per_duration = "/mo";

            binding.monthCard.setVisibility(View.VISIBLE);
            binding.yearCard.setVisibility(View.GONE);

        } else if (getString(R.string.year).equals(plan.plan_name)) {
            // yearly

            // code to show discounts and other values.
//            binding.yearlyName.setText(plan.plan_name);
//
//            binding.yearCheck.setSelected(true);
//
//            String price = "$" + plan.plan_value;
//            binding.yearDiscountedPrice.setText(price);
//
//            binding.yearActualPrice.setVisibility(View.GONE);
//            binding.yearDiscount.setVisibility(View.GONE);
//
//            try {
//                BigDecimal year_price_d = new BigDecimal(plan.plan_value);
//                String yearly_month_price = year_price_d.divide(new BigDecimal(12), RoundingMode.DOWN).toString();
//                yearly_month_price = "$" + yearly_month_price;
//                binding.yearlyMonthPrice.setText(yearly_month_price);
//            } catch (Exception e) {
//                binding.yearlyMonthPrice.setVisibility(View.GONE);
//            }

            // code to only show name
            binding.monthlyName.setText(plan.plan_name);
            binding.monthCheck.setSelected(true);

            String price = "$" + plan.plan_value;
            binding.monthlyPrice.setText(price);

            per_duration = "/year";

            binding.monthCard.setVisibility(View.VISIBLE);
            binding.yearCard.setVisibility(View.GONE);
        }

        if (per_duration != null) {
            binding.perMonthText.setText(per_duration);
        }else{
            binding.perMonthText.setVisibility(View.GONE);
        }

        // next due date
        String next_due_date = AppUtil.formatDate("yyyy-mm-dd", "mm-dd-yyyy", currentPlan.current_period_end);
        if (next_due_date != null){
            binding.nextDueDate.setText(next_due_date);
            binding.nextDueDate.setVisibility(View.VISIBLE);

            String next_due_text;
            if ("2".equals(currentPlan.is_subscription_completed)){
                // cancelled subscription
                next_due_text = "Your current plan will expire on";
            }else{
                next_due_text = "Next payment is due on";
            }

            binding.nextDueDateText.setText(next_due_text);
            binding.nextDueDateText.setVisibility(View.VISIBLE);
        }

    }

    private void inflatePlans() {

        binding.makePayment.setVisibility(View.VISIBLE);
        binding.makePayment.setText(getString(R.string.subscribe));

        binding.yourPlan.setVisibility(View.GONE);

        binding.yearCard.setVisibility(View.VISIBLE);
        binding.yearCard.setOnClickListener(v -> {
            if (!binding.yearCheck.isSelected()) {
                // not selected
                binding.monthCheck.setSelected(false);
                binding.yearCheck.setSelected(true);
            }
        });

        binding.monthCard.setVisibility(View.VISIBLE);
        binding.monthCard.setOnClickListener(v -> {
            if (!binding.monthCheck.isActivated()) {
                binding.yearCheck.setSelected(false);
                binding.monthCheck.setSelected(true);
            }
        });

        try {
            String monthly_price = null;
            String yearly_price = null;

            for (SubscriptionPlan plan : subscriptionPlans) {
                if (getString(R.string.monthly).equals(plan.plan_name)) {
                    // monthly
                    binding.monthlyName.setText(plan.plan_name);
                    monthly_price = plan.plan_value;
                } else if (getString(R.string.year).equals(plan.plan_name)) {
                    // yearly
                    binding.yearlyName.setText(plan.plan_name);
                    yearly_price = plan.plan_value;
                }
            }

            if (monthly_price == null || yearly_price == null) throw new Exception();

            binding.yearDiscountedPrice.setText(yearly_price);
            binding.monthlyPrice.setText("$" + monthly_price);

            BigDecimal TWELVE = new BigDecimal(12);

            BigDecimal year_price_d = new BigDecimal(yearly_price);
            BigDecimal month_price_d = new BigDecimal(monthly_price);

            BigDecimal actual_year_price = month_price_d.multiply(TWELVE);

            String strike_actual_year_price = "<strike>$" + actual_year_price + "</strike>";
            binding.yearActualPrice.setText(Html.fromHtml(strike_actual_year_price));

            String yearly_month_price = year_price_d.divide(TWELVE, RoundingMode.DOWN).toString();
            yearly_month_price = "$" + yearly_month_price;
            binding.yearlyMonthPrice.setText(yearly_month_price);

            try {
                String discount = (actual_year_price.subtract(year_price_d)).divide(actual_year_price, RoundingMode.DOWN).multiply(new BigDecimal(100)).toBigInteger().toString() + "% OFF";
                binding.yearDiscount.setText(discount);
            } catch (Exception e) {
                binding.yearDiscount.setVisibility(View.GONE);
            }

            binding.plansView.setVisibility(View.VISIBLE);

        } catch (Exception e) {
            binding.plansView.setVisibility(View.GONE);
        }
    }

    // get payment credentials callback
    @Override
    public void onPaymentCredFetched(SubscriptionCredentials credentials) {
        if (credentials == null || credentials.stripe_publish_key == null) {
            progressDialog.dismiss();
            Toast.makeText(this, "Something went wrong.", Toast.LENGTH_SHORT).show();
            return;
        }

        PaymentConfiguration.init(getApplicationContext(), credentials.stripe_publish_key);

        final PaymentSheet.CustomerConfiguration customerConfig = new PaymentSheet.CustomerConfiguration(
                credentials.customerId,
                credentials.ephemeralKey
        );

        // dismissing dialog now
        progressDialog.dismiss();

        final PaymentSheet.Configuration configuration = new PaymentSheet.Configuration.Builder("SimpliTend")
                .customer(customerConfig)
                .allowsDelayedPaymentMethods(false)
                .build();

        paymentSheet.presentWithPaymentIntent(
                credentials.clientSecret,
                configuration
        );

    }

    @Override
    public void onPaymentCredFetchFailed(Throwable throwable, String message) {
        progressDialog.dismiss();
        Toast.makeText(this, "" + message, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onSubscriptionFetched(ArrayList<SubscriptionPlan> subscriptionPlans) {
        this.subscriptionPlans = subscriptionPlans;
        inflatePlans();
        progressDialog.dismiss();
    }

    @Override
    public void onSubsFetchFailed(Throwable t, String message) {
        progressDialog.dismiss();
        binding.plansView.setVisibility(View.GONE);
    }

    // subscription create callback
    @Override
    public void onSubscriptionCreated() {
        // statically changing the flag of subscription to 1
        if (careGiverData != null) {
            careGiverData.isCaregiverTakeSubscription = 1;
        }

        Intent intent = new Intent(this, CgProfileProgressActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        progressDialog.dismiss();

        startActivity(intent);
        finish();
    }

    @Override
    public void onSubscriptionCreateFailed(Throwable throwable, String message) {
        progressDialog.dismiss();
        AppUtil.showAlert(this,
                getString(R.string.something_went_wrong),
                message,
                "OK",
                ((dialogInterface, i) -> {

                }), null, null);
    }

    @Override
    public void currentPlan(@NonNull CurrentPlan currentPlan) {
        progressDialog.dismiss();
        inflateCurrentPlan(currentPlan);
        this.current_subscription_plan_id = currentPlan.subscription_id;
    }

    @Override
    public void failedCurrentPlan(Throwable t, String message) {
        progressDialog.dismiss();
        binding.plansView.setVisibility(View.GONE);
    }

    @Override
    public void subscriptionCancelled(@NonNull CurrentPlan currentPlan) {
        progressDialog.dismiss();
        Toast.makeText(this, "Subscription cancelled.", Toast.LENGTH_SHORT).show();
        inflateCurrentPlan(currentPlan);
        this.current_subscription_plan_id = null;
    }

    @Override
    public void subscriptionCancelFailed(Throwable t, String message) {
        progressDialog.dismiss();
        Toast.makeText(this, "" + message, Toast.LENGTH_SHORT).show();
    }
}
