package com.atmob.voiceai.module.subscription;

import android.os.SystemClock;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.atmob.app.lib.base.BaseViewModel;
import com.atmob.app.lib.handler.RxHttpHandler;
import com.atmob.app.lib.livedata.SingleLiveEvent;
import com.atmob.common.data.KVUtils;
import com.atmob.common.logging.AtmobLog;
import com.atmob.common.runtime.ActivityUtil;
import com.atmob.common.runtime.ContextUtil;
import com.atmob.voiceai.R;
import com.atmob.voiceai.data.api.AtmobApi;
import com.atmob.voiceai.data.api.bean.GoodsBean;
import com.atmob.voiceai.data.api.bean.PayOptionsBean;
import com.atmob.voiceai.data.api.response.OrderPayResponse;
import com.atmob.voiceai.data.repositories.MemberRepository;
import com.atmob.voiceai.helper.ErrorHelper;
import com.atmob.voiceai.sdk.billing.GPBillingClient;
import com.atmob.voiceai.utils.BoxingUtil;
import com.atmob.voiceai.utils.SpannableUtil;
import com.atmob.voiceai.utils.ToastUtil;

import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import atmob.reactivex.rxjava3.annotations.NonNull;
import atmob.reactivex.rxjava3.core.Observable;
import atmob.reactivex.rxjava3.core.ObservableSource;
import atmob.reactivex.rxjava3.core.Single;
import atmob.reactivex.rxjava3.core.SingleObserver;
import atmob.reactivex.rxjava3.core.SingleSource;
import atmob.reactivex.rxjava3.disposables.Disposable;
import atmob.reactivex.rxjava3.functions.Function;
import atmob.reactivex.rxjava3.schedulers.Schedulers;
import atmob.rxjava.utils.RxJavaUtil;
import dagger.hilt.android.lifecycle.HiltViewModel;

@HiltViewModel
public class SubscriptionPageViewModel extends BaseViewModel {


    private final String TAG = SubscriptionPageViewModel.class.getSimpleName();
    private final String LAST_BACK_SHOW_RETAIN_TIME = "last_back_show_retain_time";

    private final SingleLiveEvent<?> showRetentionDialogEvent = new SingleLiveEvent<>();
    private final SingleLiveEvent<?> finishEvent = new SingleLiveEvent<>();

    private final MutableLiveData<Boolean> isShowCloseBtn = new MutableLiveData<>();
    private final MutableLiveData<List<GoodsBean>> goodsList = new MutableLiveData<>();
    private final GPBillingClient gpBillingClient;
    private List<PayOptionsBean> payList;
    private final MutableLiveData<CharSequence> autoRenewableText = new MutableLiveData<>();
    private final MutableLiveData<CharSequence> subCancelTxt = new MutableLiveData<>();
    private final MemberRepository memberRepository;
    private GoodsBean checkGoodsBean;
    private boolean isRequestSubmitOrder;


    @Inject
    public SubscriptionPageViewModel(MemberRepository memberRepository, GPBillingClient gpBillingClient) {
        this.memberRepository = memberRepository;
        this.gpBillingClient = gpBillingClient;
        init();
        refreshSubscriptionDetail();
        gpBillingClient.startUrgentConnection();
    }

    public void setCheckGoodsBean(GoodsBean checkGoodsBean) {
        this.checkGoodsBean = checkGoodsBean;
    }

    public LiveData<?> getShowRetentionDialogEvent() {
        return showRetentionDialogEvent;
    }

    public LiveData<?> getFinishEvent() {
        return finishEvent;
    }

    public LiveData<Boolean> getIsShowCloseBtn() {
        return isShowCloseBtn;
    }

    public LiveData<List<GoodsBean>> getGoodsList() {
        return goodsList;
    }

    private void init() {
        initSubTxt();
        addDisposable(RxJavaUtil.timer(3000, TimeUnit.MILLISECONDS, () -> {
            isShowCloseBtn.setValue(true);
        }));
    }

    private void initSubTxt() {
        String allRenewableTxt = "Subscription is auto-renewable.";
        String targetRenewableTxt = "auto-renewable";
        autoRenewableText.setValue(SpannableUtil.getSpannableStringBuilder(allRenewableTxt, targetRenewableTxt, ContextUtil.getContext().getResources().getColor(R.color.colorPrimaryVariant), false));
        String allCancelTxt = "You can cancel your subscription at any time.";
        String targetCancelTxt = "at any time";
        subCancelTxt.setValue(SpannableUtil.getSpannableStringBuilder(allCancelTxt, targetCancelTxt, ContextUtil.getContext().getResources().getColor(R.color.colorPrimaryVariant), false));
    }

    public LiveData<CharSequence> getAutoRenewableText() {
        return autoRenewableText;
    }

    public LiveData<CharSequence> getSubCancelTxt() {
        return subCancelTxt;
    }

    public void onBackClick() {
        if (isShowRetentionDialog()) {
            showRetentionDialogEvent.call();
        } else {
            finishEvent.call();
        }
    }

    public void onRestoreClick() {
        memberRepository.subscriptionResume()
                .subscribe(new SingleObserver<Object>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        addDisposable(d);
                    }

                    @Override
                    public void onSuccess(@NonNull Object object) {
                        ToastUtil.show(R.string.member_restore_success, ToastUtil.LENGTH_SHORT);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        ErrorHelper.errorThrowableToast(e, R.string.member_restore_fail, ToastUtil.LENGTH_SHORT);
                    }
                });
    }


    private void refreshSubscriptionDetail() {
        memberRepository.payGoodsList()
                .map(payGoodsResponse -> {
                    payList = payGoodsResponse.getPayOptions();
                    return payGoodsResponse.getList();
                })
                .flatMapObservable((Function<List<GoodsBean>, ObservableSource<GoodsBean>>) Observable::fromIterable)
                .flatMapSingle((Function<GoodsBean, SingleSource<GoodsBean>>) memberBean
                        -> gpBillingClient.querySkuDetails(BillingClient.ProductType.SUBS,
                                memberBean.getGoogleProductId(), memberBean.getPlanId(), memberBean.getLowGoogleProductId())
                        .map(gPProductInfo -> {
                            memberBean.setGpProductInfo(gPProductInfo);
                            return memberBean;
                        })
                        .subscribeOn(Schedulers.io())
                )
                .toSortedList()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new SingleObserver<List<GoodsBean>>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        addDisposable(d);
                    }

                    @Override
                    public void onSuccess(@NonNull List<GoodsBean> goodsBeanList) {
                        goodsList.setValue(goodsBeanList);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        ErrorHelper.errorThrowableToast(e, ToastUtil.LENGTH_SHORT);
                    }
                });
    }

    public void setRetentionTime() {
        KVUtils.getDefault().putLong(LAST_BACK_SHOW_RETAIN_TIME, SystemClock.elapsedRealtime());
    }

    public boolean isShowRetentionDialog() {
        long lastShowTime = KVUtils.getDefault().getLong(LAST_BACK_SHOW_RETAIN_TIME, 0);
        return SystemClock.elapsedRealtime() - lastShowTime > 12 * 60 * 60 * 1000;
    }


    public void onSubNowClick() {
        if (isRequestSubmitOrder) {
            return;
        }
        if (checkGoodsBean == null) {
            ToastUtil.show(R.string.please_select_goods, ToastUtil.LENGTH_SHORT);
            return;
        }
        if (payList == null || payList.isEmpty()) {
            ToastUtil.show(R.string.no_pay_way, ToastUtil.LENGTH_SHORT);
            return;
        }
        PayOptionsBean payOptionsBean = payList.get(0);
        int payPlatform = payOptionsBean.getPayPlatform();
        int payMethod = payOptionsBean.getPayMethod();
        memberRepository.requestPayOrder(checkGoodsBean.getId(), payPlatform, payMethod)
                .subscribe(new SingleObserver<OrderPayResponse>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        addDisposable(d);
                        isRequestSubmitOrder = true;
                    }

                    @Override
                    public void onSuccess(@NonNull OrderPayResponse orderPayResponse) {
                        isRequestSubmitOrder = false;
                        requestPayment(checkGoodsBean, orderPayResponse.getOutTradeNo());
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        isRequestSubmitOrder = false;
                        ErrorHelper.errorThrowableToast(e, ToastUtil.LENGTH_SHORT);
                    }
                });
    }

    private void requestPayment(GoodsBean bean, String orderNo) {
        gpBillingClient.subscriptionGoods(ActivityUtil.getTopActivity(),
                        bean.getGpProductInfo().getProductDetails(), bean.getPlanId(), orderNo)
                .compose(RxJavaUtil.SingleSchedule.subThread2Main())
                .subscribe(new SingleObserver<BillingResult>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        addDisposable(d);
                    }

                    @Override
                    public void onSuccess(@NonNull BillingResult billingResult) {
                        AtmobLog.d(TAG, "requestPayment onSuccess: " + billingResult);
                        gpBillingClient.registerFlowListener(this, orderNo, purchase -> queryOrderStatus(bean, orderNo, purchase));
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }
                });
    }

    private void queryOrderStatus(GoodsBean bean, String orderNo, Purchase purchase) {
        memberRepository.orderStatus(orderNo, purchase.getPurchaseToken())
                .subscribe(new SingleObserver<Boolean>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        addDisposable(d);
                    }

                    @Override
                    public void onSuccess(@NonNull Boolean aBoolean) {
                        if (BoxingUtil.boxing(aBoolean)) {
                            ToastUtil.show(R.string.pay_success, ToastUtil.LENGTH_SHORT);
                            finishEvent.call();
                        }
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }
                });
    }

    public void onSubRetentionClick() {
        onSubNowClick();
    }



    @Override
    protected void onCleared() {
        super.onCleared();
        gpBillingClient.endUrgentConnection();
        gpBillingClient.unregisterAllFlowListener(this);
    }
}
