package it.integry.integrywmsnative.gest.prod_recupero_materiale;


import android.content.Context;
import android.os.Bundle;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.appcompat.widget.AppCompatTextView;
import androidx.databinding.ObservableArrayList;
import androidx.fragment.app.Fragment;

import com.annimon.stream.Stream;

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

import javax.inject.Inject;

import it.integry.barcode_base_android_library.model.BarcodeScanDTO;
import it.integry.integrywmsnative.MainApplication;
import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.core.barcode_reader.BarcodeCallbackDTO;
import it.integry.integrywmsnative.core.barcode_reader.BarcodeManager;
import it.integry.integrywmsnative.core.expansion.BaseFragment;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.expansion.RunnableArgss;
import it.integry.integrywmsnative.core.interfaces.IScrollableFragment;
import it.integry.integrywmsnative.core.interfaces.ITitledFragment;
import it.integry.integrywmsnative.core.model.MtbAart;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.databinding.FragmentProdRecuperoMaterialeBinding;
import it.integry.integrywmsnative.gest.prod_recupero_materiale.dto.HistoryVersamentoProdULDTO;
import it.integry.integrywmsnative.gest.prod_recupero_materiale.ui.HistoryULsListAdapter;
import it.integry.integrywmsnative.gest.prod_recupero_materiale.ui.HistoryULsListModel;
import it.integry.integrywmsnative.gest.spedizione.model.PickedQuantityDTO;
import it.integry.integrywmsnative.view.dialogs.DialogCommon;
import it.integry.integrywmsnative.view.dialogs.base.DialogSimpleMessageView;
import it.integry.integrywmsnative.view.dialogs.input_quantity_v2.DialogInputQuantityV2DTO;
import it.integry.integrywmsnative.view.dialogs.input_quantity_v2.DialogInputQuantityV2View;
import it.integry.integrywmsnative.view.dialogs.scan_or_create_lu.DialogScanOrCreateLUView;

/**
 * A simple {@link Fragment} subclass.
 */
public class ProdRecuperoMaterialeFragment extends BaseFragment implements ITitledFragment, IScrollableFragment, ProdRecuperoMaterialeViewModel.Listener {

    @Inject
    ProdRecuperoMaterialeViewModel mViewModel;

    @Inject
    DialogInputQuantityV2View mDialogInputQuantityV2View;

    private FragmentProdRecuperoMaterialeBinding mBinding;

    private int barcodeScannerIstanceID = -1;
    private String codJfas;
    private String fragmentResultKeyString;

    private final ObservableArrayList<HistoryULsListModel> mHistoryULMutableData = new ObservableArrayList<>();

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

    public static ProdRecuperoMaterialeFragment newInstance() {
        return newInstance(null, null);
    }

    public static ProdRecuperoMaterialeFragment newInstance(String codJfas, String keyString) {
        ProdRecuperoMaterialeFragment fragment = new ProdRecuperoMaterialeFragment();
        if (keyString != null) {
            fragment.setFragmentResultKeyString(keyString);
        }
        fragment.setCodJfas(codJfas);
        return fragment;
    }

    public static ProdRecuperoMaterialeFragment newInstance(String codJfas) {
        return newInstance(codJfas, null);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        mBinding = FragmentProdRecuperoMaterialeBinding.inflate(inflater, container, false);

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

        mViewModel.setListener(this);

        mBinding.setLifecycleOwner(getViewLifecycleOwner());
        mBinding.setView(this);

        this.initBarcodeReader();
        this.initRecyclerView();

        this.addOnPreDestroy(() -> {
            if (!UtilityString.isNullOrEmpty(fragmentResultKeyString)) {
                Bundle result = new Bundle();
                result.putString(fragmentResultKeyString, "result");
                getParentFragmentManager().setFragmentResult(fragmentResultKeyString, result);
            }
        });

        return mBinding.getRoot();
    }


    @Override
    public void onStart() {
        super.onStart();
        this.addOnPreDestroy(() -> {
            if (barcodeScannerIstanceID > -1) {
                BarcodeManager.removeCallback(barcodeScannerIstanceID);
            }
        });
        mViewModel.init(codJfas);
    }


    @Override
    public void onCreateActionBar(AppCompatTextView titleText, Context context) {
        titleText.setText(context.getText(R.string.prod_recupero_materiale_title_fragment).toString());
    }


    private void initBarcodeReader() {
        barcodeScannerIstanceID = BarcodeManager.addCallback(new BarcodeCallbackDTO()
                .setOnScanSuccessful(onScanSuccessful)
                .setOnScanFailed(this::onError));

        BarcodeManager.enable();
    }

    public String getCodJfas() {
        return codJfas;
    }

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

    public String getFragmentResultKeyString() {
        return fragmentResultKeyString;
    }

    public ProdRecuperoMaterialeFragment setFragmentResultKeyString(String fragmentResultKeyString) {
        this.fragmentResultKeyString = fragmentResultKeyString;
        return this;
    }

    private final RunnableArgs<BarcodeScanDTO> onScanSuccessful = data -> {
        this.onLoadingStarted();

        this.mViewModel.processBarcodeDTO(data);
    };

    private void initRecyclerView() {
        this.mViewModel.getOrderList().observe(getViewLifecycleOwner(), this::refreshList);

        HistoryULsListAdapter adapter = new HistoryULsListAdapter(getActivity(), mHistoryULMutableData)
                .setOnItemClicked(data -> this.mViewModel.dispatchItem(data.getOriginalModel(), null));

        adapter.setEmptyView(mBinding.emptyView);

        mBinding.prodRecuperoMaterialeMainList.setAdapter(adapter);

        if (mToolbar != null)
            mToolbar.setRecyclerView(mBinding.prodRecuperoMaterialeMainList);

    }

    private void refreshList(List<HistoryVersamentoProdULDTO> filteredList) {

        List<HistoryVersamentoProdULDTO> tmpList = null;

        if (filteredList != null) {
            tmpList = filteredList;
        } else {
            tmpList = mViewModel.getOrderList().getValue();
        }

        this.mHistoryULMutableData.clear();
        this.mHistoryULMutableData.addAll(convertDataModelToListModel(tmpList));
    }

    private List<HistoryULsListModel> convertDataModelToListModel(List<HistoryVersamentoProdULDTO> dataList) {

        return Stream.of(dataList)
                .sortBy(HistoryVersamentoProdULDTO::getCodJfas)
                .map(x -> {
                    HistoryULsListModel listModel = new HistoryULsListModel();

                    listModel
                            .setOriginalModel(x)
                            .setGroupTitle(UtilityString.isNullOrEmpty(x.getDescrizioneFase()) ? x.getCodJfas() : x.getDescrizioneFase())

                            .setCodMart(x.getCodMart())
                            .setDescrizione(x.getDescrizioneArt())
                            .setNumCollo(x.getNumColloRif())
                            .setPartitaMag(x.getPartitaMag())
                            .setQtaVersata(x.getQtaCol())
                            .setUntMisVersata(x.getUntMis());


                    return listModel;
                })
                .toList();
    }

    @Override
    public void onItemDispatched(HistoryVersamentoProdULDTO item,
                                 MtbColt sourceMtbColt,
                                 MtbAart mtbAart,
                                 BigDecimal initialNumCnf,
                                 BigDecimal initialQtaCnf,
                                 BigDecimal initialQtaTot,
                                 BigDecimal totalQtaAvailable,
                                 BigDecimal totalNumCnfAvailable,
                                 BigDecimal qtaCnfAvailable,
                                 String partitaMag,
                                 boolean canOverflowOrderQuantity,
                                 boolean canLUBeClosed) {

        DialogInputQuantityV2DTO dialogInputQuantityV2DTO = new DialogInputQuantityV2DTO()
                .setMtbAart(mtbAart)
                .setInitialNumCnf(initialNumCnf)
                .setInitialQtaCnf(initialQtaCnf)
                .setInitialQtaTot(initialQtaTot)

                .setTotalQtaAvailable(totalQtaAvailable)
                .setTotalNumCnfAvailable(totalNumCnfAvailable)
                .setQtaCnfAvailable(qtaCnfAvailable)
                .setPartitaMag(partitaMag)
                .setCanOverflowOrderQuantity(canOverflowOrderQuantity)
                .setCanLUBeClosed(canLUBeClosed);

        if (!mDialogInputQuantityV2View.isVisible())
            mDialogInputQuantityV2View
                    .setDialogInputQuantityV2DTO(dialogInputQuantityV2DTO)
                    .setOnComplete((resultDTO, shouldCloseLU) -> {
                        PickedQuantityDTO pickedQuantityDTO = new PickedQuantityDTO()
                                .setNumCnf(resultDTO.getNumCnf())
                                .setQtaCnf(resultDTO.getQtaCnf())
                                .setQtaTot(resultDTO.getQtaTot())
                                .setPartitaMag(resultDTO.getPartitaMag())
                                .setDataScad(resultDTO.getDataScad());

                        this.mViewModel.onItemDispatched(item, pickedQuantityDTO, sourceMtbColt);
                    })
                    .setOnAbort(this::onLoadingEnded)
                    .show(requireActivity().getSupportFragmentManager(), "tag");
        else this.onLoadingEnded();
    }

    @Override
    public void onLURequest(boolean canLUBeCreated, boolean shouldCheckIfDocExist, RunnableArgss<MtbColt, Boolean> onComplete) {
        DialogScanOrCreateLUView.newInstance(canLUBeCreated, shouldCheckIfDocExist, onComplete)
                .show(requireActivity().getSupportFragmentManager(), "tag");
    }


    @Override
    public void onLUPrintError(Exception ex, Runnable onComplete) {
        this.onLoadingEnded();
        DialogSimpleMessageView.makeErrorDialog(
                        new SpannableString(ex.getMessage()),
                        null,
                        null,
                        R.string.button_ignore_print,
                        onComplete)
                .show(requireActivity().getSupportFragmentManager(), "tag");
    }

    @Override
    public void onNoLUFound(Runnable onComplete) {
        String errorMessage = "Nessuna stampante configurata";
        DialogSimpleMessageView
                .makeWarningDialog(new SpannableString(errorMessage), null, onComplete)
                .show(requireActivity().getSupportFragmentManager(), "tag");
    }


    @Override
    public void onDataSaved() {
        this.onLoadingEnded();
        this.requireActivity().runOnUiThread(() -> {
            DialogCommon.showDataSaved(requireActivity(), this::popMe);
        });
    }
}
