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

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.core.misc.impl.authen.mtan.MtanHandlerException;
import com.airlock.iam.flow.api.domain.model.step.FlowCondition;
import com.airlock.iam.flow.shared.application.configuration.condition.MtanHasActivationLetterConditionConfig;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import lombok.NonNull;

@LogicForConfig(MtanHasActivationLetterConditionConfig.class)
public class MtanHasActivationLetterCondition implements FlowCondition {
   @NonNull
   private final Provider<PrincipalInfo> user;
   @NonNull
   private final MtanHasActivationLetterConditionConfig config;

   @Inject
   public MtanHasActivationLetterCondition(@NonNull Provider<PrincipalInfo> user, @NonNull MtanHasActivationLetterConditionConfig config) {
      if (user == null) {
         throw new NullPointerException("user is marked non-null but is null");
      }

      if (config == null) {
         throw new NullPointerException("config is marked non-null but is null");
      }

      this.user = user;
      this.config = config;
   }

   @Override
   public boolean isFulfilled() {
      String username = this.username();

      try {
         return this.config.getMtanHandler().isIakAvailable(username);
      } catch (MtanHandlerException e) {
         throw new FailureException(String.format("An exception occurred while determining if user '%s' has an mTan activation letter", username), e);
      }
   }

   private String username() {
      return ((PrincipalInfo)this.user.get()).getKnownIdentity().orElseThrow().id().getValue();
   }

   @Override
   public String displayName() {
      return "Has mTAN Activation Letter";
   }

   @SuppressFBWarnings(justification = "generated code")
   public static MtanHasActivationLetterCondition.MtanHasActivationLetterConditionBuilder builder() {
      return new MtanHasActivationLetterCondition.MtanHasActivationLetterConditionBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class MtanHasActivationLetterConditionBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Provider<PrincipalInfo> user;
      @SuppressFBWarnings(justification = "generated code")
      private MtanHasActivationLetterConditionConfig config;

      @SuppressFBWarnings(justification = "generated code")
      MtanHasActivationLetterConditionBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public MtanHasActivationLetterCondition.MtanHasActivationLetterConditionBuilder user(@NonNull Provider<PrincipalInfo> user) {
         if (user == null) {
            throw new NullPointerException("user is marked non-null but is null");
         }

         this.user = user;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MtanHasActivationLetterCondition.MtanHasActivationLetterConditionBuilder config(@NonNull MtanHasActivationLetterConditionConfig config) {
         if (config == null) {
            throw new NullPointerException("config is marked non-null but is null");
         }

         this.config = config;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MtanHasActivationLetterCondition build() {
         return new MtanHasActivationLetterCondition(this.user, this.config);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "MtanHasActivationLetterCondition.MtanHasActivationLetterConditionBuilder(user=" + this.user + ", config=" + this.config + ")";
      }
   }
}
