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

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ObservableField;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.MutableLiveData;
import androidx.recyclerview.widget.LinearLayoutManager;

import com.annimon.stream.Stream;
import com.google.gson.reflect.TypeToken;

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

import javax.inject.Inject;

import it.integry.integrywmsnative.MainApplication;
import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.core.expansion.AtomicBigDecimal;
import it.integry.integrywmsnative.core.expansion.BaseFragment;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.DtbOrdSteps;
import it.integry.integrywmsnative.core.model.MtbColr;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.rest.consumers.ArticoloRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers.SystemRESTConsumer;
import it.integry.integrywmsnative.core.utility.UtilityDB;
import it.integry.integrywmsnative.databinding.FragmentProdRientroMerceOrderDetailBinding;
import it.integry.integrywmsnative.gest.prod_versamento_materiale.dto.OrdineLavorazioneDTO;
import it.integry.integrywmsnative.ui.SimpleDividerItemDecoration;
import it.integry.integrywmsnative.view.dialogs.input_lu_prod.DialogInputLUProdDTO;
import it.integry.integrywmsnative.view.dialogs.input_lu_prod.DialogInputLUProdView;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link ProdRientroMerceOrderDetailFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class ProdRientroMerceOrderDetailFragment extends BaseFragment implements ProdRientroMerceOrderDetailViewModel.Listener {


    public final MutableLiveData<OrdineLavorazioneDTO> currentOrder = new MutableLiveData<>();

    @Inject
    ArticoloRESTConsumer mArticoloRESTConsumer;

    @Inject
    SystemRESTConsumer mSystemRESTConsumer;

    @Inject
    ProdRientroMerceOrderDetailViewModel mViewModel;

    private FragmentProdRientroMerceOrderDetailBinding mBindings;
    private ProdRientroMerceOrderDetailMtbColtListAdapter mAdapter;

    private RunnableArgs<MtbColt> onMtbColtClicked;


    public ObservableField<BigDecimal> sumLUNumber = new ObservableField<>(BigDecimal.ZERO);
    public ObservableField<BigDecimal> sumColliNumber = new ObservableField<>(BigDecimal.ZERO);
    public ObservableField<BigDecimal> sumNetKG = new ObservableField<>(BigDecimal.ZERO);
    public ObservableField<BigDecimal> sumGrossKG = new ObservableField<>(BigDecimal.ZERO);

    public ProdRientroMerceOrderDetailFragment() {
        // Required empty public constructor
    }

    public static ProdRientroMerceOrderDetailFragment newInstance() {
        return new ProdRientroMerceOrderDetailFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        mBindings = DataBindingUtil.inflate(LayoutInflater.from(getActivity()), R.layout.fragment_prod_rientro_merce_order_detail, container, false);
        mBindings.setLifecycleOwner(this);

        mBindings.setView(this);

        MainApplication.appComponent
                .prodRientroMerceOrderDetailComponent()
                .create()
                .inject(this);

        mViewModel.setListener(this);

        this.mViewModel.mtbColtsOfOrder.observe(getViewLifecycleOwner(), this::refreshList);

        this.initRecyclerView();

        return mBindings.getRoot();
    }

    private void initRecyclerView() {
        mBindings.mainList.setNestedScrollingEnabled(false);
        mBindings.mainList.setHasFixedSize(true);
        mBindings.mainList.setLayoutManager(new LinearLayoutManager(getActivity()));

        SimpleDividerItemDecoration itemDecorator = new SimpleDividerItemDecoration(getActivity(), SimpleDividerItemDecoration.VERTICAL);
        itemDecorator.setDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.divider));
        mBindings.mainList.addItemDecoration(itemDecorator);

        mAdapter = new ProdRientroMerceOrderDetailMtbColtListAdapter(new ObservableArrayList<>());
        mAdapter.setEmptyView(mBindings.mtbColtEmptyView);

        mBindings.mainList.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(item -> {
            if(this.onMtbColtClicked != null) this.onMtbColtClicked.run(item);
        });
    }

    public void setOrder(OrdineLavorazioneDTO order) {
        currentOrder.postValue(order);
        mBindings.invalidateAll();
        mAdapter.clearDataset();

        mViewModel.setOrder(order);
    }

    private void refreshList(List<MtbColt> mtbColts) {
        if(mtbColts != null) {
            sumLUNumber.set(new BigDecimal(mtbColts.size()));

            AtomicBigDecimal sumColli = new AtomicBigDecimal(BigDecimal.ZERO);
            AtomicBigDecimal sumNet = new AtomicBigDecimal(BigDecimal.ZERO);
            AtomicBigDecimal sumGross = new AtomicBigDecimal(BigDecimal.ZERO);

            Stream.of(mtbColts)
                    .forEach(x -> Stream.of(x.getMtbColr()).forEach(y -> {
                        sumColli.getAndAdd(y.getNumCnf());
                        sumNet.getAndAdd(y.getPesoNettoKg());
                        sumGross.getAndAdd(y.getPesoLordoKg());
                    }));
            sumColliNumber.set(sumColli.get());
            sumGrossKG.set(sumGross.get());
            sumNetKG.set(sumNet.get());
        } else {
            sumLUNumber.set(BigDecimal.ZERO);
            sumColliNumber.set(BigDecimal.ZERO);
            sumGrossKG.set(BigDecimal.ZERO);
            sumNetKG.set(BigDecimal.ZERO);
        }

        mAdapter.updateDataset(mtbColts);
    }

    @Override
    public void onDataSaved() {

    }


    public void addULButtonClick() {
        this.openProgress();

        String codProd = this.currentOrder.getValue().getCodProd();
        mArticoloRESTConsumer.getByCodMart(codProd, mtbAart -> {

            String sql = "SELECT TOP 1 * " +
                    "FROM ( " +
                    "         SELECT MAX(id_step) OVER ( PARTITION BY gestione, num_ord, data_ord) as last_step, " +
                    "                * " +
                    "         FROM dtb_ord_steps " +
                    "         WHERE cod_jfas IS NOT NULL " +
                    "           AND gestione = " + UtilityDB.valueToString(this.currentOrder.getValue().getGestione()) +
                    "           AND num_ord = " + UtilityDB.valueToString(this.currentOrder.getValue().getNumOrd()) +
                    "           AND data_ord = " + UtilityDB.valueToString(this.currentOrder.getValue().getDataOrdD()) +
                    "     ) tmp " +
                    "WHERE data_iniz IS NOT NULL " +
                    "  AND (data_fine IS NULL OR last_step = id_step) " +
                    "ORDER BY id_step DESC";

            mSystemRESTConsumer.<List<DtbOrdSteps>>processSql(sql, new TypeToken<ArrayList<DtbOrdSteps>>() {}.getType(), dtbOrdStep -> {

                this.closeProgress();

                DialogInputLUProdDTO dialogInputLUProdDTO = new DialogInputLUProdDTO()
                        .setMtbAart(mtbAart)
                        .setNumCnf(this.currentOrder.getValue().getColliPedana())
                        .setQtaCnf(mtbAart.getQtaCnf())
                        .setQtaTot(this.currentOrder.getValue().getColliPedana().multiply(mtbAart.getQtaCnf()))
                        .setPartitaMag(this.currentOrder.getValue().getPartitaMag())
                        .setDataScad(this.currentOrder.getValue().getDataScadD())
                        .setCodJfasParent(this.currentOrder.getValue().getCodJfas())
                        .setCodTcol(this.currentOrder.getValue().getCodTcolUl())
                        .setSuggestedCodJfas(dtbOrdStep != null && dtbOrdStep.size() > 0 ? dtbOrdStep.get(0).getCodJfas() : null);


                DialogInputLUProdView
                        .newInstance(dialogInputLUProdDTO, resultDTO -> {
                            ProdRientroMerceOrderDetailPickedQuantityDTO pickedQuantityDTO = new ProdRientroMerceOrderDetailPickedQuantityDTO()
                                    .setNumCnf(resultDTO.getNumCnf())
                                    .setPesoCollo(resultDTO.getPesoCollo())
                                    .setPesoNetto(resultDTO.getPesoNetto())
                                    .setTaraPed(resultDTO.getTaraPed())
                                    .setTaraCol(resultDTO.getTaraCol())
                                    .setPesoLordo(resultDTO.getPesoLordo())
                                    .setMtbTCol(resultDTO.getMtbTCol())
                                    .setJtbFasi(resultDTO.getJtbFasi());

                            this.mViewModel.createLU(pickedQuantityDTO);
                        }, () -> {
                            this.closeProgress();
                        })
                        .show(getActivity().getSupportFragmentManager(), "tag");

            }, this::onError);

        }, this::onError);
    }

    public ProdRientroMerceOrderDetailFragment setOnMtbColtClicked(RunnableArgs<MtbColt> onMtbColtClicked) {
        this.onMtbColtClicked = onMtbColtClicked;
        return this;
    }

    public void editMtbColr(MtbColr mtbColr) {

    }

    public void deleteMtbColr(MtbColr mtbColr) {
        MtbColt mtbColt = new MtbColt()
                .setGestione(mtbColr.getGestione())
                .setDataCollo(mtbColr.getDataColloS())
                .setSerCollo(mtbColr.getSerCollo())
                .setNumCollo(mtbColr.getNumCollo());

        this.mViewModel.deleteLU(mtbColt);
    }

    public Drawable getOrderStatusIcon() {
        if (currentOrder.getValue() != null) {
            switch (currentOrder.getValue().getStatoEnum()) {
                case IN_CORSO:
                    return ContextCompat.getDrawable(getActivity(), R.drawable.ic_play_circle_filled_24dp);
                case PAUSA:
                    return ContextCompat.getDrawable(getActivity(), R.drawable.ic_pause_circle_filled_24dp);
                case PROGRAMMATO:
                default:
                    return ContextCompat.getDrawable(getActivity(), R.drawable.ic_clock_circle_outline_24dp);
            }
        }
        else
            return ContextCompat.getDrawable(getActivity(), R.drawable.ic_clock_circle_outline_24dp);
    }

    public Integer getOrderStatusIconTintColor() {
        if (currentOrder.getValue() != null) {
            switch (currentOrder.getValue().getStatoEnum()) {
                case IN_CORSO:
                    return ContextCompat.getColor(getActivity(), R.color.green_800);
                case PAUSA:
                    return ContextCompat.getColor(getActivity(), R.color.yellow_800);
                case PROGRAMMATO:
                default:
                    return ContextCompat.getColor(getActivity(), R.color.blue_800);
            }
        }
        else
            return ContextCompat.getColor(getActivity(), R.color.blue_800);
    }

    public Drawable getOrderStatusLabelBackgroud() {
        if (currentOrder.getValue() != null) {
            switch (currentOrder.getValue().getStatoEnum()) {
                case IN_CORSO:
                    return ContextCompat.getDrawable(getActivity(), R.drawable.label_success_text);
                case PAUSA:
                    return ContextCompat.getDrawable(getActivity(), R.drawable.label_warning_text);
                case PROGRAMMATO:
                default:
                    return ContextCompat.getDrawable(getActivity(), R.drawable.label_primary_text);
            }
        }
        else
            return ContextCompat.getDrawable(getActivity(), R.drawable.label_primary_text);
    }

    public Integer getOrderStatusLabelTextColor() {
        if (currentOrder.getValue() != null) {
            switch (currentOrder.getValue().getStatoEnum()) {
                case IN_CORSO:
                    return ContextCompat.getColor(getActivity(), R.color.green_800);
                case PAUSA:
                    return ContextCompat.getColor(getActivity(), R.color.yellow_800);
                case PROGRAMMATO:
                default:
                    return ContextCompat.getColor(getActivity(), R.color.blue_800);
            }
        }
        else
            return ContextCompat.getColor(getActivity(), R.color.blue_800);
    }
}