package com.airlock.iam.saml2.infrastructure.session;

import com.airlock.iam.base.api.domain.model.exception.ViolationException;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.flow.shared.api.domain.model.session.UserSession;
import com.airlock.iam.saml2.domain.model.session.FlowFederationSession;
import com.airlock.iam.saml2.domain.model.session.FlowFederationSessionRepository;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

public final class FlowFederationSessionRepositoryImpl implements FlowFederationSessionRepository {
   private static final ELogger LOG = ELoggerFactory.getLogger(FlowFederationSessionRepositoryImpl.class);
   private final Provider<UserSession> userSession;

   @Inject
   public FlowFederationSessionRepositoryImpl(Provider<UserSession> userSession) {
      this.userSession = userSession;
   }

   @Override
   public Optional<FlowFederationSession> getFederationSession() {
      return ((UserSession)this.userSession.get()).findUserSessionAttribute(FlowFederationSession.class);
   }

   @Override
   public void removeFederationSession() {
      LOG.debug("Removing flow federation session from user session");
      ((UserSession)this.userSession.get()).removeUserSessionAttribute(FlowFederationSession.class);
   }

   @Override
   public void putFederationSession(FlowFederationSession federationSession) {
      LOG.debug(String.format("Adding flow federation session with ID %s to user session", LogUtil.logSafeQuote(federationSession.getSessionId())));
      ((UserSession)this.userSession.get()).addUserSessionAttribute(federationSession);
   }

   @Override
   public void updateFederationSession(FlowFederationSession session) {
      LOG.debug(String.format("Updating flow federation session with ID %s in user session", LogUtil.logSafeQuote(session.getSessionId())));
      Optional<FlowFederationSession> previousSession = this.getFederationSession();
      if (previousSession.isPresent() && !previousSession.get().getSessionId().equals(session.getSessionId())) {
         throw new ViolationException(
            "Unexpected flow federation session. Expected %s, but got %s with a different session id".formatted(session, previousSession.get())
         );
      }

      this.putFederationSession(session);
   }

   @Override
   public FlowFederationSession createNewFederationSession() {
      FlowFederationSession newSession = FlowFederationSession.emptySession();
      this.putFederationSession(newSession);
      return newSession;
   }
}
