package com.airlock.iam.oauth2.domain.model;

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.common.api.domain.model.user.UserIdentity;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.flow.api.domain.model.step.FlowStep;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.log.api.signing.SigningLogger;
import com.airlock.iam.oauth2.application.configuration.step.OAuth2SessionResetStepConfig;
import com.airlock.iam.oauth2.domain.model.session.OAuth2GlobalSessionsRepository;
import com.airlock.iam.oauth2.domain.model.session.OperationStatistics;
import jakarta.inject.Inject;
import jakarta.inject.Provider;

@LogicForConfig(OAuth2SessionResetStepConfig.class)
public final class OAuth2SessionResetStep implements FlowStep {
   private static final ELogger LOG = ELoggerFactory.getLogger(OAuth2SessionResetStep.class);
   private final Provider<PrincipalInfo> user;
   private final Provider<OAuth2GlobalSessionsRepository> repository;
   private final SigningLogger signingLogger;

   @Inject
   public OAuth2SessionResetStep(Provider<PrincipalInfo> user, Provider<OAuth2GlobalSessionsRepository> repository, SigningLogger signingLogger) {
      this.user = user;
      this.repository = repository;
      this.signingLogger = signingLogger;
   }

   @Override
   public StepResult initialize() {
      UserId userId = ((PrincipalInfo)this.user.get())
         .getKnownIdentity()
         .map(UserIdentity::id)
         .orElseThrow(() -> new FailureException("User must be known to reset OAuth 2.0 sessions"));
      OperationStatistics stats = ((OAuth2GlobalSessionsRepository)this.repository.get()).deleteAllSessionsByUser(userId);
      if (stats.getTokenCount() <= 0 && stats.getSessionCount() <= 0) {
         LOG.info("No OAuth 2.0 tokens or sessions deleted for user " + LogUtil.quote(userId));
      } else {
         this.signingLogger
            .log(
               "Deleted "
                  + LogUtil.pluralize(stats.getTokenCount(), "OAuth 2.0 token")
                  + " and "
                  + LogUtil.pluralize(stats.getSessionCount(), "session")
                  + " for user "
                  + LogUtil.quote(userId)
            );
      }

      return this.stepResultFactory().success().build();
   }

   @Override
   public String getDescription() {
      return "OAuth 2.0 Session Reset Step";
   }
}
