package com.airlock.iam.publicselfservice.domain.model.step;

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.common.domain.model.event.UserEventFactory;
import com.airlock.iam.common.domain.model.user.Lockable;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.flow.api.domain.model.session.FlowAttributeRepository;
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.helpdesk.HelpdeskLogger;
import com.airlock.iam.log.api.signing.SigningLogger;
import com.airlock.iam.publicselfservice.api.domain.model.PublicSelfServiceUser;
import com.airlock.iam.publicselfservice.application.configuration.steps.PublicSelfServiceUnlockUserStepConfig;
import com.airlock.iam.publicselfservice.domain.service.restrictions.TooManyUnlocksRestriction;
import jakarta.inject.Inject;
import jakarta.inject.Provider;

@LogicForConfig(PublicSelfServiceUnlockUserStepConfig.class)
public class PublicSelfServiceUnlockUserStep implements FlowStep {
   private static final ELogger LOG = ELoggerFactory.getLogger(PublicSelfServiceUnlockUserStep.class);
   private final Provider<PublicSelfServiceUser> resettableUser;
   private final Provider<Lockable> lockableUser;
   private final Provider<UserEventFactory> eventFactory;
   private final Provider<FlowAttributeRepository> attributes;
   private final HelpdeskLogger helpdeskLogger;
   private final SigningLogger signingLogger;

   @Inject
   public PublicSelfServiceUnlockUserStep(
      Provider<PublicSelfServiceUser> resettableUser,
      Provider<Lockable> lockableUser,
      Provider<UserEventFactory> eventFactory,
      Provider<FlowAttributeRepository> attributes,
      HelpdeskLogger helpdeskLogger,
      SigningLogger signingLogger
   ) {
      this.resettableUser = resettableUser;
      this.lockableUser = lockableUser;
      this.eventFactory = eventFactory;
      this.attributes = attributes;
      this.helpdeskLogger = helpdeskLogger;
      this.signingLogger = signingLogger;
   }

   @Override
   public StepResult initialize() {
      if (!((PublicSelfServiceUser)this.resettableUser.get()).isPublicSelfServiceAllowed()) {
         LOG.info("Not unlocking user " + this.quotedName() + " because public self-service is not allowed.");
         return this.stepResultFactory().skip().build();
      } else if (((Lockable)this.lockableUser.get()).isLocked()) {
         ((Lockable)this.lockableUser.get()).unlock();
         ((FlowAttributeRepository)this.attributes.get()).putOrMergeAttribute(new TooManyUnlocksRestriction.UnlocksInCurrentFlow(1));
         this.signingLogger.log("Unlocked user " + this.quotedName() + ".");
         this.helpdeskLogger.log(((PublicSelfServiceUser)this.resettableUser.get()).getIdentity().id(), "User performed self-unlock.");
         ((UserEventFactory)this.eventFactory.get()).publishUserUnlockedEvent(((PublicSelfServiceUser)this.resettableUser.get()).getIdentity().id());
         return this.stepResultFactory().success().build();
      } else {
         this.helpdeskLogger.log(((PublicSelfServiceUser)this.resettableUser.get()).getIdentity().id(), "Skipping self-unlock because user is not locked.");
         return this.stepResultFactory().skip().build();
      }
   }

   private String quotedName() {
      return LogUtil.quote(((PublicSelfServiceUser)this.resettableUser.get()).getIdentity().id());
   }

   @Override
   public String getDescription() {
      return "Public Self-Service Unlock User Step";
   }
}
