package com.airlock.iam.flow.shared.domain.model.cronto;

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.persistency.exception.PersisterException;
import com.airlock.iam.common.domain.model.cronto.event.CrontoEventFactory;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.core.misc.cronto.CrontoHandler;
import com.airlock.iam.core.misc.impl.token.cronto.CrontoLetterToken;
import com.airlock.iam.flow.api.domain.model.step.FlowStep;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.flow.shared.application.configuration.cronto.CrontoLetterOrderStepConfig;
import com.airlock.iam.log.api.helpdesk.HelpdeskLogger;
import com.airlock.iam.log.api.signing.SigningLogger;
import jakarta.inject.Inject;
import jakarta.inject.Provider;

@LogicForConfig(CrontoLetterOrderStepConfig.class)
public final class CrontoLetterOrderStep implements FlowStep {
   private final Provider<PrincipalInfo> user;
   private final Provider<CrontoEventFactory> eventFactory;
   private final CrontoHandler crontoHandler;
   private final HelpdeskLogger helpdeskLogger;
   private final SigningLogger signingLogger;

   @Inject
   public CrontoLetterOrderStep(
      Provider<PrincipalInfo> user,
      Provider<CrontoEventFactory> eventFactory,
      CrontoHandler crontoHandler,
      HelpdeskLogger helpdeskLogger,
      SigningLogger signingLogger
   ) {
      this.user = user;
      this.eventFactory = eventFactory;
      this.crontoHandler = crontoHandler;
      this.helpdeskLogger = helpdeskLogger;
      this.signingLogger = signingLogger;
   }

   @Override
   public StepResult initialize() {
      UserId userId = ((PrincipalInfo)this.user.get()).getKnownIdentity().orElseThrow().id();
      this.signingLogger.log("Ordering new cronto activation letter for user " + LogUtil.quote(userId) + ".");

      try {
         if (this.crontoHandler.getAccountForUser(userId).isEmpty()) {
            this.crontoHandler.createNewAccountForUser(userId);
         }

         this.crontoHandler.deleteAllLetters(userId);
         CrontoLetterToken letter = this.crontoHandler.createActivationLetter(userId);
         this.crontoHandler.orderLetterPrinting(letter, userId);
         this.helpdeskLogger.log(userId, "User ordered new cronto activation letter.");
         ((CrontoEventFactory)this.eventFactory.get()).publishCrontoLetterOrderedEvent(userId);
         return this.stepResultFactory().success().build();
      } catch (PersisterException e) {
         throw new FailureException("Exception while ordering Cronto letter for " + userId, e);
      }
   }

   @Override
   public String getDescription() {
      return "Cronto Letter Order Step";
   }
}
