package it.integry.integrywmsnative.gest.accettazione_ordini_elenco;


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

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

import com.annimon.stream.Stream;

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.data_cache.DataCache;
import it.integry.integrywmsnative.core.di.BindableBoolean;
import it.integry.integrywmsnative.core.expansion.BaseFragment;
import it.integry.integrywmsnative.core.interfaces.IScrollableFragment;
import it.integry.integrywmsnative.core.interfaces.ISearchableFragment;
import it.integry.integrywmsnative.core.interfaces.ITitledFragment;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityBigDecimal;
import it.integry.integrywmsnative.core.utility.UtilityDate;
import it.integry.integrywmsnative.databinding.FragmentMainAccettazioneOrdiniBinding;
import it.integry.integrywmsnative.gest.accettazione_ordini_elenco.dto.OrdineAccettazioneInevasoDTO;
import it.integry.integrywmsnative.gest.accettazione_ordini_elenco.dto.SitArtOrdDTO;
import it.integry.integrywmsnative.gest.accettazione_ordini_elenco.ui.MainListAccettazioneOrdiniElencoAdapter;
import it.integry.integrywmsnative.gest.accettazione_ordini_elenco.ui.MainListAccettazioneOrdiniElencoClienteListModel;
import it.integry.integrywmsnative.gest.accettazione_ordini_elenco.ui.MainListAccettazioneOrdiniElencoListModel;
import it.integry.integrywmsnative.gest.accettazione_ordini_picking.AccettazioneOrdiniPickingActivity;
import it.integry.integrywmsnative.ui.ElevatedToolbar;
import it.integry.integrywmsnative.view.dialogs.base.DialogSimpleMessageView;

public class MainAccettazioneOrdiniElencoFragment extends BaseFragment implements ISearchableFragment, ITitledFragment, IScrollableFragment, MainAccettazioneOrdiniElencoViewModel.Listener {

    public BindableBoolean fabVisible = new BindableBoolean(false);

    @Inject
    MainAccettazioneOrdiniElencoViewModel mViewModel;

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

    private String mTextFilter;
    private FragmentMainAccettazioneOrdiniBinding mBinding;

    private final ObservableArrayList<MainListAccettazioneOrdiniElencoListModel> mOrdiniInevasiMutableData = new ObservableArrayList<>();

    private AppCompatTextView mAppBarTitle;


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

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


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

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        onLoadingEnded();
        outState.putString("mToolbar", DataCache.addItem(mToolbar));

        super.onSaveInstanceState(outState);
    }


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

        if (savedInstanceState != null && savedInstanceState.containsKey("mToolbar"))
            mToolbar = DataCache.retrieveItem(savedInstanceState.getString("mToolbar"));

        mBinding = FragmentMainAccettazioneOrdiniBinding.inflate(inflater, container, false);

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

        mViewModel.setListener(this);

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

        this.initRecyclerView();

        mToolbar.setRecyclerView(mBinding.accettazioneMainList);

        return mBinding.getRoot();
    }


    @Override
    public void onStart() {
        super.onStart();

        this.fabVisible.set(false);

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

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


    private void initRecyclerView() {
        this.mViewModel.getOrderList().observe(getViewLifecycleOwner(), x -> {
            this.refreshList(getFilteredList(mTextFilter));
        });


        MainListAccettazioneOrdiniElencoAdapter adapter = new MainListAccettazioneOrdiniElencoAdapter(getActivity(), mOrdiniInevasiMutableData)
                .setOnGroupItemClicked(x -> {
                    Stream.of(mOrdiniInevasiMutableData)
                            .filter(y -> !y.getGroupTitle().equalsIgnoreCase(x) && y.getSelectedObservable().get())
                            .forEach(y -> y.getSelectedObservable().set(false));

                    boolean allSelected = Stream.of(mOrdiniInevasiMutableData)
                            .filter(y -> y.getGroupTitle().equalsIgnoreCase(x))
                            .allMatch(y -> y.getSelectedObservable().get());

                    Stream.of(mOrdiniInevasiMutableData)
                            .filter(y -> y.getGroupTitle().equalsIgnoreCase(x))
                            .forEach(y -> y.getSelectedObservable().set(!allSelected));
                })
                .setOnItemChecked(x -> {
                    Stream.of(mOrdiniInevasiMutableData)
                            .filter(y -> !y.getGroupTitle().equalsIgnoreCase(x.getGroupTitle()) && y.getSelectedObservable().get())
                            .forEach(y -> y.getSelectedObservable().set(false));

                    fabVisible.set(Stream.of(mOrdiniInevasiMutableData)
                            .anyMatch(y -> y.getSelectedObservable().get()));
                });

        adapter.setEmptyView(this.mBinding.ordiniAccettazioneEmptyView);

        this.mBinding.accettazioneMainList.setAdapter(adapter);
        this.mBinding.accettazioneMainList.setLayoutManager(new LinearLayoutManager(getActivity()));

        if (mToolbar != null)
            mToolbar.setRecyclerView(this.mBinding.accettazioneMainList);
    }


    private void refreshList(List<OrdineAccettazioneInevasoDTO> filteredList) {

        List<OrdineAccettazioneInevasoDTO> tmpList = null;

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

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

    private List<MainListAccettazioneOrdiniElencoListModel> convertDataModelToListModel(List<OrdineAccettazioneInevasoDTO> dataList) {

        return Stream.of(dataList)
                .distinctBy(OrdineAccettazioneInevasoDTO::getBarcode)
                .sortBy(x -> x.getRagSocOrd() + (x.getDataConsD() != null ? UtilityDate.formatDate(x.getDataConsD(), UtilityDate.COMMONS_DATE_FORMATS.YMD_SLASH) : ""))
                .map(x -> {
                    MainListAccettazioneOrdiniElencoListModel listModel = new MainListAccettazioneOrdiniElencoListModel();

                    listModel.setOriginalModel(x);

                    listModel.setGroupTitle(x.getRagSocOrd());

                    listModel.setDescription(String.format(getString(R.string.ord_acq_testata), x.getNumero(), UtilityDate.formatDate(x.getDataD(), UtilityDate.COMMONS_DATE_FORMATS.DMY_HUMAN)));

                    List<MainListAccettazioneOrdiniElencoClienteListModel> clienti = Stream.of(dataList)
                            .filter(y -> y.getBarcode().equals(x.getBarcode()))
                            .map(y -> new MainListAccettazioneOrdiniElencoClienteListModel()
                                    .setPrimaryText(y.getRifOrd())
                                    .setRightText(UtilityDate.formatDate(y.getDataConsD(), UtilityDate.COMMONS_DATE_FORMATS.DMY_SLASH)))
                            .toList();

                    listModel.setClientiListModel(clienti);

                    return listModel;
                })
                .toList();
    }

    public void dispatchOrders() {
        List<OrdineAccettazioneInevasoDTO> selectedOrders = Stream.of(this.mOrdiniInevasiMutableData)
                .filter(x -> x.getSelectedObservable().get())
                .map(MainListAccettazioneOrdiniElencoListModel::getOriginalModel)
                .toList();


        this.mViewModel.loadPicking(selectedOrders);
    }


    @Override
    public void onSearchEnabled() {
        mAppBarTitle.setVisibility(View.GONE);
    }

    @Override
    public void onSearchDisabled() {
        mAppBarTitle.setVisibility(View.VISIBLE);
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        List<OrdineAccettazioneInevasoDTO> originalList = this.mViewModel.getOrderList().getValue();
        if (originalList == null || originalList.isEmpty()) return false;
        mTextFilter = newText;
        List<OrdineAccettazioneInevasoDTO> filteredOrders = getFilteredList(newText);

        refreshList(filteredOrders);
        return true;
    }

    private List<OrdineAccettazioneInevasoDTO> getFilteredList(String newText) {
        List<OrdineAccettazioneInevasoDTO> filteredOrders = new ArrayList<>();
        List<OrdineAccettazioneInevasoDTO> originalList = this.mViewModel.getOrderList().getValue();
        if (originalList == null || originalList.isEmpty() || newText == null) return originalList;
        for (int i = 0; i < originalList.size(); i++) {
            if (originalList.get(i).getRagSocOrd().toLowerCase().contains(newText.toLowerCase())) {
                filteredOrders.add(originalList.get(i));
            }
        }
        return filteredOrders;
    }

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


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

    @Override
    public void onOrdersDispatched(List<OrdineAccettazioneInevasoDTO> orders, List<SitArtOrdDTO> sitArts) {
        long artsCounter = Stream.of(sitArts)
                .filter(x -> UtilityBigDecimal.greaterThan(x.getQtaDaEvadere(), BigDecimal.ZERO))
                .map(SitArtOrdDTO::getCodMart)
                .distinct()
                .count();

        long ordsCounter = Stream.of(sitArts)
                .distinctBy(x -> x.getDataOrd() + " " + x.getNumOrd() + " " + x.getGestione())
                .count();


        DialogSimpleMessageView.makeInfoDialog(getText(R.string.orders).toString(),
                Html.fromHtml(String.format(getActivity().getResources().getQuantityString(R.plurals.loaded_orders_message, (int) ordsCounter), ordsCounter)
                        + "<br /><br />" +
                        "<b>" + artsCounter + "</b> " + getActivity().getResources().getQuantityString(R.plurals.ordered_articles, (int) artsCounter)),
                null,
                () -> {

                    String cacheSitArtItemID = DataCache.addItem(sitArts);
                    String cacheOrdersItemID = DataCache.addItem(orders);

                    Intent myIntent = new Intent(getActivity(), AccettazioneOrdiniPickingActivity.class);
                    myIntent.putExtra("keyOrders", cacheOrdersItemID);
                    myIntent.putExtra("keySitArts", cacheSitArtItemID);
                    getActivity().startActivity(myIntent);

                }).show(getActivity().getSupportFragmentManager(), "tag");
    }
}
