package co.pixelbeard.theanfieldwrap.freeSubscription;

import static java.lang.Math.abs;

import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;

import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import co.pixelbeard.theanfieldwrap.R;
import co.pixelbeard.theanfieldwrap.billing.BillingConstants;
import co.pixelbeard.theanfieldwrap.billing.BillingManager;
import co.pixelbeard.theanfieldwrap.billing.Security;
import co.pixelbeard.theanfieldwrap.buyTokens.IndicatorAdapter;
import co.pixelbeard.theanfieldwrap.data.responses.SubscriptionItemResponse;
import co.pixelbeard.theanfieldwrap.data.source.DataRepository;
import co.pixelbeard.theanfieldwrap.data.source.local.LocalRepository;
import co.pixelbeard.theanfieldwrap.data.source.remote.RemoteRepository;
import co.pixelbeard.theanfieldwrap.databinding.ActivitySubscriptionBinding;
import co.pixelbeard.theanfieldwrap.dialog.LoadingDialog;
import co.pixelbeard.theanfieldwrap.utils.BaseActivity;
import co.pixelbeard.theanfieldwrap.utils.DialogUtils;
import co.pixelbeard.theanfieldwrap.utils.PrefKey;
import co.pixelbeard.theanfieldwrap.utils.PrefUtils;
import io.realm.Realm;

public class SubscriptionActivity extends BaseActivity implements SkuDetailsResponseListener, BillingManager.BillingUpdatesListener, SubscriptionContract.View {

    private String TAG = SubscriptionActivity.class.getName();
    private ActivitySubscriptionBinding binding;
    private IndicatorAdapter indicatorAdapter;
    private BillingManager mBillingManager;
    private List<SkuDetails> skuDetailsList;
    private LoadingDialog loadingDialog;

    private SubscriptionContract.Presenter mPresenter;
    private int activationDuration = 0;
    private String planType = "";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_subscription);
        new SubscriptionPresenter(this, new DataRepository(new LocalRepository(Realm.getDefaultInstance()), new RemoteRepository()));
        handleClick();
        setupBilling();
        handleIntent();
    }

    private void handleIntent() {
        Intent intent = this.getIntent();
        Bundle bundle = intent.getExtras();

        ArrayList<SubscriptionModel> subscriptionItem = bundle.getParcelableArrayList(BillingConstants.SUBSCRIPTION);
        setViewPager(subscriptionItem);
    }

    private void setViewPager(List<SubscriptionModel> mainModel) {
        binding.subscriptionViewPager.setAdapter(new SubscriptionViewPager(getSupportFragmentManager(), getLifecycle(), mainModel));
        // You need to retain one page on each side so that the next and previous items are visible
        binding.subscriptionViewPager.setOffscreenPageLimit(1);

        // Add a PageTransformer that translates the next and previous items horizontally
        // towards the center of the screen, which makes them visible
        float nextItemVisiblePx = getResources().getDimension(R.dimen.viewpager_next_item_visible);
        float pageTranslationX = nextItemVisiblePx;
        binding.subscriptionViewPager.setPageTransformer((page, position) -> {
            page.setTranslationX(-pageTranslationX * position);
            page.setScaleY(1 - (0.10f * abs(position)));
        });

        // The ItemDecoration gives the current (centered) item horizontal margin so that
        // it doesn't occupy the whole screen width. Without it the items overlap
        HorizontalMarginItemDecoration itemDecoration = new HorizontalMarginItemDecoration(this, R.dimen.viewpager_current_item_horizontal_margin);
        binding.subscriptionViewPager.addItemDecoration(itemDecoration);
        binding.subscriptionViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }

            @Override
            public void onPageSelected(int position) {
                indicatorAdapter.setSelected(position);
                super.onPageSelected(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                super.onPageScrollStateChanged(state);
            }
        });
        setupPagerIndicator(mainModel.size());
    }

    private void handleClick() {
        binding.closeBtn.setOnClickListener(view -> {
            finish();
        });
    }

    private void setupPagerIndicator(int count) {
        binding.pagerIndicator.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));
        indicatorAdapter = new IndicatorAdapter(count);
        indicatorAdapter.setDotColor(R.drawable.subscribe_selected_indicator);
        binding.pagerIndicator.setAdapter(indicatorAdapter);
    }

    private void setupBilling() {
        mBillingManager = new BillingManager(this, this);
    }

    private void querySkuDetails() {
        List<String> skuList = BillingConstants.getSubscriptionList(BillingClient.SkuType.SUBS);
        SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
        params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS);

        mBillingManager.querySkuDetailsAsync(BillingClient.SkuType.SUBS, skuList, this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mBillingManager.destroy();
    }

    @Override
    public void onBillingClientSetupFinished() {
        querySkuDetails();
    }

    @Override
    public void onConsumeFinished(String token, int result) {
    }

    @Override
    public void onPurchasesUpdated(List<Purchase> purchases) {
        for (Purchase purchase : purchases) {
            if (!verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
                return;
            }
            for (String skId : purchase.getSkus()) {
                if (mPresenter != null)
                    mPresenter.activatePaidSubscription(BillingConstants.getAuthLevelSubscriptionSKU(skId), planType, activationDuration, purchase.getPurchaseToken());
            }
        }
    }

    private boolean verifyValidSignature(String signedData, String signature) {
        try {
            return Security.verifyPurchase(BillingManager.BASE_64_ENCODED_PUBLIC_KEY, signedData, signature);
        } catch (IOException e) {
            Log.e(TAG, "Got an exception trying to validate a purchase: " + e);
            return false;
        }
    }

    @Override
    public void onSkuDetailsResponse(@NonNull BillingResult billingResult, @Nullable List<SkuDetails> skuDetailsList) {
        if (skuDetailsList.size() > 0) {
            this.skuDetailsList = skuDetailsList;
        } else {
            DialogUtils.showSingleButtonDialog(getString(R.string.error), getString(R.string.failed_to_get_iap), this, null);
        }
    }

    private SkuDetails getPlayStoreSubscriptionDetails(String subscriptionName) {
        for (SkuDetails skuDetails : skuDetailsList) {
            if (BillingConstants.getSubscriptionSKU(subscriptionName).equals(skuDetails.getSku()))
                return skuDetails;
        }
        return null;
    }

    void purchaseSubscription(String subscriptionName, String planType, int days) {
        this.planType = planType;
        activationDuration = days;
        mBillingManager.initiatePurchaseFlow(getPlayStoreSubscriptionDetails(subscriptionName));
    }

    @Override
    public void onActiveSubscription(ActiveSubscriptionResponse response) {
        PrefUtils.getInstance().putBooleanPref(PrefKey.SHOW_SUBSCRIPTION_FREE, false);
        Toast.makeText(this, response.getMessage(), Toast.LENGTH_LONG).show();
        finish();
    }

    @Override
    public void onActivePaidSubscription(ActiveSubscriptionResponse response) {
        Toast.makeText(this, response.getMessage(), Toast.LENGTH_LONG).show();
        PrefUtils.getInstance().putBooleanPref(PrefKey.SHOW_SUBSCRIPTION_FREE, false);
        finish();
    }

    @Override
    public void showActivateError(String message) {
        showSingleButtonDialog(getString(R.string.error), message, null);
    }

    private void showSingleButtonDialog(String string, String error, DialogInterface.OnDismissListener listener) {
        DialogUtils.showSingleButtonDialog(string, error, this, listener);
    }

    @Override
    public void setPresenter(SubscriptionContract.Presenter presenter) {
        if (presenter != null) {
            this.mPresenter = presenter;
        } else {
            throw new RuntimeException();
        }
    }

    @Override
    public void goBack() {
    }

    @Override
    public void showLoader(String text) {
        loadingDialog = new LoadingDialog(text, this);
        loadingDialog.setCancelable(false);
        loadingDialog.setCanceledOnTouchOutside(false);
        loadingDialog.show();
    }

    @Override
    public void hideLoader() {
        if (loadingDialog != null && loadingDialog.isShowing()) {
            try {
                loadingDialog.dismiss();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onUnknownError(String error) {

    }

    @Override
    public void onTimeout() {

    }

    @Override
    public void onNetworkError() {

    }

    @Override
    public void onConnectionError() {

    }

    @Override
    public void logoutUser() {

    }

    @Override
    public boolean checkConnection() {
        return false;
    }
}
