package it.integry.integrywmsnative.gest.vendita.core;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.google.firebase.perf.metrics.Trace;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import it.integry.integrywmsnative.core.CommonConst;
import it.integry.integrywmsnative.core.REST.RESTBuilder;
import it.integry.integrywmsnative.core.REST.consumers.ISimpleOperationCallback;
import it.integry.integrywmsnative.core.REST.consumers.SystemRESTConsumer;
import it.integry.integrywmsnative.core.REST.model.EsitoType;
import it.integry.integrywmsnative.core.REST.model.ServiceRESTResponse;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.DtbOrdt;
import it.integry.integrywmsnative.core.model.MtbColr;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.model.secondary.GestioneEnum;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityDate;
import it.integry.integrywmsnative.core.utility.UtilityFirebase;
import it.integry.integrywmsnative.core.utility.UtilityLogger;
import it.integry.integrywmsnative.gest.vendita.dto.OrdineVenditaGroupedInevasoDTO;
import it.integry.integrywmsnative.gest.vendita.dto.OrdineVenditaInevasoDTO;
import it.integry.integrywmsnative.gest.vendita.dto.PickingObjectDTO;
import it.integry.integrywmsnative.gest.vendita.rest.OrdiniVenditaRESTConsumerService;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class VenditaHelper {

    private Context mContext;

    public VenditaHelper(Context context){
        mContext = context;
    }

    public void loadOrdini(final ILoadOrdiniCallback callback){
        String codMdep = SettingsManager.i().userSession.depo.getCodMdep();

        Trace perfTrace = UtilityFirebase.getNewPerformanceTrace("db_load_ords_v");
        perfTrace.start();

        OrdiniVenditaRESTConsumerService service = RESTBuilder.getService(OrdiniVenditaRESTConsumerService.class);
        service.listOrdiniInevasi(codMdep).enqueue(new Callback<ServiceRESTResponse<List<OrdineVenditaInevasoDTO>>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<List<OrdineVenditaInevasoDTO>>> call, Response<ServiceRESTResponse<List<OrdineVenditaInevasoDTO>>> response) {

                if(response.isSuccessful()) {

                    if(response.body() != null) {
                        if(response.body().getEsito() == EsitoType.OK) {
                            UtilityFirebase.stopPerformanceTrace(perfTrace, false);
                            callback.onLoadSuccess(response.body().getDto());
                        } else {
                            UtilityFirebase.stopPerformanceTrace(perfTrace, true);
                            Log.e("Vendita", response.body().getErrorMessage());
                            callback.onLoadFail(new Exception(response.body().getErrorMessage()));
                        }
                    } else {
                        UtilityFirebase.stopPerformanceTrace(perfTrace, true);
                        Log.e("Vendita", response.message());
                        callback.onLoadFail(new Exception(response.message()));
                    }
                } else {
                    UtilityFirebase.stopPerformanceTrace(perfTrace, true);
                    Log.e("Vendita", "Status " + response.code() + ": " + response.message());
                    callback.onLoadFail(new Exception("Status " + response.code() + ": " + response.message()));
                }
            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<List<OrdineVenditaInevasoDTO>>> call, Throwable t) {
                UtilityFirebase.stopPerformanceTrace(perfTrace, true);
                Log.e("Vendita", t.toString());
                UtilityLogger.errorMe(new Exception(t));
                callback.onLoadFail(new Exception(t));
            }
        });
    }



    public void retrievePickingList(List<String> barcodeOrdini, String dateCons, final ILoadPickingListCallback callback){
        String codMdep = SettingsManager.i().userSession.depo.getCodMdep();

        String joinedBarcodes = TextUtils.join(",", barcodeOrdini);

        OrdiniVenditaRESTConsumerService service = RESTBuilder.getService(OrdiniVenditaRESTConsumerService.class, 60);

        Trace perfTrace = UtilityFirebase.getNewPerformanceTrace("db_load_pick_v");
        perfTrace.start();

        service.getPickingList(codMdep, dateCons, joinedBarcodes).enqueue(new Callback<ServiceRESTResponse<List<PickingObjectDTO>>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<List<PickingObjectDTO>>> call, Response<ServiceRESTResponse<List<PickingObjectDTO>>> response) {
                if(response.isSuccessful()) {

                    if(response.body() != null) {
                        if(response.body().getEsito() == EsitoType.OK) {
                            UtilityFirebase.stopPerformanceTrace(perfTrace, false);
                            callback.onLoadSuccess(response.body().getDto());

                        } else {
                            Log.e("Vendita", response.body().getErrorMessage());
                            UtilityFirebase.stopPerformanceTrace(perfTrace, true);
                            callback.onLoadFail(new Exception(response.message()));
                        }
                    } else {
                        Log.e("Vendita", response.message());
                        UtilityFirebase.stopPerformanceTrace(perfTrace, true);
                        callback.onLoadFail(new Exception(response.message()));
                    }
                } else {
                    UtilityFirebase.stopPerformanceTrace(perfTrace, true);
                    Log.e("Vendita", "Status " + response.code() + ": " + response.message());
                    callback.onLoadFail(new Exception("Status " + response.code() + ": " + response.message()));
                }
            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<List<PickingObjectDTO>>> call, Throwable t) {
                UtilityFirebase.stopPerformanceTrace(perfTrace, true);
                Log.e("Vendita", t.toString());
                UtilityLogger.errorMe(new Exception(t));
                callback.onLoadFail(new Exception(t));
            }
        });

    }



    public void getBancaliVenditaGiaRegistrati(List<OrdineVenditaGroupedInevasoDTO> orders, RunnableArgs<List<MtbColt>> onComplete, RunnableArgs<Exception> onFailed) {

        String baseSql = "SELECT DISTINCT mtb_colt.* " +
                "FROM mtb_colt, mtb_colr " +
                "WHERE mtb_colt.gestione = mtb_colr.gestione AND " +
                "mtb_colt.ser_collo = mtb_colr.ser_collo AND " +
                "mtb_colt.data_collo = mtb_colr.data_collo AND " +
                "mtb_colt.num_collo = mtb_colr.num_collo AND " +
                "mtb_colt.gestione = 'V' AND " +
                "mtb_colt.data_doc is null AND ";

        String whereCond = "";

        for(int i = 0; i < orders.size(); i++){

            List<OrdineVenditaGroupedInevasoDTO.Ordine> currentOrders = orders.get(i).ordini;

            for(int j = 0; j < currentOrders.size(); j++){

                whereCond += "(mtb_colr.data_ord = '" + UtilityDate.formatDate(currentOrders.get(j).getData(), UtilityDate.COMMONS_DATE_FORMATS.YMD_SLASH) + "' " +
                        "AND mtb_colr.num_ord = " + currentOrders.get(j).getNumero() + ") ";

                if(i != (orders.size() - 1)){
                    whereCond += "OR ";
                } else if(j != (currentOrders.size() - 1)) {
                    whereCond += "OR ";
                }
            }
        }

        baseSql += "( " + whereCond + ")";

        Type typeOfObjectsList = new TypeToken<ArrayList<MtbColt>>() {}.getType();
        SystemRESTConsumer.processSql(baseSql, typeOfObjectsList, new ISimpleOperationCallback<List<MtbColt>>() {
            @Override
            public void onSuccess(List<MtbColt> value) {
                if(onComplete != null) onComplete.run(value);
            }

            @Override
            public void onFailed(Exception ex) {
                if(onFailed != null) onFailed.run(ex);
            }
        });

    }


    public void getOrdiniInCommessaCollo(MtbColt testataCollo, RunnableArgs<List<DtbOrdt>> onComplete, RunnableArgs<Exception> onFailed) {



        OrdiniVenditaRESTConsumerService service = RESTBuilder.getService(OrdiniVenditaRESTConsumerService.class);
        service.getOrdiniInCommessaCollo(
                testataCollo.getDataColloS(),
                testataCollo.getNumCollo(),
                testataCollo.getSerCollo(),
                testataCollo.getGestione(),
                GestioneEnum.VENDITA.getText(),
                SettingsManager.i().userSession.depo.getCodMdep())
                .enqueue(new Callback<ServiceRESTResponse<List<DtbOrdt>>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<List<DtbOrdt>>> call, Response<ServiceRESTResponse<List<DtbOrdt>>> response) {

                if(response.isSuccessful()) {

                    if(response.body() != null) {
                        if(response.body().getEsito() == EsitoType.OK) {
                            onComplete.run(response.body().getDto());
                        } else {
                            Log.e("getOrdiniInCommCollo", response.body().getErrorMessage());
                            onFailed.run(new Exception(response.body().getErrorMessage()));
                        }
                    } else {
                        Log.e("getOrdiniInCommCollo", response.message());
                        onFailed.run(new Exception(response.message()));
                    }
                } else {
                    Log.e("getOrdiniInCommCollo", "Status " + response.code() + ": " + response.message());
                    onFailed.run(new Exception("Status " + response.code() + ": " + response.message()));
                }

            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<List<DtbOrdt>>> call, Throwable t) {
                Log.e("getOrdiniInCommCollo", t.toString());
                UtilityLogger.errorMe(new Exception(t));
                onFailed.run(new Exception(t));
            }
        });

    }




    public List<OrdineVenditaGroupedInevasoDTO> getSelectedOrders(List<OrdineVenditaGroupedInevasoDTO> groupedOrdiniInevasi){
        List<OrdineVenditaGroupedInevasoDTO> selectedOrdini = new ArrayList<>();

        for(int i = 0; i < groupedOrdiniInevasi.size(); i++){
            List<OrdineVenditaGroupedInevasoDTO.Ordine> selectedOrdiniGroup = new ArrayList<>();

            for(int j = 0; j < groupedOrdiniInevasi.get(i).ordini.size(); j++){
                if(groupedOrdiniInevasi.get(i).ordini.get(j).checkBox) {
                    selectedOrdiniGroup.add(groupedOrdiniInevasi.get(i).ordini.get(j));
                }
            }

            if(selectedOrdiniGroup.size() > 0) {
                try {
                    OrdineVenditaGroupedInevasoDTO cloneOrdine = groupedOrdiniInevasi.get(i).clone();
                    cloneOrdine.ordini = selectedOrdiniGroup;
                    selectedOrdini.add(cloneOrdine);
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
            }
        }

        return selectedOrdini;
    }



    public void selectAll(List<OrdineVenditaGroupedInevasoDTO> groupedOrdiniInevasi) {
        toggleSelection(groupedOrdiniInevasi, true);
    }

    public void deselectAll(List<OrdineVenditaGroupedInevasoDTO> groupedOrdiniInevasi) {
        toggleSelection(groupedOrdiniInevasi, false);
    }

    public void toggleSelection(List<OrdineVenditaGroupedInevasoDTO> groupedOrdiniInevasi, boolean value) {
        for(int i = 0; i < groupedOrdiniInevasi.size(); i++){
            for(int j = 0; j < groupedOrdiniInevasi.get(i).ordini.size(); j++){
                groupedOrdiniInevasi.get(i).ordini.get(j).setCheckbox(value);
            }
        }
    }







    public interface ILoadOrdiniCallback {


        void onLoadSuccess(List<OrdineVenditaInevasoDTO> ordini);

        void onLoadFail(Exception ex);

    }


    public interface ILoadPickingListCallback {

        void onLoadSuccess(List<PickingObjectDTO> ordini);

        void onLoadFail(Exception ex);

    }


}
