package it.integry.integrywmsnative.gest.main;


import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
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.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.inject.Inject;

import it.integry.integrywmsnative.MainApplication;
import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.core.class_router.configs.BaseMenuConfiguration;
import it.integry.integrywmsnative.core.class_router.configs.MenuConfiguration;
import it.integry.integrywmsnative.core.data_recover.ColliDataRecoverDTO;
import it.integry.integrywmsnative.core.data_recover.ColliDataRecoverService;
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.menu.MenuService;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.model.secondary.GestioneEnum;
import it.integry.integrywmsnative.core.rest.consumers.ColliLavorazioneRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers.ColliMagazzinoRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers.ColliSpedizioneRESTConsumer;
import it.integry.integrywmsnative.core.rest.model.uds.CloseUDSRequestDTO;
import it.integry.integrywmsnative.core.rest.model.uds.CloseUDSResponseDTO;
import it.integry.integrywmsnative.core.rest.watcher.ServerStatusChecker;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityDimension;
import it.integry.integrywmsnative.core.utility.UtilityExceptions;
import it.integry.integrywmsnative.core.utility.UtilityResources;
import it.integry.integrywmsnative.databinding.FragmentMainBinding;
import it.integry.integrywmsnative.databinding.FragmentMainMenuGroupLayoutBinding;
import it.integry.integrywmsnative.ui.ElevatedToolbar;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link MainFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class MainFragment extends Fragment implements ITitledFragment, IScrollableFragment {

    @Inject
    ColliDataRecoverService colliDataRecoverService;

    @Inject
    ColliSpedizioneRESTConsumer colliSpedizioneRESTConsumer;

    @Inject
    ColliLavorazioneRESTConsumer colliLavorazioneRESTConsumer;


    @Inject
    MenuService menuService;

    @Inject
    ColliMagazzinoRESTConsumer colliMagazzinoRESTConsumer;

    private FragmentMainBinding mBindings;

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

    private LayoutInflater mLayoutInflater;

    private boolean easterEggToggle = false;

    public MainFragment() {
    }

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

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);

        MainApplication.appComponent
                .mainFragmentComponent()
                .create()
                .inject(this);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        this.mLayoutInflater = inflater;
        mBindings = DataBindingUtil.inflate(inflater, R.layout.fragment_main, container, false);
        mBindings.setView(this);

        mBindings.easterEggHorrorBloodExpandableLayout.setExpanded(false, false);
        return mBindings.getRoot();
    }

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

        mToolbar.setNestedScrollView(mBindings.fragmentMainScrollview);

        init();
        initGestMenu();
        initVersion();
    }

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


    private void init() {
        ServerStatusChecker.getInstance().addCallback(value -> {
            if (value && mBindings.noConnectionTopLayout.isExpanded()) {
                collapseNoConnectionLayout();
            } else if (!value && !mBindings.noConnectionTopLayout.isExpanded()) {
                expandNoConnectionLayout();
            }
        });

//        WiFiCheckerViewHolder wiFiCheckerViewHolder = new WiFiCheckerViewHolder(getActivity(), mView, R.id.wifi_power);
//        wiFiCheckerViewHolder.startMonitoring();

        initSessionData();

        initRecuperoCollo();
    }

    private void initSessionData() {
        mBindings.currentUserName.setText(SettingsManager.i().getUser().getFullname());
        mBindings.currentDeposito.setText(String.format("Deposito: %s • %s", SettingsManager.i().getUserSession().getDepo().getCodMdep(), SettingsManager.i().getUserSession().getDepo().getDescrizione()));

        if (SettingsManager.iDB().getDatiAzienda() != null && SettingsManager.iDB().getDatiAzienda().isLogoAvailable()) {
//            currentLogoAzienda.setImageBitmap(SettingsManager.iDB().getDatiAzienda().getLogo());
        }
    }

    private void initRecuperoCollo() {
        if (colliDataRecoverService.thereIsAnExistantSession()) {
            startRecoverMode();

            List<Exception> generatedErrors = new ArrayList<>();

            Iterator<Integer> sessionsIterator = colliDataRecoverService.getAllSessionIDs().iterator();

            cyclicRecover(sessionsIterator, () -> {

                for (Exception ex : generatedErrors) {
                    UtilityExceptions.defaultException(getActivity(), ex);
                }

                endRecoverMode();
            }, generatedErrors::add);

        }
    }

    private void cyclicRecover(Iterator<Integer> sessionsIterator, Runnable onComplete, RunnableArgs<Exception> onFailed) {

        RunnableArgss<Exception, Integer> tmpOnFailed = (ex, recoveredMtbColtID) -> {
            if (ex.getMessage().contains("Dati entity mtb_colt non trovati") ||
                    ex.getMessage().contains("Dati collo non corretti") ||
                    (ex.getMessage().contains("Il collo numero") && ex.getMessage().contains("non esiste")) ||
                    ex.getMessage().contains("Impossibile eliminare un collo agganciato a documento")) {
                colliDataRecoverService.closeSession(recoveredMtbColtID);
                onFailed.run(ex);
            } else {
                onFailed.run(ex);
            }

            cyclicRecover(sessionsIterator, onComplete, onFailed);
        };

        if (!sessionsIterator.hasNext()) {
            onComplete.run();
            return;
        }

        Integer recoveredMtbColtID = sessionsIterator.next();
        ColliDataRecoverDTO recoveredMtbColtDto = colliDataRecoverService.getSession(recoveredMtbColtID);
        MtbColt recoveredMtbColt = recoveredMtbColtDto.getMtbColt();

        if (recoveredMtbColt != null &&
                (recoveredMtbColt.getGestioneEnum() == GestioneEnum.VENDITA ||
                        recoveredMtbColt.getGestioneEnum() == GestioneEnum.LAVORAZIONE)) {

            String codMdep = SettingsManager.i().getUserSession().getDepo().getCodMdep();
            if(recoveredMtbColtDto.getTestateOrdini() != null &&
                    !recoveredMtbColtDto.getTestateOrdini().isEmpty()){
                codMdep = recoveredMtbColtDto.getTestateOrdini().get(0).getCodMdep();
            }

            var closeUDSRequestDto = new CloseUDSRequestDTO()
                    .setMtbColt(recoveredMtbColt)
                    //.setPrintSSCC(shouldPrint)
                    .setOrderCodMdep(codMdep);

            RunnableArgs<CloseUDSResponseDTO> onRequestComplete = closeUDSResponseDto -> {
                colliDataRecoverService.closeSession(recoveredMtbColtID);
                cyclicRecover(sessionsIterator, onComplete, onFailed);
            };

            switch (recoveredMtbColt.getGestioneEnum()) {
                case LAVORAZIONE:
                    colliLavorazioneRESTConsumer.closeUDS(closeUDSRequestDto, onRequestComplete, ex -> {
                        tmpOnFailed.run(ex, recoveredMtbColtID);
                    });
                    break;
                case VENDITA:
                    colliSpedizioneRESTConsumer.closeUDS(closeUDSRequestDto, onRequestComplete, ex -> {
                        tmpOnFailed.run(ex, recoveredMtbColtID);
                    });
                    break;
            }
        } else {
            colliDataRecoverService.closeSession(recoveredMtbColtID);
            cyclicRecover(sessionsIterator, onComplete, onFailed);
        }

    }

    private void collapseNoConnectionLayout() {
        if (getActivity() != null)
            getActivity().runOnUiThread(() -> mBindings.noConnectionTopLayout.collapse(true));
    }

    private void expandNoConnectionLayout() {
        if (getActivity() != null)
            getActivity().runOnUiThread(() -> mBindings.noConnectionTopLayout.expand(true));
    }

    private void startRecoverMode() {
        mBindings.recoverDataExpandableLayout.expand(true);
    }

    private void endRecoverMode() {
        mBindings.recoverDataExpandableLayout.collapse(true);
    }

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

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

    private void initGestMenu() {
        int menuSpanCount = 2;
        if (UtilityDimension.getDisplayInchs(this.getActivity()) > 8) menuSpanCount = 4;
        else if (UtilityDimension.getDisplayInchs(this.getActivity()) > 6.5) menuSpanCount = 3;

        MenuConfiguration baseMenuConfiguration = new MenuConfiguration();
        List<MenuConfiguration.MenuGroup> menuGroups = baseMenuConfiguration.getGroups();

        for (int i = 0; i < menuGroups.size(); i++) {
            try {

                BaseMenuConfiguration.MenuGroup menuGroup = menuGroups.get(i);

                if (menuService.isGroupEnabled(menuGroup)) {

                    FragmentMainMenuGroupLayoutBinding groupBinding = DataBindingUtil.inflate(mLayoutInflater, R.layout.fragment_main_menu_group_layout, null, false);

                    String title = this.getResources().getString(menuGroup.getGroupText());
                    groupBinding.generalDashboardGroupTitle.setText(title);

                    List<BaseMenuConfiguration.MenuItem> enableMenuItems = new ArrayList<>();

                    for (int j = 0; j < menuGroup.getItems().size(); j++) {
                        if (menuService.isItemEnabled(menuGroup.getItems().get(j))) {
                            enableMenuItems.add(menuGroup.getItems().get(j));
                        }
                    }

                    MenuListAdapter menuListAdapter = new MenuListAdapter(getContext(), enableMenuItems);

                    groupBinding.mainList.setLayoutManager(new GridLayoutManager(getContext(), menuSpanCount));
                    groupBinding.mainList.setAdapter(menuListAdapter);
                    groupBinding.mainList.setNestedScrollingEnabled(false);

                    menuListAdapter.setClickListener(this::onMenuClick);

                    mBindings.menuContainer.addView(groupBinding.getRoot());


                }


            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }

    }

    private void onMenuClick(MenuConfiguration.MenuItem menuItem) {
        ((MainActivity) getActivity()).setMenuItem(menuItem.getID());
    }

    private void initVersion() {
        String appVersion = UtilityResources.getAppVersion();
        mBindings.currentAppVersionName.setText("v" + appVersion);
    }

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


    public void toggleEasterEggMode() {
        easterEggToggle = !easterEggToggle;


        int rootBgStart, rootBgEnd;
        int profileBgStart, profileBgEnd;
        float titleFlipStart, titleFlipEnd;
        int animationTimeMillis = 0;

        if (easterEggToggle) {
            rootBgStart = Color.argb(255, 255, 255, 255);
            rootBgEnd = Color.argb(255, 0, 0, 0);

            profileBgStart = Color.argb(255, 26, 115, 232);
            profileBgEnd = Color.argb(255, 211, 47, 47);
            animationTimeMillis = 2500;
            titleFlipStart = 1f;
            titleFlipEnd = -1f;
        } else {
            rootBgStart = Color.argb(255, 0, 0, 0);
            rootBgEnd = Color.argb(255, 255, 255, 255);

            profileBgStart = Color.argb(255, 211, 47, 47);
            profileBgEnd = Color.argb(255, 26, 115, 232);
            animationTimeMillis = 750;
            titleFlipStart = -1f;
            titleFlipEnd = 1f;
        }

        mBindings.easterEggHorrorBloodExpandableLayout.setDuration(animationTimeMillis);
        mBindings.easterEggHorrorBloodExpandableLayout.setExpanded(easterEggToggle, true);

        View rootActivityView = requireActivity().findViewById(R.id.drawer_layout);
        ObjectAnimator colorFadeRootBg = ObjectAnimator.ofObject(rootActivityView, "backgroundColor",
                new ArgbEvaluator(),
                rootBgStart,
                rootBgEnd);

        colorFadeRootBg.setDuration(animationTimeMillis);
        colorFadeRootBg.start();

        View toolbarActivityView = requireActivity().findViewById(R.id.toolbar);
        ObjectAnimator colorFadeToolbarBg = ObjectAnimator.ofObject(toolbarActivityView, "backgroundColor",
                new ArgbEvaluator(),
                rootBgStart,
                rootBgEnd);

        colorFadeToolbarBg.setDuration(animationTimeMillis);
        colorFadeToolbarBg.start();

        ObjectAnimator colorFadeProfileBg = ObjectAnimator.ofObject(mBindings.profileRootContainer, "backgroundColor",
                new ArgbEvaluator(),
                profileBgStart,
                profileBgEnd);

        colorFadeProfileBg.setDuration(animationTimeMillis);
        colorFadeProfileBg.start();

        View toolbarTitleActivityView = requireActivity().findViewById(R.id.toolbar_title);
        ObjectAnimator flipToolbarTitleX = ObjectAnimator.ofFloat(toolbarTitleActivityView, "scaleX",
                titleFlipStart,
                titleFlipEnd);

        flipToolbarTitleX.setDuration(animationTimeMillis);
        flipToolbarTitleX.start();

        ObjectAnimator flipToolbarTitleY = ObjectAnimator.ofFloat(toolbarTitleActivityView, "scaleY",
                titleFlipStart,
                titleFlipEnd);

        flipToolbarTitleY.setDuration(animationTimeMillis);
        flipToolbarTitleY.start();

        ObjectAnimator colorFadeTitleTextColor = ObjectAnimator.ofObject(toolbarTitleActivityView, "textColor",
                new ArgbEvaluator(),
                rootBgEnd,
                rootBgStart);

        colorFadeTitleTextColor.setDuration(animationTimeMillis);
        colorFadeTitleTextColor.start();
    }
}
