package it.integry.integrywmsnative.gest.contab_doc_interni;

import androidx.lifecycle.MutableLiveData;

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

import javax.inject.Inject;

import it.integry.integrywmsnative.core.data_store.db.entity.SqlMtbColt;
import it.integry.integrywmsnative.core.data_store.db.repository.MtbColtRepository;
import it.integry.integrywmsnative.core.data_store.db.wrappers.DocInternoWrapper;
import it.integry.integrywmsnative.core.di.BindableInteger;
import it.integry.integrywmsnative.core.exception.NoDocTypeSelectedException;
import it.integry.integrywmsnative.core.interfaces.viewmodel_listeners.ILoadingListener;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.DialogSelectDocInfoViewModel;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.DocInterniSetupDTO;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.FornitoreDTO;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.GrigliaArticoliDTO;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.GruppiArticoloDTO;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.TipiDocDTO;
import it.integry.integrywmsnative.gest.contab_doc_interni.rest.DocInterniRESTConsumer;

public class DocInterniViewModel {

    @Inject
    MtbColtRepository documentRepository;
    private Listener mListener;
    private final DocInterniRESTConsumer mDocInterniRESTConsumer;
    private boolean productsFetched = true;
    private boolean docsFetched = true;
    private int nextNumCollo = 0;
    private GrigliaArticoliDTO productsList;
    private final MutableLiveData<List<DocInternoWrapper>> mDocsList = new MutableLiveData<>();

    public final MutableLiveData<TipiDocDTO> dtbTipi = new MutableLiveData<>();
    public final MutableLiveData<GruppiArticoloDTO> mtbGrup = new MutableLiveData<>();
    public final MutableLiveData<FornitoreDTO> fornitore = new MutableLiveData<>();
    public final MutableLiveData<Date> dataDoc = new MutableLiveData<>();
    public final MutableLiveData<String> numDoc = new MutableLiveData<>();
    public final MutableLiveData<String> note = new MutableLiveData<>();
    public final BindableInteger artsSize = new BindableInteger(0);

    @Inject
    public DocInterniViewModel(DocInterniRESTConsumer docInterniRESTConsumer, MtbColtRepository documentRepository) {
        mDocInterniRESTConsumer = docInterniRESTConsumer;
        this.documentRepository = documentRepository;
        this.mDocsList.setValue(new ArrayList<>());
    }


    public void init() {
        this.sendOnLoadingStarted();
//        new Thread(() -> {
        mDocInterniRESTConsumer.getDocInterniSetup(returnDto -> {
            this.sendOnLoadingEnded();
            this.mListener.onDocInterniSetupFetched(returnDto);
        }, this::sendError);
//        }).start();
    }

    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 DocInterniViewModel setListeners(Listener listener) {
        this.mListener = listener;
        return this;
    }

    public MutableLiveData<List<DocInternoWrapper>> getDocsList() {
        return mDocsList;
    }

    public void setSelectedDocDetails(DialogSelectDocInfoViewModel selection) {

        this.fornitore.postValue(selection.getSelectedFornitore());
        this.mtbGrup.postValue(selection.getSelectedGruppoArt());
        this.dataDoc.postValue(selection.getDataDoc());
        this.numDoc.postValue(selection.getNumDoc());
        this.note.postValue(selection.getNote());

        if (selection.getSelectedTipoDoc() != null) {
            this.dtbTipi.postValue(selection.getSelectedTipoDoc());
        }
    }

    public void fetchProducts() {
        this.productsFetched = false;
        this.sendOnLoadingStarted();
        mDocInterniRESTConsumer.fetchProducts(this.getCodDtip(), this.getCodMgrp(), returnDto -> {
            this.productsFetched = true;
            this.productsList = returnDto;
            this.artsSize.set(returnDto.getGrigliaAcquistiChild().size());
            if (this.docsFetched) {
                this.sendOnLoadingEnded();
            }
        }, this::sendError);
    }

    public void fetchDocuments() {
        this.docsFetched = false;
        this.sendOnLoadingStarted();
        String codAnag = null, codVdes = null;
        FornitoreDTO fornitore = this.fornitore.getValue();
        if (fornitore != null) {
            codAnag = fornitore.getCodAnag();
            codVdes = fornitore.getCodVdes();
        }
        documentRepository.getLocalDocumentsByCodDtip(this.getCodDtip(), codAnag, codVdes, dataDoc.getValue(), numDoc.getValue(), list -> {
            documentRepository.getNextNumCollo(nextNumCollo -> {
                this.mDocsList.postValue(list);
                this.setNextNumCollo(nextNumCollo);
                this.docsFetched = true;
                if (this.productsFetched) {
                    this.sendOnLoadingEnded();
                }
            }, this::sendError);
        }, this::sendError);
    }

    private void setNextNumCollo(Integer nextNumCollo) {
        this.nextNumCollo = nextNumCollo;
    }

    private String getCodDtip() {
        if (this.dtbTipi.getValue() == null) {
            return null;
        }
        return this.dtbTipi.getValue().getCodDtip();
    }

    public TipiDocDTO getTipoDoc() {
        if (this.dtbTipi.getValue() == null) {
            return null;
        }
        return this.dtbTipi.getValue();
    }

    private String getCodMgrp() {
        if (this.mtbGrup.getValue() == null) {
            return null;
        }
        return this.mtbGrup.getValue().getCodMgrp();
    }

    public void editDocument(SqlMtbColt document) {
        this.mListener.onDocumentEditRequest(document, productsList);
    }

    public void newDocument() {
        SqlMtbColt document = new SqlMtbColt();
        if (this.dtbTipi.getValue() == null) {
            this.sendError(new NoDocTypeSelectedException());
            return;
        }
        document.setCodDtipProvv(this.getCodDtip());
        document.setCodMgrp(this.getCodMgrp());
        document.setDataCollo(new Date());
        document.setCodMdep(SettingsManager.i().getUserSession().getDepo().getCodMdep());
        document.setAnnotazioni(this.note.getValue());
        document.setSegno(-1);
        document.setSerCollo("/");
        document.setNumCollo(this.nextNumCollo);
        document.setGestione("L");
        document.setDataDoc(this.dataDoc.getValue());
        if (this.numDoc.getValue() != null) {
            document.setNumDoc(Integer.parseInt(this.numDoc.getValue()));
        }
        if (this.fornitore.getValue() != null) {
            document.setCodAnag(this.fornitore.getValue().getCodAnag());
            document.setCodVdes(this.fornitore.getValue().getCodVdes());
        }
        documentRepository.insert(document, id -> {
            document.setId(id);
            this.editDocument(document);
        }, this::sendError);
    }

    public boolean hasDocDetails() {
        return this.dtbTipi.getValue() != null;
    }

    public interface Listener extends ILoadingListener {

        void onError(Exception ex);

        void onDocInterniSetupFetched(DocInterniSetupDTO docInterniSetupDTO);

        void onDocDetailsChanged(DialogSelectDocInfoViewModel selection);

        void onDocumentEditRequest(SqlMtbColt document, GrigliaArticoliDTO arts);

    }

}
