package org.gcube.keycloak.account;

import java.net.URI;

import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

import org.gcube.keycloak.avatar.storage.AvatarStorageProvider;
import org.gcube.keycloak.event.OrchestratorEventPublisherProviderFactory;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.resources.RealmsResource;

public class DeleteAccountResource {

    protected static final Logger logger = Logger.getLogger(DeleteAccountResource.class);

//    public static final String STATE_CHECKER_ATTRIBUTE = "state_checker";
//    public static final String STATE_CHECKER_PARAMETER = "stateChecker";

    private final KeycloakSession session;
    private final AuthenticationManager.AuthResult auth;

    public DeleteAccountResource(KeycloakSession session) {
        logger.info("Created new DeleteAccountResource object");
        this.session = session;
        auth = new AppAuthManager().authenticateIdentityCookie(session, session.getContext().getRealm());
    }

    @NoCache
    @POST()
    @Path("delete")
//    public Response performDeleteAccount(@FormParam(STATE_CHECKER_PARAMETER) String stateChecker) {
    public Response performDeleteAccount() {
        if (auth == null) {
            logger.debug("Invoked DELETE without authorization");
            throw new NotAuthorizedException("Cookie");
        }
//        String requiredStateChecker = session.getAttribute(STATE_CHECKER_ATTRIBUTE, String.class);
//        if (!requiredStateChecker.equals(stateChecker)) {
//            throw new ForbiddenException("State");
//        }
        logger.info("Invoked perform delete account");

        logger.debug("Getting realm model from auth session");
        RealmModel realm = auth.getSession().getRealm();

        logger.debug("Getting user model from auth");
        UserModel user = auth.getUser();

        try {
            if (!session.getTransactionManager().isActive()) {
                logger.debug("Beginning a new transaction on transaction manager");
                session.getTransactionManager().begin();
            }

            logger.debug("Finding user model and setting it as not enabled in realm");
            session.users().getUserById(realm, user.getId()).setEnabled(false);

            if (session.getTransactionManager().isActive()) {
                logger.debug("Committing the transaction on transaction manager");
                session.getTransactionManager().commit();
            }
        } catch (Exception e) {
            logger.error("Cannot perform user model modifications", e);
        }

        logger.debug("Getting the the configured avatar storage provider");
        AvatarStorageProvider avatarStorageProvider = session.getProvider(AvatarStorageProvider.class);
        if (avatarStorageProvider != null) {
            logger.tracev("Configured avatar storage provider type is {0}", avatarStorageProvider.getClass().getName());
            logger.debug("Deleting user's avatar from the configured storage");
            avatarStorageProvider.deleteAvatarImage(realm, user);
        } else {
            logger.warn("Cannot perform avatar import ince the avatar storage provider is null");
        }

        logger.debug("Sending delete account event to the orchestrator");
        new OrchestratorEventPublisherProviderFactory().create(session)
                .publish(new DeleteAccountEvent(user, realm));

        logger.debug("Forcing logout from all active sessions");
        session.sessions().removeUserSessions(realm);

        URI auccountLoginUri = RealmsResource.accountUrl(session.getContext().getUri().getBaseUriBuilder())
                .build(realm.getName());

        logger.debugf("Finally redirecting to the account form login: %s", auccountLoginUri);
        return Response.status(302).location(auccountLoginUri).build();
    }

}
