package be.iminds.ilabt.jfed.connectivity_tester;

import be.iminds.ilabt.jfed.lowlevel.AnyCredential;
import be.iminds.ilabt.jfed.lowlevel.GeniUser;
import be.iminds.ilabt.jfed.lowlevel.GeniUserProvider;
import be.iminds.ilabt.jfed.lowlevel.SfaCredential;
import be.iminds.ilabt.jfed.lowlevel.api_wrapper.UserAndSliceApiWrapper;
import be.iminds.ilabt.jfed.lowlevel.api_wrapper.impl.AutomaticUserAndSliceApiWrapper;
import be.iminds.ilabt.jfed.lowlevel.connection.JFedConnectionProvider;
import be.iminds.ilabt.jfed.preferences.JFedPreferences;
import be.iminds.ilabt.jfed.util.JavaFXLogger;

import java.util.Date;
import java.util.List;
import java.util.Objects;

public class GetSACredentialTest implements ConnectivityTest {

    private static final int TIMEOUT = 5000; //5 seconds

    private final String description = "GetCredential @ user authority";
    private final String category = "GetCredential";

    private final GeniUserProvider geniUserProvider;
    private final JFedConnectionProvider jFedConnectionProvider;
    private final JFedPreferences jFedPreferences;
    private final JavaFXLogger logger;
    private final AutomaticUserAndSliceApiWrapper.AutomaticUserAndSliceApiWrapperFactory automaticUserAndSliceApiWrapperFactory;

    public GetSACredentialTest(GeniUserProvider geniUserProvider, JFedConnectionProvider jFedConnectionProvider, JavaFXLogger logger, JFedPreferences jFedPreferences,
                               AutomaticUserAndSliceApiWrapper.AutomaticUserAndSliceApiWrapperFactory automaticUserAndSliceApiWrapperFactory) {
        this.geniUserProvider = geniUserProvider;
        this.jFedConnectionProvider = jFedConnectionProvider;
        this.logger = logger;
        this.jFedPreferences = jFedPreferences;
        this.automaticUserAndSliceApiWrapperFactory = automaticUserAndSliceApiWrapperFactory;
    }

    @Override
    public String getName() {
        return String.format("[%s] %s", category, description);
    }

    @Override
    public boolean isLoginRequired() {
        return true;
    }

    @Override
    public ConnectivityTestResult call() {
        try {
            GeniUser geniUser = null;
            if (geniUserProvider.isUserLoggedIn())
                geniUser = geniUserProvider.getLoggedInGeniUser();
            else {
                return new ConnectivityTestResult(Status.FAILED, "No user logged in. Cannot test.");
            }
            if (geniUser == null)
                return new ConnectivityTestResult(Status.FAILED,
                        "No user logged in (logged in user is null). Cannot test");


            if (geniUser.getUserUrn() == null)
                return new ConnectivityTestResult(Status.FAILED,
                        "No user logged in (logged in user URN is null). Cannot test");

            UserAndSliceApiWrapper sa =
                    automaticUserAndSliceApiWrapperFactory.create();

            List<AnyCredential> creds = sa.getUserCredentials(logger, geniUser.getUserUrn());
            if (creds == null) {
                return new ConnectivityTestResult(Status.FAILED, "Did not successfully fetch credential (null reply) for " + geniUser.getUserUrnString());
            }
            if (creds.isEmpty()) {
                return new ConnectivityTestResult(Status.FAILED, "Did not successfully fetch credential (empty list reply) for " + geniUser.getUserUrnString());
            }
            for (AnyCredential cred : creds) {
                if (cred.getCredentialXml() == null) {
                    return new ConnectivityTestResult(Status.FAILED, "did not successfully fetch credential (xml null) for " + geniUser.getUserUrnString());

                }
                if (cred instanceof SfaCredential) {
                    SfaCredential sfaCred = (SfaCredential) cred;

                    if (!Objects.equals(sfaCred.getOwnerUrn(), geniUser.getUserUrnString())) {
                        return new ConnectivityTestResult(Status.FAILED, "credential was recieved, but was for user " + sfaCred.getOwnerUrn() + " instead of for expected user " + geniUser.getUserUrnString());
                    }
                }

                Date now = new Date();
                if (cred.getExpiresDate() != null && cred.getExpiresDate().before(now)) {
                    return new ConnectivityTestResult(Status.FAILED, "received credential has already expired (" + cred.getExpiresDate() + ") for user" + geniUser.getUserUrnString());
                }
            }

            //credential ok
            return new ConnectivityTestResult(Status.SUCCEEDED, "GetCredential success for user " + geniUser.getUserUrnString());

        } catch (Exception e) {
            return new ConnectivityTestResult(Status.FAILED, "Failed to get User Credential. msg:" + e.getMessage(), e);
        }
    }
}
