package it.integry.integrywmsnative.gest.prod_rientro_merce.order_detail;

import androidx.lifecycle.MutableLiveData;

import com.annimon.stream.Optional;
import com.annimon.stream.Stream;

import java.util.Date;
import java.util.List;

import javax.inject.Inject;

import it.integry.integrywmsnative.core.interfaces.viewmodel_listeners.ILoadingListener;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.rest.consumers.ColliMagazzinoRESTConsumer;
import it.integry.integrywmsnative.gest.prod_rientro_merce.order_detail.rest.ProdRientroMerceOrderDetailRESTConsumer;
import it.integry.integrywmsnative.gest.prod_rientro_merce.order_detail.rest.dto.ImportColliDaProduzioneRequestDTO;
import it.integry.integrywmsnative.gest.prod_versamento_materiale.dto.OrdineLavorazioneDTO;

public class ProdRientroMerceOrderDetailViewModel {

    public MutableLiveData<List<MtbColt>> mtbColtsOfOrder = new MutableLiveData<>();
    private OrdineLavorazioneDTO currentOrder;

    private final ProdRientroMerceOrderDetailRESTConsumer mProdRientroMerceOrderDetailRESTConsumer;
    private final ColliMagazzinoRESTConsumer mColliMagazzinoRESTConsumer;

    private Listener mListener;

    @Inject
    public ProdRientroMerceOrderDetailViewModel(ProdRientroMerceOrderDetailRESTConsumer prodRientroMerceOrderDetailRESTConsumer,
                                                ColliMagazzinoRESTConsumer colliMagazzinoRESTConsumer) {
        this.mProdRientroMerceOrderDetailRESTConsumer = prodRientroMerceOrderDetailRESTConsumer;
        this.mColliMagazzinoRESTConsumer = colliMagazzinoRESTConsumer;
    }

    public void setOrder(OrdineLavorazioneDTO order) {
        this.currentOrder = order;

        refreshMtbColts();
    }

    private void refreshMtbColts() {
        this.sendOnLoadingStarted();
        this.mtbColtsOfOrder.postValue(null);

        this.mProdRientroMerceOrderDetailRESTConsumer.getMtbColtsOfOrder(currentOrder, mtbColts -> {
            for (MtbColt mtbColt : mtbColts) {
                mtbColt.getMtbColr().get(0)
                        .setDescrizione(currentOrder.getDescrizioneProd())
                        .setUntMis(currentOrder.getUntOrd());
            }

            this.mtbColtsOfOrder.postValue(mtbColts);
            this.sendOnLoadingEnded();
        }, this::sendError);
    }

    public void createLU(ProdRientroMerceOrderDetailPickedQuantityDTO pickedQuantityDTO) {

        new Thread(this::sendOnLoadingStarted).start();

        new Thread(() -> {

            ImportColliDaProduzioneRequestDTO importColliDaProduzioneRequestDTO =
                    new ImportColliDaProduzioneRequestDTO()
                            .setColliBancale(pickedQuantityDTO.getNumCnf().intValue())
                            .setQtaCnf(pickedQuantityDTO.getPesoCollo())
                            .setQtaCol(pickedQuantityDTO.getPesoNetto())
                            .setCodJcom(currentOrder.getCodJcom())
                            .setCodJfas(pickedQuantityDTO.getJtbFasi() != null ? pickedQuantityDTO.getJtbFasi().getCodJfas() : null)
                            .setCodMart(currentOrder.getCodProd())
                            .setCodTcol(pickedQuantityDTO.getMtbTCol().getCodTcol())
                            .setDataCollo(new Date())
                            .setDataOrd(currentOrder.getDataOrdD())
                            .setNumOrd(currentOrder.getNumOrd())
                            .setGestione(currentOrder.getGestione())
                            .setPartitaMag(currentOrder.getPartitaMag())
                            .setFornitore(currentOrder.getRagSocAnag())
                            .setPesoLordo(pickedQuantityDTO.getPesoLordo())
                            .setPesoNetto(pickedQuantityDTO.getPesoNetto());

            this.mProdRientroMerceOrderDetailRESTConsumer.importColloDaProduzione(importColliDaProduzioneRequestDTO, mtbColtSaved -> {

                synchronized (this.mtbColtsOfOrder) {
                    refreshMtbColts();
                }

                this.sendOnLoadingEnded();
            }, this::sendError);


        }).start();

    }

    public void deleteLU(MtbColt mtbColt) {
        new Thread(this::sendOnLoadingStarted).start();

        new Thread(() -> {
            this.mProdRientroMerceOrderDetailRESTConsumer.deleteColloDaProduzione(mtbColt, () -> {
                synchronized (this.mtbColtsOfOrder) {
                    Optional<MtbColt> mtbColtToRemove = Stream.of(this.mtbColtsOfOrder.getValue())
                            .filter(x -> x.getNumCollo().equals(mtbColt.getNumCollo()) &&
                                    x.getSerCollo().equalsIgnoreCase(mtbColt.getSerCollo()) &&
                                    x.getDataColloD().compareTo(mtbColt.getDataColloD()) == 0 &&
                                    x.getGestione().equalsIgnoreCase(mtbColt.getGestione()))
                            .findFirst();

                    if (mtbColtToRemove.isPresent()) {
                        this.mtbColtsOfOrder.getValue().remove(mtbColtToRemove.get());
                        this.mtbColtsOfOrder.postValue(this.mtbColtsOfOrder.getValue());
                    }

                }

                this.sendOnLoadingEnded();
            }, this::sendError);
        }).start();
    }

    public void setListener(Listener listener) {
        this.mListener = listener;
    }


    private void sendOnLoadingStarted() {
        if (this.mListener != null) mListener.onLoadingStarted();
    }

    private void sendOnLoadingEnded() {
        if (this.mListener != null) mListener.onLoadingEnded();
    }

    private void sendError(Exception ex) {
        if (this.mListener != null) mListener.onError(ex);
    }

    public interface Listener extends ILoadingListener {

        void onDataSaved();

        void onError(Exception ex);

    }
}
