package it.integry.integrywmsnative.core.model;

import android.text.TextUtils;

import androidx.databinding.ObservableArrayList;

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

import org.jetbrains.annotations.Nullable;

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

import it.integry.integrywmsnative.core.model.dto.InternalCodAnagsDTO;
import it.integry.integrywmsnative.core.model.secondary.GestioneEnum;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityDB;
import it.integry.integrywmsnative.core.utility.UtilityDate;
import it.integry.integrywmsnative.core.utility.UtilityLogger;
import it.integry.integrywmsnative.core.utility.UtilityString;

/**
 * Created by GiuseppeS on 06/03/2018.
 */

public class MtbColt extends EntityBase {
    private String gestione;
    private String dataCollo;
    private String serCollo;
    private Integer numCollo;
    private String rifOrd;
    private String codAnag;
    private String codVdes;
    private String codMdep;
    private String codVlis;
    private String codDtip;
    private String codTcol;
    private String serDoc;
    private String filtroOrdini;
    private String preparatoDa;
    private String annotazioni;
    private String posizione;
    private String codDtipProvv;
    private String serDocProvv;
    private String codJfas;
    private String dataOrd;
    private String dataDoc;
    private String oraInizPrep;
    private String oraFinePrep;
    private String dataDocProvv;
    private String dataVers;
    private Integer segno;
    private Integer numOrd;
    private Integer numDoc;
    private Integer numDocProvv;
    private BigDecimal pesoKg;
    private BigDecimal pesoNettoKg;
    private BigDecimal lunghezzaCm;
    private BigDecimal larghezzaCm;
    private BigDecimal altezzaCm;
    private String codJcom;

    private List<MtbCols> mtbCols;
    private MtbTCol mtbTCol;

    private Boolean disablePrint;
    private String ragSocCliente;

    public void generaFiltroOrdine() throws Exception {

        if (this.gestione == null) {
            throw new Exception("Impossibile creare il filtro dell'ordine se la gestione non è valorizzata");
        }

        if (this.dataOrd == null) {
            throw new Exception("Impossibile creare il filtro dell'ordine se la data dell'ordine non è valorizzata");
        }

        if (this.numOrd == null) {
            throw new Exception("Impossibile creare il filtro dell'ordine se il numero dell'ordine non è valorizzato");
        }


        Date dateOrd = UtilityDate.recognizeDate(this.dataOrd);
        String dateYMD = UtilityDate.formatDate(dateOrd, UtilityDate.COMMONS_DATE_FORMATS.YMD_SLASH);

        this.filtroOrdini = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ROOT><FILTER><DTB_ORDT><GESTIONE type=\"V\">" + this.gestione + "</GESTIONE><DATA_ORD type=\"D\">" + dateYMD + "</DATA_ORD><NUM_ORD type=\"N\">" + this.numOrd + "</NUM_ORD></DTB_ORDT></FILTER></ROOT>";
    }


    private ObservableArrayList<MtbColr> mtbColr = new ObservableArrayList<>();

    public ObservableArrayList<MtbColr> getMtbColr() {
        return mtbColr == null ? new ObservableArrayList<>() : mtbColr;
    }

    public MtbColt setMtbColr(ObservableArrayList<MtbColr> mtbColr) {
        this.mtbColr = mtbColr;
        return this;
    }

    public MtbColt() {
        type = "mtb_colt";
        setDataCollo(UtilityDate.getDateInstance());
        setSerCollo("/");

        if (SettingsManager.i().isUserLoggedIn()) {
            setPreparatoDa(SettingsManager.i().getUser().getFullname());
        }
    }

    public MtbColt initDefaultFields(GestioneEnum gestioneEnum) {
        setGestione(gestioneEnum);
        setCodMdep(SettingsManager.i().getUserSession().getDepo().getCodMdep());
        setPreparatoDa(SettingsManager.i().getUser().getFullname());
        setOraInizPrep(UtilityDate.getDateInstance());

        String codAnagToUse = null;
        switch (gestioneEnum) {
            case ACQUISTO:
            case LAVORAZIONE:
            case PRODUZIONE:
                if (SettingsManager.iDB().getInternalCodAnags() == null) break;

                Optional<InternalCodAnagsDTO> optCodAnagForn = Stream.of(SettingsManager.iDB().getInternalCodAnags())
                        .filter(InternalCodAnagsDTO::isFornitore)
                        .findFirst();

                if (optCodAnagForn.isEmpty()) break;

                codAnagToUse = optCodAnagForn.get().getCodAnag();
                break;
            case VENDITA:
                if (SettingsManager.iDB().getInternalCodAnags() == null) break;

                Optional<InternalCodAnagsDTO> optCodAnagClie = Stream.of(SettingsManager.iDB().getInternalCodAnags())
                        .filter(InternalCodAnagsDTO::isCliente)
                        .findFirst();

                if (optCodAnagClie.isEmpty()) break;

                codAnagToUse = optCodAnagClie.get().getCodAnag();
                break;
        }

        setCodAnag(codAnagToUse);

        return this;
    }


    public String getGestione() {
        return gestione;
    }

    public GestioneEnum getGestioneEnum() {
        return GestioneEnum.fromString(gestione);
    }

    public MtbColt setGestione(String gestione) {
        this.gestione = gestione;
        return this;
    }

    public MtbColt setGestione(GestioneEnum gestione) {
        this.gestione = gestione.getText();
        return this;
    }

    public String getDataColloHumanLong() {
        Date dataColloD = null;
        try {
            dataColloD = getDataColloD();
        } catch (Exception ex) {
            UtilityLogger.errorMe(ex);
        }

        if (dataColloD != null) {
            return UtilityDate.formatDate(dataColloD, UtilityDate.COMMONS_DATE_FORMATS.DMY_HUMAN_LONG);
        } else return null;
    }

    public String getDataColloS() {
        return dataCollo;
    }

    public Date getDataColloD() {
        return UtilityDate.recognizeDateWithExceptionHandler(getDataColloS());
    }

    public MtbColt setDataCollo(String dataCollo) {
        this.dataCollo = dataCollo;
        return this;
    }

    public MtbColt setDataCollo(Date dataCollo) {
        this.dataCollo = UtilityDate.formatDate(dataCollo, UtilityDate.COMMONS_DATE_FORMATS.DMY_TIME_SLASH);
        return this;
    }

    public String getSerCollo() {
        return serCollo;
    }

    public MtbColt setSerCollo(String serCollo) {
        this.serCollo = serCollo;
        return this;
    }

    public Integer getNumCollo() {
        return numCollo;
    }

    public MtbColt setNumCollo(Integer numCollo) {
        this.numCollo = numCollo;
        return this;
    }

    public String getRifOrd() {
        return rifOrd;
    }

    public MtbColt setRifOrd(String rifOrd) {
        this.rifOrd = rifOrd;
        return this;
    }

    public String getCodAnag() {
        return codAnag;
    }

    public MtbColt setCodAnag(String codAnag) {
        this.codAnag = codAnag;
        return this;
    }

    public String getCodVdes() {
        return codVdes;
    }

    public MtbColt setCodVdes(String codVdes) {
        this.codVdes = codVdes;
        return this;
    }

    public String getCodMdep() {
        return codMdep;
    }

    public MtbColt setCodMdep(String codMdep) {
        this.codMdep = codMdep;
        return this;
    }

    public String getCodVlis() {
        return codVlis;
    }

    public MtbColt setCodVlis(String codVlis) {
        this.codVlis = codVlis;
        return this;
    }

    public String getCodDtip() {
        return codDtip;
    }

    public MtbColt setCodDtip(String codDtip) {
        this.codDtip = codDtip;
        return this;
    }

    public String getCodTcol() {
        return codTcol;
    }

    public MtbColt setCodTcol(String codTcol) {
        this.codTcol = codTcol;
        return this;
    }

    public String getSerDoc() {
        return serDoc;
    }

    public MtbColt setSerDoc(String serDoc) {
        this.serDoc = serDoc;
        return this;
    }

    public String getFiltroOrdini() {
        return filtroOrdini;
    }

    public MtbColt setFiltroOrdini(String filtroOrdini) {
        this.filtroOrdini = filtroOrdini;
        return this;
    }

    public String getPreparatoDa() {
        return preparatoDa;
    }

    public MtbColt setPreparatoDa(String preparatoDa) {
        this.preparatoDa = preparatoDa;
        return this;
    }

    public String getAnnotazioni() {
        return annotazioni;
    }

    public MtbColt setAnnotazioni(String annotazioni) {
        this.annotazioni = annotazioni;
        return this;
    }

    public String getPosizione() {
        return posizione;
    }

    public MtbColt setPosizione(@Nullable String posizione) {
        this.posizione = posizione;
        return this;
    }

    public String getCodDtipProvv() {
        return codDtipProvv;
    }

    public MtbColt setCodDtipProvv(String codDtipProvv) {
        this.codDtipProvv = codDtipProvv;
        return this;
    }

    public String getSerDocProvv() {
        return serDocProvv;
    }

    public MtbColt setSerDocProvv(String serDocProvv) {
        this.serDocProvv = serDocProvv;
        return this;
    }

    public String getCodJfas() {
        return codJfas;
    }

    public MtbColt setCodJfas(String codJfas) {
        this.codJfas = codJfas;
        return this;
    }

    public Date getDataOrdD() {
        return UtilityDate.recognizeDateWithExceptionHandler(getDataOrd());
    }

    public String getDataOrd() {
        return dataOrd;
    }

    public MtbColt setDataOrd(String dataOrd) {
        this.dataOrd = dataOrd;
        return this;
    }

    public MtbColt setDataOrdD(Date dataOrd) {
        this.dataOrd = UtilityDate.formatDate(dataOrd, UtilityDate.COMMONS_DATE_FORMATS.DMY_TIME_SLASH);
        return this;
    }

    public String getDataDoc() {
        return dataDoc;
    }

    public MtbColt setDataDoc(String dataDoc) {
        this.dataDoc = dataDoc;
        return this;
    }

    public String getOraInizPrep() {
        return oraInizPrep;
    }

    public MtbColt setOraInizPrep(String oraInizPrep) {
        this.oraInizPrep = oraInizPrep;
        return this;
    }

    public MtbColt setOraInizPrep(Date oraInizPrep) {
        this.oraInizPrep = UtilityDate.formatDate(oraInizPrep, UtilityDate.COMMONS_DATE_FORMATS.DMY_TIME_SLASH);
        return this;
    }

    public String getOraFinePrep() {
        return oraFinePrep;
    }

    public MtbColt setOraFinePrep(String oraFinePrep) {
        this.oraFinePrep = oraFinePrep;
        return this;
    }

    public MtbColt setOraFinePrep(Date oraFinePrep) {
        this.oraFinePrep = UtilityDate.formatDate(oraFinePrep, UtilityDate.COMMONS_DATE_FORMATS.DMY_TIME_SLASH);
        return this;
    }

    public String getDataDocProvv() {
        return dataDocProvv;
    }

    public MtbColt setDataDocProvv(String dataDocProvv) {
        this.dataDocProvv = dataDocProvv;
        return this;
    }

    public String getDataVers() {
        return dataVers;
    }

    public Date getDataVersD() {
        return UtilityDate.recognizeDateWithExceptionHandler(getDataVers());
    }

    public String getTimeVers() {
        Date dataColloD = getDataVersD();

        if (dataColloD != null) {
            return UtilityDate.formatDate(dataColloD, UtilityDate.COMMONS_DATE_FORMATS.TIME);
        } else return null;
    }


    public MtbColt setDataVers(String dataVers) {
        this.dataVers = dataVers;
        return this;
    }

    public MtbColt setDataVers(Date dataVers) {
        this.dataVers = UtilityDate.formatDate(dataVers, UtilityDate.COMMONS_DATE_FORMATS.DMY_TIME_SLASH);
        return this;
    }

    public Integer getSegno() {
        return segno;
    }

    public MtbColt setSegno(Integer segno) {
        this.segno = segno;
        return this;
    }

    public Integer getNumOrd() {
        return numOrd;
    }

    public MtbColt setNumOrd(Integer numOrd) {
        this.numOrd = numOrd;
        return this;
    }

    public Integer getNumDoc() {
        return numDoc;
    }

    public MtbColt setNumDoc(Integer numDoc) {
        this.numDoc = numDoc;
        return this;
    }

    public Integer getNumDocProvv() {
        return numDocProvv;
    }

    public MtbColt setNumDocProvv(Integer numDocProvv) {
        this.numDocProvv = numDocProvv;
        return this;
    }

    public BigDecimal getPesoKg() {
        return pesoKg;
    }

    public MtbColt setPesoKg(BigDecimal pesoKg) {
        this.pesoKg = pesoKg;
        return this;
    }

    public BigDecimal getPesoNettoKg() {
        return pesoNettoKg;
    }

    public MtbColt setPesoNettoKg(BigDecimal pesoNettoKg) {
        this.pesoNettoKg = pesoNettoKg;
        return this;
    }

    public BigDecimal getLunghezzaCm() {
        return lunghezzaCm;
    }

    public MtbColt setLunghezzaCm(BigDecimal lunghezzaCm) {
        this.lunghezzaCm = lunghezzaCm;
        return this;
    }

    public BigDecimal getLarghezzaCm() {
        return larghezzaCm;
    }

    public MtbColt setLarghezzaCm(BigDecimal larghezzaCm) {
        this.larghezzaCm = larghezzaCm;
        return this;
    }

    public BigDecimal getAltezzaCm() {
        return altezzaCm;
    }

    public MtbColt setAltezzaCm(BigDecimal altezzaCm) {
        this.altezzaCm = altezzaCm;
        return this;
    }


    public List<MtbCols> getMtbCols() {
        return mtbCols;
    }

    public MtbColt setMtbCols(List<MtbCols> mtbCols) {
        this.mtbCols = mtbCols;
        return this;
    }

    public Boolean getDisablePrint() {
        return disablePrint == null ? false : disablePrint;
    }

    public MtbColt setDisablePrint(Boolean disablePrint) {
        this.disablePrint = disablePrint;
        return this;
    }

    public String getRagSocCliente() {
        return ragSocCliente;
    }

    public MtbColt setRagSocCliente(String ragSocCliente) {
        this.ragSocCliente = ragSocCliente;
        return this;
    }

    public String getCodJcom() {
        return codJcom;
    }

    public MtbColt setCodJcom(String codJcom) {
        this.codJcom = codJcom;
        return this;
    }

    public MtbTCol getMtbTCol() {
        return mtbTCol;
    }

    public MtbColt setMtbTCol(MtbTCol mtbTCol) {
        this.mtbTCol = mtbTCol;
        return this;
    }

    public void generaFiltroOrdineFromDTO(List<FiltroOrdineDTO> filtroOrdineDtos) {

        String xmlPrefix = "{\"whereCond\": \"";
        String xmlSuffix = "\"}";

//        StringBuilder whereCond = new StringBuilder();
        String whereCond;
        List<String> conditions = new ArrayList<>();
        String existingFilter;
        if (this.filtroOrdini != null) {
            existingFilter = this.filtroOrdini;
            existingFilter = existingFilter.replace(xmlPrefix, "").replace(xmlSuffix, "");
            conditions.add(existingFilter);
        } else {
            existingFilter = "";
        }


        for (FiltroOrdineDTO filtroOrdineDTO : filtroOrdineDtos) {
            try {
                String condition = (String.format("(d.g = %s AND d.d = %s and d.n = %s",
                        UtilityDB.valueToString(filtroOrdineDTO.getGestioneOrd()),
                        UtilityDB.valueToString(UtilityDate.formatDate(filtroOrdineDTO.getDataOrdD(), UtilityDate.COMMONS_DATE_FORMATS.YMD_SLASH)),
                        UtilityDB.valueToString(filtroOrdineDTO.getNumOrd())));

                if (!UtilityString.isNullOrEmpty(filtroOrdineDTO.getDataConsS())) {
                    condition += (String.format(" AND dr.dc = %s",
                            UtilityDB.valueToString(UtilityDate.formatDate(filtroOrdineDTO.getDataConsD(), UtilityDate.COMMONS_DATE_FORMATS.YMD_SLASH))));
                }

                condition += ")";
                if (!existingFilter.contains(condition)) {
                    conditions.add(condition);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /*if (filtroOrdineDtos != null && filtroOrdineDtos.size() > 0) {

            for (int i = 0; i < filtroOrdineDtos.size(); i++) {
                FiltroOrdineDTO x = filtroOrdineDtos.get(i);

                try {
                    whereCond.append("(");
                    whereCond.append(String.format("d.g = %s AND d.d = %s and d.n = %s",
                            UtilityDB.valueToString(x.getGestioneOrd()),
                            UtilityDB.valueToString(UtilityDate.formatDate(x.getDataOrdD(), UtilityDate.COMMONS_DATE_FORMATS.YMD_SLASH)),
                            UtilityDB.valueToString(x.getNumOrd())));

                    if (!UtilityString.isNullOrEmpty(x.getDataConsS())) {
                        whereCond.append(String.format(" AND dr.dc = %s",
                                UtilityDB.valueToString(UtilityDate.formatDate(x.getDataConsD(), UtilityDate.COMMONS_DATE_FORMATS.YMD_SLASH))));
                    }

                    whereCond.append(")");
                    if (i < filtroOrdineDtos.size() - 1) {
                        whereCond.append(" OR ");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }*/
        whereCond = TextUtils.join(" OR ", conditions);

        this.filtroOrdini = xmlPrefix + whereCond + xmlSuffix;
    }


    public boolean isDocumentPresent() {
        return this.getNumDoc() != null && this.getDataDoc() != null && this.getSerDoc() != null;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MtbColt mtbColt = (MtbColt) o;

        if (!gestione.equals(mtbColt.gestione)) return false;
        if (!dataCollo.equals(mtbColt.dataCollo)) return false;
        if (!serCollo.equals(mtbColt.serCollo)) return false;
        return numCollo.equals(mtbColt.numCollo);
    }

    @Override
    public int hashCode() {
        int result = gestione.hashCode();
        result = 31 * result + dataCollo.hashCode();
        result = 31 * result + serCollo.hashCode();
        result = 31 * result + numCollo.hashCode();
        return result;
    }


    @Override
    public EntityBase clone() {
        MtbColt mtbColt = (MtbColt) super.clone();
        mtbColt.setMtbColr((ObservableArrayList<MtbColr>) mtbColt.getMtbColr().clone());
        return mtbColt;
    }
}
