package it.integry.integrywmsnative.gest.ultime_consegne_cliente;


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.rest.model.DocumentoResoDTO;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityExceptions;
import it.integry.integrywmsnative.databinding.FragmentMainUltimeConsegneClienteBinding;
import it.integry.integrywmsnative.gest.picking_resi.PickingResiActivity;
import it.integry.integrywmsnative.gest.ultime_consegne_cliente.dialog.DialogUltimeConsegneFiltroAvanzato;
import it.integry.integrywmsnative.ui.ElevatedToolbar;

public class UltimeConsegneClienteFragment extends BaseFragment implements UltimeConsegneClienteViewModel.Listener, ITitledFragment, IScrollableFragment, IFilterableFragment {

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

    private int barcodeScannerIstanceID = -1;

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

    @Inject
    UltimeConsegneClienteViewModel mViewModel;

    private DialogUltimeConsegneFiltroAvanzato.DialogUltimeConsegneFiltroAvanzatoViewModel mAppliedFilterViewModel;

    private FragmentMainUltimeConsegneClienteBinding mBindings;

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

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


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        mBindings = DataBindingUtil.inflate(LayoutInflater.from(getActivity()), R.layout.fragment_main_ultime_consegne_cliente, container, false);

        MainApplication.appComponent
                .ultimeConsegneClienteComponent()
                .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.loadCodAnagClienti(gtbAnags -> {
            DialogUltimeConsegneFiltroAvanzato.make(getActivity(), gtbAnags, mAppliedFilterViewModel, (filter) -> {
                mAppliedFilterViewModel = filter;
                refreshItems();
            }).show();
        });
    }


    private void initRecyclerView() {
        UltimeConsegneMainListAdapter mAdapter =
                new UltimeConsegneMainListAdapter(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()
                .setOnScanSuccessful(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 refreshItems() {
        this.onLoadingStarted();

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

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

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

        this.mViewModel.loadConsegneClienti(currentCodAnagFilter,
                null,
                -1,
                548
        );

    }

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

        return sortedDataset;
    }


    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_consegne_cliente_title).toString(), selectedConsegne, +1);
    }


    @Override
    public void onDestroy() {
        for (Runnable onPreDestroy : mOnPreDestroyList) {
            onPreDestroy.run();
        }
        super.onDestroy();
    }

    @Override
    public void onCreateActionBar(AppCompatTextView titleText, Context context) {
        titleText.setText(context.getText(R.string.ultime_consegne_cliente_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);
    }

}
