package it.integry.integrywmsnative.gest.login.viewmodel;

import android.app.Dialog;
import android.content.Intent;
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;

import androidx.appcompat.app.AlertDialog;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.SplashActivity;
import it.integry.integrywmsnative.core.di.BindableBoolean;
import it.integry.integrywmsnative.core.di.BindableString;
import it.integry.integrywmsnative.core.rest.consumers.ISimpleOperationCallback;
import it.integry.integrywmsnative.core.rest.consumers.SystemRESTConsumer;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityProgress;
import it.integry.integrywmsnative.core.utility.UtilityServer;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.gest.login.LoginActivity;
import it.integry.integrywmsnative.gest.login.core.LoginHelper;
import it.integry.integrywmsnative.gest.login.dto.LoginAziendaDTO;
import it.integry.integrywmsnative.gest.login.dto.LoginDTO;
import it.integry.integrywmsnative.view.dialogs.base.DialogSimpleMessageView;

public class LoginViewModel {

    public BindableString username = new BindableString();
    public BindableString password = new BindableString();
    public BindableString codAzienda = new BindableString();

    public BindableBoolean customSettingsCheckboxEnabled = new BindableBoolean();
    public BindableBoolean customSettingsCheckboxChecked = new BindableBoolean();

    public BindableBoolean loginButtonEnabled = new BindableBoolean();


    public BindableString usernameError = new BindableString();
    public BindableString passwordError = new BindableString();
    public BindableString codAziendaError = new BindableString();


    private LoginActivity mActivity;

    private Dialog mProgress;

    public LoginViewModel(LoginActivity activity) {
        this.mActivity = activity;

        loginButtonEnabled.set(true);

        codAzienda.set(SettingsManager.i().getServer().getCodAzienda());

        customSettingsCheckboxChecked.set(SettingsManager.i().getServer().getHost() == null);
        customSettingsCheckboxEnabled.set(SettingsManager.i().getServer().getHost() != null);
    }


    public boolean validate() {
        if (username.isEmpty() || username.get().length() < 3) {
            usernameError.set(mActivity.getText(R.string.username_error_not_valid).toString());
            return false;
        } else usernameError.set(null);

        if (codAzienda.isEmpty() || codAzienda.get().length() < 3) {
            codAziendaError.set(mActivity.getText(R.string.server_cod_azienda_not_valid).toString());
            return false;
        } else codAziendaError.set(null);

        return true;
    }


    public void login(boolean areValidData) {
        if (areValidData) {
            loginButtonEnabled.set(false);

            mProgress = UtilityProgress.createDefaultProgressDialog(mActivity);

            final LoginHelper loginHelper = new LoginHelper(mActivity, codAzienda.get(), username.get(), password.get());

            loginHelper.retrieveServerData(new ISimpleOperationCallback<LoginAziendaDTO>() {

                @Override
                public void onSuccess(LoginAziendaDTO value) {

                    final String serverEndpoint = value.endpointRestApi;

                    URL u;
                    try {
                        u = new URL(serverEndpoint);
                    } catch (final MalformedURLException e) {
                        e.printStackTrace();
                        onLoginFailed(new SpannableString(e.toString()));
                        return;
                    }

                    final String host = u.getHost();
                    final int port = u.getPort();

                    UtilityServer.isEmsApiAvailable(host, port, value1 -> {

                        if (value1) { //Is online
                            loginHelper.doLogin(host, port, new ISimpleOperationCallback<LoginDTO>() {
                                @Override
                                public void onSuccess(final LoginDTO loginDTO) {

                                    SettingsManager.iDB().setAvailableProfiles(loginDTO.availableProfiles);

                                    SettingsManager.i().createUserSession();
                                    SettingsManager.i().getUser().setFullname(!UtilityString.isNullOrEmpty(loginDTO.full_name) ? loginDTO.full_name : username.get());


                                    mActivity.runOnUiThread(() -> onLoginSuccess(
                                            "Benvenuto",
                                            Html.fromHtml("Ciao <b>" + loginDTO.full_name + "</b>, la Integry le augura di svolgere al meglio il suo lavoro"),
                                            host, port, loginDTO.availableProfiles));


                                }

                                @Override
                                public void onFailed(final Exception ex) {
                                    onLoginFailed(new SpannableString(ex.getMessage()));
                                }
                            });


                        } else { //Is not online
                            onLoginFailed(Html.fromHtml(String.format(mActivity.getText(R.string.server_not_reachable).toString(), host, port)));
                        }

                    });
                }

                @Override
                public void onFailed(Exception ex) {
                    onLoginFailed(Html.fromHtml(String.format(mActivity.getText(R.string.server_cod_azienda_not_valid).toString(), codAzienda.get())));
                }
            });

        }
    }


    private void loadDepo(String host, int port, Runnable onComplete) {

        SettingsManager.i().getServer().setCodAzienda(codAzienda.get());
        SettingsManager.i().getServer().setHost(host);
        SettingsManager.i().getServer().setPort(port);

        SettingsManager.i().getUser().setUsername(username.get());
        SettingsManager.i().getUser().setPassword(password.get());

        SystemRESTConsumer.getAvailableCodMdeps(availableCodMdeps -> {
            SettingsManager.iDB().setAvailableCodMdep(availableCodMdeps);

            if (availableCodMdeps == null || availableCodMdeps.size() == 0) {
                onLoginFailed(Html.fromHtml(String.format(mActivity.getText(R.string.no_codmdep_available).toString())));
                return;
            }

            SettingsManager.i().getUserSession().setDepo(availableCodMdeps.get(0));


            if (onComplete != null) onComplete.run();
        }, ex -> {
            //BOH
            onLoginFailed(new SpannableString(ex.getMessage()));
        });
    }


    private void onLoginFailed(final Spanned message) {
        mProgress.dismiss();
        loginButtonEnabled.set(true);
        mActivity.runOnUiThread(() -> DialogSimpleMessageView.makeErrorDialog(
                message,
                null,
                null)
                .show(mActivity.getSupportFragmentManager(), "tag"));
    }


    private void onLoginSuccess(final String title, final Spanned message, final String host, final int port, final List<String> availableProfiles) {
        mProgress.dismiss();
        mActivity.runOnUiThread(() -> DialogSimpleMessageView.makeSuccessDialog(
                title,
                message,
                null,
                () -> showProfileDBSelectionDialog(host, port, availableProfiles))
                .show(mActivity.getSupportFragmentManager(), "tag"));
    }

    private void showProfileDBSelectionDialog(final String host, final int port, final List<String> availableProfiles) {
        if (availableProfiles != null && availableProfiles.size() == 1) {
            SettingsManager.i().getUserSession().setProfileDB(availableProfiles.get(0));

            loadDepo(host, port, this::onLoginCompleted);
        } else {

            // setup the alert builder
            AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
            builder.setTitle(R.string.action_choose_profile_db);

            // add a list
            String[] profiles = new String[availableProfiles.size()];
            profiles = availableProfiles.toArray(profiles);
            builder.setItems(profiles, (dialog, which) -> {
                SettingsManager.i().getUserSession().setProfileDB(availableProfiles.get(which));

                loadDepo(host, port, this::onLoginCompleted);
            });

            // create and show the alert dialog
            AlertDialog dialog = builder.create();
            dialog.show();
        }
    }

    public void onLoginCompleted() {
        loginButtonEnabled.set(true);
        SettingsManager.update();

        startSplashActivity();
    }


    private void startSplashActivity() {
        mActivity.finish();
        Intent myIntent = new Intent(mActivity, SplashActivity.class);
        mActivity.startActivity(myIntent);
    }

}
