package it.integry.integrywmsnative.gest.ultimi_arrivi_fornitore;


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

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ObservableArrayList;
import androidx.recyclerview.widget.LinearLayoutManager;

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

import java.util.ArrayList;
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.interfaces.IFilterableFragment;
import it.integry.integrywmsnative.core.interfaces.IScrollableFragment;
import it.integry.integrywmsnative.core.interfaces.ITitledFragment;
import it.integry.integrywmsnative.core.model.GtbAnag;
import it.integry.integrywmsnative.core.model.MtbAart;
import it.integry.integrywmsnative.core.model.MtbColr;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.rest.model.DocumentoResoDTO;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityExceptions;
import it.integry.integrywmsnative.databinding.FragmentUltimiArriviFornitoreBinding;
import it.integry.integrywmsnative.gest.picking_resi.PickingResiActivity;
import it.integry.integrywmsnative.gest.ultimi_arrivi_fornitore.ui.UltimiArriviFornitoreListAdapter;
import it.integry.integrywmsnative.gest.ultimi_arrivi_fornitore.dialog.DialogUltimiArriviFornitoreFiltroAvanzato;
import it.integry.integrywmsnative.ui.ElevatedToolbar;
import it.integry.integrywmsnative.view.dialogs.choose_arts_from_lista_arts.DialogChooseArtsFromListaArts;

/**
 * A simple {@link BaseFragment} subclass.
 */
public class UltimiArriviFornitoreFragment extends BaseFragment implements ITitledFragment, IScrollableFragment, IFilterableFragment, UltimiArriviFornitoreViewModel.Listener {

    private final List<Runnable> mOnPreDestroyList = new ArrayList<>();
    private ElevatedToolbar mToolbar;

    private int barcodeScannerIstanceID = -1;

    private final ObservableArrayList<DocumentoResoDTO> mDocumentiMutableData = new ObservableArrayList<>();

    @Inject
    UltimiArriviFornitoreViewModel mViewModel;

    private FragmentUltimiArriviFornitoreBinding mBindings;
    private DialogUltimiArriviFornitoreFiltroAvanzato.DialogUltimiArriviFiltroAvanzatoViewModel mAppliedFilterViewModel;

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

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


    @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_ultimi_arrivi_fornitore, container, false);

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

        mViewModel.setListener(this);

        mBindings.setLifecycleOwner(this);
        mBindings.setView(this);
        mBindings.setViewmodel(mViewModel);

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

        // Inflate the layout for this fragment
        return mBindings.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        String codMdep = SettingsManager.i().getUserSession().getDepo().getCodMdep();
        mViewModel.init(codMdep);

        this.mBindings.mainFab.hide();
        this.mBindings.mainFab.setOnClickListener(v -> {
            dispatchConsegne();
        });

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

        openFilterDialog();
    }


    public void openFilterDialog() {
        this.mViewModel.loadCodAnagFornitori(gtbAnags -> {
            DialogUltimiArriviFornitoreFiltroAvanzato.make(getActivity(), gtbAnags, mAppliedFilterViewModel, (filter) -> {
                mAppliedFilterViewModel = filter;
                filterItems(null);
            }).show();
        });
    }


    private void initRecyclerView() {
        UltimiArriviFornitoreListAdapter mAdapter =
                new UltimiArriviFornitoreListAdapter(getActivity(), mDocumentiMutableData);
        mAdapter.setOnSelectionChanged(this::onSingleSelectionChanged);
        mAdapter.setEmptyView(mBindings.emptyView);

        mBindings.recyclerView.setHasFixedSize(true);
        mBindings.recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mBindings.recyclerView.setAdapter(mAdapter);
//        mBindings.fastscroll.setRecyclerView(mBindings.recyclerView);

        if (mToolbar != null)
            mToolbar.setRecyclerView(mBindings.recyclerView);

    }

    private void initBarcodeReader() {
        barcodeScannerIstanceID = BarcodeManager.addCallback(new BarcodeCallbackDTO()
                .setOnScanSuccessfull(onScanSuccessful)
                .setOnScanFailed(ex -> UtilityExceptions.defaultException(getActivity(), ex, false)));

        BarcodeManager.enable();
    }

    private final RunnableArgs<BarcodeScanDTO> onScanSuccessful = data -> {
        BarcodeManager.disable();

        this.mViewModel.processBarcodeDTO(data, () -> {
            BarcodeManager.enable();
        });
    };

    private void refreshList(List<DocumentoResoDTO> documentList) {
        this.mDocumentiMutableData.clear();
        this.mDocumentiMutableData.addAll(sort(documentList));
    }

    private void filterItems(List<MtbAart> filteredMtbAarts) {
        this.openProgress();

        String currentAnagFilter = mAppliedFilterViewModel != null ? mAppliedFilterViewModel.ragSoc.get() : null;
        String currentCodAnagFilter = null;

        Optional<GtbAnag> singleGtbAnag = Stream.of(mViewModel.getGtbAnagClienti().getValue())
                .filter(x -> (x.getCodAnag() + " - " + x.getRagSoc()).equals(currentAnagFilter))
                .findSingle();

        if (singleGtbAnag.isPresent()) {
            currentCodAnagFilter = singleGtbAnag.get().getCodAnag();
        }

        this.mViewModel.loadArriviFornitori(currentCodAnagFilter,
                filteredMtbAarts,
                -1,
                365);
    }

    private List<DocumentoResoDTO> sort(List<DocumentoResoDTO> dataset) {
        List<DocumentoResoDTO> items = Stream.of(dataset)
                .sortBy(DocumentoResoDTO::getRagSoc)
                .toList();
        return items;

    }

    private void onSingleSelectionChanged(DocumentoResoDTO dto) {
        List<DocumentoResoDTO> selectedOrders = getSelectedItems();

        if (dto.isSelected()) {
            Stream.of(selectedOrders)
                    .filter(x -> !x.getRagSoc().equalsIgnoreCase(dto.getRagSoc()))
                    .forEach(x -> x.setSelected(false));
        }

        if (selectedOrders != null && selectedOrders.size() > 0) {
            mBindings.mainFab.show();
        } else {
            mBindings.mainFab.hide();
        }
    }


    private List<DocumentoResoDTO> getSelectedItems() {
        return Stream.of(this.mDocumentiMutableData)
                .filter(DocumentoResoDTO::isSelected)
                .toList();
    }

    private void dispatchConsegne() {
        List<DocumentoResoDTO> selectedConsegne = getSelectedItems();

        PickingResiActivity.startActivity(getActivity(), getActivity().getText(R.string.ultime_arrivi_fornitore_title).toString(), selectedConsegne, -1);
    }


    @Override
    public void onDestroy() {
        BarcodeManager.removeCallback(barcodeScannerIstanceID);

        for (Runnable onPreDestroy : mOnPreDestroyList) {
            onPreDestroy.run();
        }
        super.onDestroy();
    }

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

    @Override
    public void setScrollToolbar(ElevatedToolbar toolbar) {
        mToolbar = toolbar;
    }


    @Override
    public void onFilterClick() {
        openFilterDialog();
    }


    @Override
    public void addOnPreDestroy(Runnable onPreDestroy) {
        this.mOnPreDestroyList.add(onPreDestroy);
    }

    @Override
    public void onLoadingStarted() {
        BarcodeManager.disable();
        this.openProgress();
    }

    @Override
    public void onLoadingEnded() {
        this.closeProgress();
        BarcodeManager.enable();
    }

    @Override
    public void onError(Exception ex) {
        this.closeProgress();
        UtilityExceptions.defaultException(getActivity(), ex, mCurrentProgress);
        BarcodeManager.enable();
    }

    @Override
    public void onMtbColtScanned(MtbColt scannedMtbColt) {

        DialogChooseArtsFromListaArts
                .newInstance(scannedMtbColt.getMtbColr(), items -> {

                    List<MtbAart> mtbAarts = Stream.of(items)
                            .map(MtbColr::getMtbAart)
                            .toList();

                    filterItems(mtbAarts);

                }, null)
                .show(requireActivity().getSupportFragmentManager(), "tag");
    }
}
