package it.integry.integrywmsnative.gest.pv_ordine_acquisto_edit;

import android.app.Dialog;
import android.os.Bundle;
import android.text.Html;
import android.text.SpannableString;
import android.view.View;
import android.widget.Toast;

import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.LinearLayoutManager;

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.data_cache.DataCache;
import it.integry.integrywmsnative.core.data_store.db.entity.ArticoloOrdine;
import it.integry.integrywmsnative.core.data_store.db.entity.Griglia;
import it.integry.integrywmsnative.core.data_store.db.entity.Ordine;
import it.integry.integrywmsnative.core.data_store.db.repository.ArticoliOrdineRepository;
import it.integry.integrywmsnative.core.data_store.db.repository.ArticoloGrigliaRepository;
import it.integry.integrywmsnative.core.data_store.db.repository.GrigliaRepository;
import it.integry.integrywmsnative.core.data_store.db.repository.OrdineRepository;
import it.integry.integrywmsnative.core.expansion.BaseActivity;
import it.integry.integrywmsnative.core.rest.consumers.PVOrdiniAcquistoRESTConsumer;
import it.integry.integrywmsnative.core.utility.UtilityDate;
import it.integry.integrywmsnative.core.utility.UtilityExceptions;
import it.integry.integrywmsnative.core.utility.UtilityProgress;
import it.integry.integrywmsnative.databinding.ActivityPvOrdineAcquistoEditBinding;
import it.integry.integrywmsnative.gest.pv_ordine_acquisto_edit.ui.OrdineAcquistoArtListAdapter;
import it.integry.integrywmsnative.gest.pv_ordine_acquisto_edit.dialog.EditArticoloDialog;
import it.integry.integrywmsnative.gest.pv_ordine_acquisto_edit.helper.PVEditOrderHelper;
import it.integry.integrywmsnative.ui.FabMenuCustomAnimations;
import it.integry.integrywmsnative.ui.SimpleDividerItemDecoration;
import it.integry.integrywmsnative.view.dialogs.DialogAskAction;
import it.integry.integrywmsnative.view.dialogs.base.DialogSimpleInputHelper;
import it.integry.integrywmsnative.view.dialogs.base.DialogSimpleMessageView;

public class PVOrdineAcquistoEditActivity extends BaseActivity {

    private Ordine mOrdine;
    private Griglia mGriglia;
    private List<ArticoloOrdine> mArticoli = new ArrayList<>();
    private PVEditOrderHelper mhelper;
    private ActivityPvOrdineAcquistoEditBinding mBinding;
    private int mBarcodeScannerIstanceID;
    private OrdineAcquistoArtListAdapter mAdapter;

    @Inject
    OrdineRepository mOrdineRepository;
    @Inject
    GrigliaRepository mGrigliaRepository;
    @Inject
    ArticoliOrdineRepository mArticoliOrdineRepository;
    @Inject
    ArticoloGrigliaRepository mArticoloGrigliaRepository;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

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

        mhelper = new PVEditOrderHelper(mGrigliaRepository, mArticoliOrdineRepository, mArticoloGrigliaRepository);

        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_pv_ordine_acquisto_edit);
        mBinding.setViewModel(this);
        mOrdine = DataCache.retrieveItem(getIntent().getStringExtra("keyOrdine"));
        setSupportActionBar(mBinding.toolbar);
        mBinding.toolbar.setTitle(R.string.edit_order);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        if (mOrdine == null) {
            Toast.makeText(this, "Impossibile modificare ordine esportato", Toast.LENGTH_SHORT).show();
            closeEdit();
        }
        if (mOrdine.isTransmitted()) {
            Toast.makeText(this, "Impossibile modificare ordine esportato", Toast.LENGTH_SHORT).show();
            closeEdit();
        }
        String testataOrdString = String.format(this.getString(R.string.ord_acq_testata), String.valueOf(mOrdine.getOrdineId()), UtilityDate.formatDate(mOrdine.getDataIns(), UtilityDate.COMMONS_DATE_FORMATS.DMY_HUMAN));
        mBinding.orderIdentifier.setText(Html.fromHtml(testataOrdString));
        FabMenuCustomAnimations.changeIconOnFocus(mBinding.closeActivityFab, R.drawable.ic_check_white_24dp, R.drawable.ic_close_24dp);


        initRecyclerView();
        fetchDetails();
        mBarcodeScannerIstanceID = BarcodeManager.addCallback(new BarcodeCallbackDTO()
                .setOnScanSuccessfull(this::onScanSuccessful)
                .setOnScanFailed(this::handleException));

    }

    @Override
    public boolean onSupportNavigateUp() {
        onBackPressed();
        return true;
    }

    private void initRecyclerView() {
        mBinding.articoliOrdineList.setHasFixedSize(true);

        mBinding.articoliOrdineList.setLayoutManager(new LinearLayoutManager(this));

        SimpleDividerItemDecoration itemDecorator = new SimpleDividerItemDecoration(this, SimpleDividerItemDecoration.VERTICAL);
        itemDecorator.setDrawable(ContextCompat.getDrawable(this, R.drawable.divider));
        mBinding.articoliOrdineList.addItemDecoration(itemDecorator);
        mAdapter = new OrdineAcquistoArtListAdapter(this, mArticoli, this::selectAction);
        mBinding.articoliOrdineList.setAdapter(mAdapter);
    }

    private void selectAction(ArticoloOrdine articoloOrdine) {
        mBinding.closeActivityFab.close(false);
        BarcodeManager.disable();
        runOnUiThread(() -> DialogAskAction.make(this,
                articoloOrdine.getDescrizione(),
                articoloOrdine.getQtaOrd() + " " + articoloOrdine.getUntMis(),
                () -> this.addArticolo(articoloOrdine),
                () -> this.deleteArticolo(articoloOrdine)).show());

    }

    private void deleteArticolo(ArticoloOrdine articoloOrdine) {
        String text = "Stai per eliminare l'articolo <b> " + articoloOrdine.getDescrizione() + "</b>  dall'ordine, <br> sei sicuro?";

        DialogSimpleMessageView.makeWarningDialog(new SpannableString(Html.fromHtml(text)), null, () -> this.runOnUiThread(() -> {
            final Dialog progress = UtilityProgress.createDefaultProgressDialog(this);
            mhelper.removeArticoloFromOrdine(articoloOrdine, () -> {
                progress.dismiss();
                BarcodeManager.enable();
                runOnUiThread(this::fetchArticoli);
            }, e -> {
                progress.dismiss();
                runOnUiThread(() -> UtilityExceptions.defaultException(this, e));
            });
        }), () -> {
        }).show(getSupportFragmentManager(), "tag");
    }

    private void handleException(Exception ex) {
        runOnUiThread(() -> {
            BarcodeManager.enable();
            UtilityExceptions.defaultException(this, ex, false);
        });
    }

    private void onScanSuccessful(BarcodeScanDTO dto) {
        mBinding.closeActivityFab.close(false);
        BarcodeManager.disable();
        final Dialog progress = UtilityProgress.createDefaultProgressDialog(this);
        mhelper.checkArticolo(
                mOrdine,
                dto.getStringValue(),
                articoloOrdine -> {
                    progress.dismiss();
                    addArticolo(articoloOrdine);
                },
                e -> {
                    progress.dismiss();
                    handleException(e);
                }
        );
    }

    private void addArticolo(ArticoloOrdine articoloOrdine) {
        runOnUiThread(() -> EditArticoloDialog.make(this, mhelper, articoloOrdine, articolo -> {
            BarcodeManager.enable();
            if (articolo != null) {
                Toast.makeText(this, "Articolo aggiunto all'ordine!", Toast.LENGTH_SHORT).show();
            }
            fetchArticoli();
        }).show());
    }

    private void fetchDetails() {
        fetchGriglia();
        fetchArticoli();
    }

    private void fetchGriglia() {
        mhelper.loadGriglia(mOrdine.getIdGriglia(), griglia -> {
            runOnUiThread(() -> {
                mGriglia = griglia;
                mBinding.codAlis.setText(mGriglia.getCodAlis());
            });
        }, this::handleException);
    }

    private void fetchArticoli() {
        final Dialog progress = UtilityProgress.createDefaultProgressDialog(this);
        mhelper.loadArticoli(mOrdine, articoli -> {
            progress.dismiss();
            mArticoli = articoli;
            runOnUiThread(() -> {
                mAdapter.updateItems(mArticoli);
                mBinding.countArtOrd.setText(String.valueOf(mArticoli.size()));
                mBinding.pvOrdineExport.setVisibility(mArticoli.size() > 0 ? View.INVISIBLE : View.GONE);
                mBinding.closeActivityFab.close(false);
                mBinding.scanArtSpinner.setVisibility(mArticoli.size() > 0 ? View.GONE : View.VISIBLE);
            });
        }, this::handleException);
    }

    public void closeEdit() {
        onBackPressed();
    }

    public void exportOrdine() {
        final Dialog progress = UtilityProgress.createDefaultProgressDialog(this);
        PVOrdiniAcquistoRESTConsumer.saveOrdine(mOrdine, mArticoli, mGriglia, (ordine) -> {

            mOrdineRepository.updateOrder(ordine, ord -> {
                progress.dismiss();
                runOnUiThread(() -> {
                    Toast.makeText(this, "Ordine salvato con successo", Toast.LENGTH_SHORT).show();
                    onBackPressed();
                });
            }, e -> runOnUiThread(() -> {
                progress.dismiss();
                UtilityExceptions.defaultException(this, e);
            }));

        }, e -> runOnUiThread(() -> {
            progress.dismiss();
            UtilityExceptions.defaultException(this, e);
        }));
    }

    @Override
    public void onBackPressed() {
        BarcodeManager.removeCallback(mBarcodeScannerIstanceID);
        super.onBackPressed();
    }

    public void manualSearch(){
        BarcodeManager.disable();
        DialogSimpleInputHelper.makeInputDialog(this,"Inserisci il codice a barre/codice articolo da cercare",codice->{
            final Dialog progress = UtilityProgress.createDefaultProgressDialog(this);
            mhelper.checkArticolo(
                    mOrdine,
                    codice,
                    articoloOrdine -> {
                        progress.dismiss();
                        addArticolo(articoloOrdine);
                    },
                    e -> {
                        progress.dismiss();
                        handleException(e);
                    }
            );
        }, BarcodeManager::enable).show();
    }

}
