package it.integry.integrywmsnative.core.REST.consumers;

import com.annimon.stream.Stream;
import com.google.gson.JsonObject;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;

import it.integry.integrywmsnative.core.CommonConst;
import it.integry.integrywmsnative.core.REST.RESTBuilder;
import it.integry.integrywmsnative.core.REST.model.DistribuzioneColloDTO;
import it.integry.integrywmsnative.core.REST.model.ServiceRESTResponse;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.CommonModelConsts;
import it.integry.integrywmsnative.core.model.MtbAart;
import it.integry.integrywmsnative.core.model.MtbColr;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.model.MtbDepoPosizione;
import it.integry.integrywmsnative.core.model.secondary.GestioneEnum;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityBarcode;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.plugins.barcode_base_library.model.BarcodeScanDTO;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class ColliMagazzinoRESTConsumer extends _BaseRESTConsumer{


    public static void getAvailablePosizioni(RunnableArgs<List<MtbDepoPosizione>> onComplete, RunnableArgs<Exception> onFailed) {
        String codMdep = SettingsManager.i().userSession.depo.getCodMdep();

        ColliMagazzinoRESTConsumerService colliMagazzinoRESTConsumerService = RESTBuilder.getService(ColliMagazzinoRESTConsumerService.class);
        colliMagazzinoRESTConsumerService.getAvailablePosizioni(codMdep).enqueue(new Callback<ServiceRESTResponse<List<MtbDepoPosizione>>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<List<MtbDepoPosizione>>> call, Response<ServiceRESTResponse<List<MtbDepoPosizione>>> response) {
                analyzeAnswer(response, "getAvailablePosizioni", (m) -> {
                    onComplete.run(response.body().getDto());
                }, onFailed);
            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<List<MtbDepoPosizione>>> call, Throwable t) {
                onFailed.run(new Exception(t));
            }
        });
    }


    public static void saveCollo(MtbColt mtbColtToSave, final ISimpleOperationCallback<MtbColt> callback){

        EntityRESTConsumer.processEntity(mtbColtToSave, callback, MtbColt.class);

    }


    public static void saveCollo(MtbColt mtbColtToSave, RunnableArgs<MtbColt> onComplete, RunnableArgs<Exception> onFailed){

        EntityRESTConsumer.processEntity(mtbColtToSave, new ISimpleOperationCallback<MtbColt>() {
            @Override
            public void onSuccess(MtbColt value) {
                if(onComplete != null) onComplete.run(value);
            }

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

    }

    public static void saveRigaCollo(MtbColr mtbColrToSave, RunnableArgs<MtbColr> onComplete, RunnableArgs<Exception> onFailed){

        EntityRESTConsumer.processEntity(mtbColrToSave, new ISimpleOperationCallback<MtbColr>() {
            @Override
            public void onSuccess(MtbColr value) {
                if(onComplete != null) onComplete.run(value);
            }

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

    }

    public static void createColloLavorazione(int segno, RunnableArgs<MtbColt> onComplete, RunnableArgs<Exception> onFailed) {
        MtbColt mtbColtToCreate = new MtbColt()
                .setSegno(segno)
                .setGestione(GestioneEnum.LAVORAZIONE);

        mtbColtToCreate
                .setOperation(CommonModelConsts.OPERATION.INSERT);


        saveCollo(mtbColtToCreate, new ISimpleOperationCallback<MtbColt>() {
            @Override
            public void onSuccess(MtbColt value) {
                if(onComplete != null) onComplete.run(value);
            }

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


    public static void createColloFromEtichettaAnonima(BarcodeScanDTO barcodeScanDTO, GestioneEnum gestione, RunnableArgs<MtbColt> onComplete, RunnableArgs<Exception> onFailed) {
        createColloFromEtichettaAnonima(barcodeScanDTO.getStringValue(), gestione, onComplete, onFailed);
    }


    public static void createColloFromEtichettaAnonima(String barcode, GestioneEnum gestione, RunnableArgs<MtbColt> onComplete, RunnableArgs<Exception> onFailed) {

        MtbColt mtbColtToCreate = new MtbColt()
                .setGestione(gestione);

        Integer customNumCollo = UtilityBarcode.getNumColloFromULAnonima(barcode);
        String customSerCollo = CommonConst.Config.DEFAULT_ANONYMOUS_UL_SERIE;

        if(customNumCollo != null) {
            mtbColtToCreate.setNumCollo(customNumCollo);
        }

        if(!UtilityString.isNullOrEmpty(customSerCollo)) {
            mtbColtToCreate.setSerCollo(customSerCollo);
        }

        Calendar calendar = Calendar.getInstance();
        int currentYear = calendar.get(Calendar.YEAR);


        String fullYear = "20" + UtilityBarcode.getAnnoColloFromULAnonima(barcode);



        if(!fullYear.equalsIgnoreCase("" + currentYear)){
            onFailed.run(new Exception("Per continuare scansiona un'etichetta dell'anno corrente"));
        }

        mtbColtToCreate
                .setOperation(CommonModelConsts.OPERATION.INSERT);

        saveCollo(mtbColtToCreate, new ISimpleOperationCallback<MtbColt>() {
            @Override
            public void onSuccess(MtbColt value) {
                if(onComplete != null) onComplete.run(value);
            }

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

    public static void deleteCollo(MtbColt mtbColtToDelete, Runnable onComplete, RunnableArgs<Exception> onFailed){

        mtbColtToDelete.setOperation(CommonModelConsts.OPERATION.DELETE);

        saveCollo(mtbColtToDelete, new ISimpleOperationCallback<MtbColt>() {
            @Override
            public void onSuccess(MtbColt value) {
                if(onComplete != null) onComplete.run();
            }

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

    }

    public static void distribuisciCollo(MtbColt mtbColtToDistribute, DistribuzioneColloDTO.CriterioDistribuzione criterioDistribuzione, Runnable onComplete, RunnableArgs<Exception> onFailed) {

        DistribuzioneColloDTO distribuzioneColloDTO = new DistribuzioneColloDTO()
                .setCriterioDistribuzione(criterioDistribuzione)
                .setDataCollo(mtbColtToDistribute.getDataColloS())
                .setNumCollo(mtbColtToDistribute.getNumCollo())
                .setGestione(mtbColtToDistribute.getGestione())
                .setSerCollo(mtbColtToDistribute.getSerCollo());

        ColliMagazzinoRESTConsumerService colliMagazzinoRESTConsumerService = RESTBuilder.getService(ColliMagazzinoRESTConsumerService.class);
        colliMagazzinoRESTConsumerService.distribuisciCollo(distribuzioneColloDTO)
            .enqueue(new Callback<ServiceRESTResponse<JsonObject>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<JsonObject>> call, Response<ServiceRESTResponse<JsonObject>> response) {
                analyzeAnswer(response, "DistribuzioneCollo", obj -> onComplete.run(), onFailed);
            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<JsonObject>> call, Throwable t) {
                onFailed.run(new Exception(t));
            }
        });

    }

    public static void getBySSCC(String ssccString, boolean onlyResiduo, boolean throwExcIfNull, RunnableArgs<MtbColt> onComplete, RunnableArgs<Exception> onFailed) {
        ColliMagazzinoRESTConsumerService colliMagazzinoRESTConsumerService = RESTBuilder.getService(ColliMagazzinoRESTConsumerService.class);
        colliMagazzinoRESTConsumerService.getColloByBarcode(ssccString, onlyResiduo, throwExcIfNull).enqueue(new Callback<ServiceRESTResponse<MtbColt>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<MtbColt>> call, Response<ServiceRESTResponse<MtbColt>> response) {
                analyzeAnswer(response, "GetBySSCC", mtbColt -> {

                    if(mtbColt != null && mtbColt.getMtbColr() != null && mtbColt.getMtbColr().size() > 0){
                        List<String> codMarts = Stream.of(mtbColt.getMtbColr())
                                .map(MtbColr::getCodMart)
                                .withoutNulls()
                                .distinct()
                                .toList();

                        ArticoloRESTConsumer.getByCodMart(codMarts, arts -> {

                            if(arts != null && arts.size() > 0) {
                                for (MtbColr mtbColr : mtbColt.getMtbColr()) {

                                    MtbAart foundMtbAart = null;

                                    List<MtbAart> mtbAartStream = Stream.of(arts)
                                            .filter(x -> x.getCodMart().equalsIgnoreCase(mtbColr.getCodMart())).toList();

                                    if(mtbAartStream != null && mtbAartStream.size() > 0){
                                        foundMtbAart = mtbAartStream.get(0);
                                    }

                                    mtbColr.setMtbAart(foundMtbAart);
                                    mtbColr.setGestione(mtbColt.getGestione());
                                    mtbColr.setSerCollo(mtbColt.getSerCollo());
                                    mtbColr.setNumCollo(mtbColt.getNumCollo());
                                    mtbColr.setDataCollo(mtbColt.getDataColloS());
                                }


                                onComplete.run(mtbColt);
                            }

                        }, onFailed);

                    } else {
                        onComplete.run(mtbColt);
                    }

                }, onFailed);



            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<MtbColt>> call, Throwable t) {
                onFailed.run(new Exception(t));
            }
        });
    }


    public static void getByTestata(MtbColt testata, boolean onlyResiduo, boolean throwExcIfNull, RunnableArgs<MtbColt> onComplete, RunnableArgs<Exception> onFailed) {
        String ssccString = null;

        if(testata.getSerCollo().equalsIgnoreCase(CommonConst.Config.DEFAULT_ANONYMOUS_UL_SERIE)){
            ssccString = "U";

            SimpleDateFormat sdf = new SimpleDateFormat("yy");
            ssccString += sdf.format(testata.getDataColloD());

            ssccString += String.format("%07d", testata.getNumCollo());
        } else {
            ssccString = "";

            switch (testata.getGestioneEnum()) {
                case ACQUISTO:
                    ssccString += "1";
                    break;

                case LAVORAZIONE:
                    ssccString += "2";
                    break;

                case VENDITA:
                    ssccString += "3";
                    break;
            }

            SimpleDateFormat sdf = new SimpleDateFormat("yy");
            ssccString += sdf.format(testata.getDataColloD());

            ssccString += String.format("%05d", testata.getNumCollo());
            ssccString += "0";
        }

        getBySSCC(ssccString, onlyResiduo, throwExcIfNull, onComplete, onFailed);
    }




    public static void changePosizione(MtbColt testata, MtbDepoPosizione posizione, Runnable onComplete, RunnableArgs<Exception> onFailed) {

        testata.setOperation(CommonModelConsts.OPERATION.UPDATE);

        if(posizione == null) testata.setPosizione(null);
        else testata.setPosizione(posizione.getPosizione());

        ColliMagazzinoRESTConsumer.saveCollo(testata, new ISimpleOperationCallback<MtbColt>() {
            @Override
            public void onSuccess(MtbColt value) {
                if(onComplete != null) onComplete.run();
            }

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

    }



    public static void deleteRiga(MtbColr mtbColrToDelete, Runnable onComplete, RunnableArgs<Exception> onFailed){
        MtbColr newMtbColr = new MtbColr();

        newMtbColr.setNumCollo(mtbColrToDelete.getNumCollo());
        newMtbColr.setDataCollo(mtbColrToDelete.getDataColloS());
        newMtbColr.setSerCollo(mtbColrToDelete.getSerCollo());
        newMtbColr.setGestione(mtbColrToDelete.getGestione());
        newMtbColr.setRiga(mtbColrToDelete.getRiga());


        newMtbColr.setOperation(CommonModelConsts.OPERATION.DELETE);

        EntityRESTConsumer.processEntity(newMtbColr, new ISimpleOperationCallback<MtbColr>() {
            @Override
            public void onSuccess(MtbColr value) {
                if(onComplete != null) onComplete.run();
            }

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

    }

    public static void updateRiga(MtbColr mtbColrToUpdate, Runnable onComplete, RunnableArgs<Exception> onFailed){

        mtbColrToUpdate.setOperation(CommonModelConsts.OPERATION.UPDATE);

        EntityRESTConsumer.processEntity(mtbColrToUpdate, new ISimpleOperationCallback<MtbColr>() {
            @Override
            public void onSuccess(MtbColr value) {
                if(onComplete != null) onComplete.run();
            }

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

    }







}
