package com.airlock.iam.authentication.application.configuration.emailotp;

import com.airlock.iam.common.api.application.configuration.valueprovider.StringValueProviderConfig;
import com.airlock.iam.common.api.domain.service.email.EmailService;
import com.airlock.iam.common.application.configuration.masking.MaskingConfig;
import com.airlock.iam.core.misc.authen.SecretStringGenerator;
import com.airlock.iam.flow.api.application.configuration.dynamicactivation.DynamicStepActivationConfig;
import com.airlock.iam.flow.api.application.configuration.selection.FlowConditionConfig;
import com.airlock.iam.flow.api.application.configuration.step.InteractiveGotoTargetConfig;
import com.airlock.iam.flow.api.application.configuration.step.StepIdConfig;
import com.airlock.iam.flow.api.application.configuration.tag.TagConfig;
import com.airlock.iam.flow.api.application.configuration.valueprovider.ValueMapProviderConfig;
import com.airlock.iam.flow.shared.api.application.configuration.message.EmailMessageProviderConfig;
import com.airlock.iam.flow.shared.application.configuration.emailotp.CommonEmailOtpCheckingStepConfig;
import com.airlock.iam.flow.shared.domain.model.emailotp.EmailOtpCheckingStep;
import com.airlock.iam.flow.types.api.application.configuration.step.StepConfigForAuthenticationFlows;
import com.airlock.iam.plugin.api.annotation.config.Groups;
import com.airlock.iam.plugin.api.annotation.config.NextActions;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Plugin(
   description = "<p>Configuration for an authentication flow step to check an OTP sent via email. This Email OTP Authentication\nStep supports template based emails.</p>\n<b>Note:</b> Emails are neither confidential nor authentic (i.e. the user cannot be sure that the email is\nreally from Airlock IAM and Airlock IAM cannot be sure that the email is delivered to the correct user).\nTherefore, this step must not be used for high-security applications.</p>",
   displayName = "Email OTP Authentication Step"
)
@Groups(groupSequence = {"Basic Settings", "Security Settings", "Tags/Guards", "Flow Control", "Advanced Settings"}, openGroups = "Basic Settings")
@NextActions(EmailOtpCheckingStep.EmailOtpStepActions.class)
public final class EmailOtpAuthenticationStepConfig extends CommonEmailOtpCheckingStepConfig implements StepConfigForAuthenticationFlows {
   private EmailOtpAuthenticationStepConfig(
      FlowConditionConfig skipCondition,
      FlowConditionConfig preCondition,
      boolean requiresActivation,
      List<TagConfig> tagsOnSuccess,
      @Nullable StepIdConfig stepId,
      List<InteractiveGotoTargetConfig> interactiveGotoTargets,
      List<DynamicStepActivationConfig> dynamicStepActivations,
      Map<String, StepIdConfig> onFailureGotos,
      List<ValueMapProviderConfig> customResponseAttributes,
      List<ValueMapProviderConfig> customFailureResponseAttributes,
      EmailService emailService,
      EmailMessageProviderConfig emailMessageProvider,
      StringValueProviderConfig recipientAddress,
      boolean messageTemplateIsHtml,
      boolean ignoreCase,
      int otpValiditySeconds,
      int maxRetries,
      int maxResends,
      SecretStringGenerator otpGenerator,
      String authenticationMethodId,
      MaskingConfig maskingSettings
   ) {
      super(
         skipCondition,
         preCondition,
         requiresActivation,
         tagsOnSuccess,
         stepId,
         interactiveGotoTargets,
         dynamicStepActivations,
         onFailureGotos,
         customResponseAttributes,
         customFailureResponseAttributes,
         emailService,
         emailMessageProvider,
         recipientAddress,
         messageTemplateIsHtml,
         ignoreCase,
         otpValiditySeconds,
         maxRetries,
         maxResends,
         otpGenerator,
         authenticationMethodId,
         maskingSettings
      );
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public EmailOtpAuthenticationStepConfig() {
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class EmailOtpAuthenticationStepConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private FlowConditionConfig skipCondition;
      @SuppressFBWarnings(justification = "generated code")
      private FlowConditionConfig preCondition;
      @SuppressFBWarnings(justification = "generated code")
      private boolean requiresActivation;
      @SuppressFBWarnings(justification = "generated code")
      private List<TagConfig> tagsOnSuccess;
      @SuppressFBWarnings(justification = "generated code")
      private StepIdConfig stepId;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<InteractiveGotoTargetConfig> interactiveGotoTargets;
      @SuppressFBWarnings(justification = "generated code")
      private List<DynamicStepActivationConfig> dynamicStepActivations;
      @SuppressFBWarnings(justification = "generated code")
      private Map<String, StepIdConfig> onFailureGotos;
      @SuppressFBWarnings(justification = "generated code")
      private List<ValueMapProviderConfig> customResponseAttributes;
      @SuppressFBWarnings(justification = "generated code")
      private List<ValueMapProviderConfig> customFailureResponseAttributes;
      @SuppressFBWarnings(justification = "generated code")
      private EmailService emailService;
      @SuppressFBWarnings(justification = "generated code")
      private EmailMessageProviderConfig emailMessageProvider;
      @SuppressFBWarnings(justification = "generated code")
      private StringValueProviderConfig recipientAddress;
      @SuppressFBWarnings(justification = "generated code")
      private boolean messageTemplateIsHtml;
      @SuppressFBWarnings(justification = "generated code")
      private boolean ignoreCase;
      @SuppressFBWarnings(justification = "generated code")
      private int otpValiditySeconds;
      @SuppressFBWarnings(justification = "generated code")
      private int maxRetries;
      @SuppressFBWarnings(justification = "generated code")
      private int maxResends;
      @SuppressFBWarnings(justification = "generated code")
      private SecretStringGenerator otpGenerator;
      @SuppressFBWarnings(justification = "generated code")
      private String authenticationMethodId;
      @SuppressFBWarnings(justification = "generated code")
      private MaskingConfig maskingSettings;

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

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder skipCondition(FlowConditionConfig skipCondition) {
         this.skipCondition = skipCondition;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder preCondition(FlowConditionConfig preCondition) {
         this.preCondition = preCondition;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder requiresActivation(boolean requiresActivation) {
         this.requiresActivation = requiresActivation;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder tagsOnSuccess(List<TagConfig> tagsOnSuccess) {
         this.tagsOnSuccess = tagsOnSuccess;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder stepId(@Nullable StepIdConfig stepId) {
         this.stepId = stepId;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder interactiveGotoTarget(InteractiveGotoTargetConfig interactiveGotoTarget) {
         if (this.interactiveGotoTargets == null) {
            this.interactiveGotoTargets = new ArrayList<>();
         }

         this.interactiveGotoTargets.add(interactiveGotoTarget);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder interactiveGotoTargets(
         Collection<? extends InteractiveGotoTargetConfig> interactiveGotoTargets
      ) {
         if (interactiveGotoTargets == null) {
            throw new NullPointerException("interactiveGotoTargets cannot be null");
         }

         if (this.interactiveGotoTargets == null) {
            this.interactiveGotoTargets = new ArrayList<>();
         }

         this.interactiveGotoTargets.addAll(interactiveGotoTargets);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder clearInteractiveGotoTargets() {
         if (this.interactiveGotoTargets != null) {
            this.interactiveGotoTargets.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder dynamicStepActivations(
         List<DynamicStepActivationConfig> dynamicStepActivations
      ) {
         this.dynamicStepActivations = dynamicStepActivations;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder onFailureGotos(Map<String, StepIdConfig> onFailureGotos) {
         this.onFailureGotos = onFailureGotos;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder customResponseAttributes(
         List<ValueMapProviderConfig> customResponseAttributes
      ) {
         this.customResponseAttributes = customResponseAttributes;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder customFailureResponseAttributes(
         List<ValueMapProviderConfig> customFailureResponseAttributes
      ) {
         this.customFailureResponseAttributes = customFailureResponseAttributes;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder emailService(EmailService emailService) {
         this.emailService = emailService;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder emailMessageProvider(EmailMessageProviderConfig emailMessageProvider) {
         this.emailMessageProvider = emailMessageProvider;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder recipientAddress(StringValueProviderConfig recipientAddress) {
         this.recipientAddress = recipientAddress;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder messageTemplateIsHtml(boolean messageTemplateIsHtml) {
         this.messageTemplateIsHtml = messageTemplateIsHtml;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder ignoreCase(boolean ignoreCase) {
         this.ignoreCase = ignoreCase;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder otpValiditySeconds(int otpValiditySeconds) {
         this.otpValiditySeconds = otpValiditySeconds;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder maxRetries(int maxRetries) {
         this.maxRetries = maxRetries;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder maxResends(int maxResends) {
         this.maxResends = maxResends;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder otpGenerator(SecretStringGenerator otpGenerator) {
         this.otpGenerator = otpGenerator;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder authenticationMethodId(String authenticationMethodId) {
         this.authenticationMethodId = authenticationMethodId;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder maskingSettings(MaskingConfig maskingSettings) {
         this.maskingSettings = maskingSettings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public EmailOtpAuthenticationStepConfig build() {
         return new EmailOtpAuthenticationStepConfig(
            this.skipCondition,
            this.preCondition,
            this.requiresActivation,
            this.tagsOnSuccess,
            this.stepId,
            switch (this.interactiveGotoTargets == null ? 0 : this.interactiveGotoTargets.size()) {
               case 0 -> Collections.emptyList();
               case 1 -> Collections.singletonList(this.interactiveGotoTargets.get(0));
               default -> Collections.unmodifiableList(new ArrayList<>(this.interactiveGotoTargets));
            },
            this.dynamicStepActivations,
            this.onFailureGotos,
            this.customResponseAttributes,
            this.customFailureResponseAttributes,
            this.emailService,
            this.emailMessageProvider,
            this.recipientAddress,
            this.messageTemplateIsHtml,
            this.ignoreCase,
            this.otpValiditySeconds,
            this.maxRetries,
            this.maxResends,
            this.otpGenerator,
            this.authenticationMethodId,
            this.maskingSettings
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "EmailOtpAuthenticationStepConfig.EmailOtpAuthenticationStepConfigBuilder(skipCondition="
            + this.skipCondition
            + ", preCondition="
            + this.preCondition
            + ", requiresActivation="
            + this.requiresActivation
            + ", tagsOnSuccess="
            + this.tagsOnSuccess
            + ", stepId="
            + this.stepId
            + ", interactiveGotoTargets="
            + this.interactiveGotoTargets
            + ", dynamicStepActivations="
            + this.dynamicStepActivations
            + ", onFailureGotos="
            + this.onFailureGotos
            + ", customResponseAttributes="
            + this.customResponseAttributes
            + ", customFailureResponseAttributes="
            + this.customFailureResponseAttributes
            + ", emailService="
            + this.emailService
            + ", emailMessageProvider="
            + this.emailMessageProvider
            + ", recipientAddress="
            + this.recipientAddress
            + ", messageTemplateIsHtml="
            + this.messageTemplateIsHtml
            + ", ignoreCase="
            + this.ignoreCase
            + ", otpValiditySeconds="
            + this.otpValiditySeconds
            + ", maxRetries="
            + this.maxRetries
            + ", maxResends="
            + this.maxResends
            + ", otpGenerator="
            + this.otpGenerator
            + ", authenticationMethodId="
            + this.authenticationMethodId
            + ", maskingSettings="
            + this.maskingSettings
            + ")";
      }
   }
}
