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

import com.airlock.iam.common.application.configuration.rememberme.JspRememberMeConfig;
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.AbstractFlowStepConfig;
import com.airlock.iam.flow.api.application.configuration.step.InteractiveGotoTargetConfig;
import com.airlock.iam.flow.api.application.configuration.step.NonInteractiveStepConfig;
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.types.api.application.configuration.step.StepConfigForAuthenticationFlows;
import com.airlock.iam.plugin.api.annotation.config.Groups;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.GroupProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Plugin(
   description = "Step that identifies the user by means of a Remember-Me token.<p>The step is skipped if no valid token is found in the request.</p>",
   displayName = "Remember-Me User Identifying Step"
)
@Groups(openGroups = "Basic Settings", groupSequence = {"Basic Settings", "Tags/Guards", "Flow Control", "Advanced Settings"})
public class RememberMeUserIdentifyingStepConfig extends AbstractFlowStepConfig implements NonInteractiveStepConfig, StepConfigForAuthenticationFlows {
   public static final String REMEMBER_ME_USER_IDENTIFYING_STEP_PLUGIN_NAME = "Remember-Me User Identifying Step";
   @GroupProperty(groupIdentifier = "Basic Settings")
   @PluginProperty(
      description = "If configured, Remember-Me cookies which originated from the JSP-Loginapp will be automatically migrated to the the new flow-based Remember-Me tokens. Be aware that invalid Remember-Me cookies will be forcibly removed from the client.",
      displayName = "Migrate JSP Remember-Me Cookies",
      optional = true
   )
   private JspRememberMeConfig migrateJspRememberMeCookies;
   @GroupProperty(groupIdentifier = "Advanced Settings")
   @StringProperty(
      description = "The identifier of the authentication method for this step. Since the authentication method is also the identifier for failed login attempts for this step, distinct identifiers must be chosen if multiple instances of the same step type are used to check different credentials (e.g., two password step instances check two different passwords).<p>Example: a system tracks two passwords per user. Password 1 is used in flow A, password 2 in flow B. These two steps must have distinct 'Authentication Method Ids', e.g. PASSWORD1 and PASSWORD2.</p>If only one identifier (e.g. \"PASSWORD\") is used, this may allow brute force attacks on the password as follows. Assuming an attacker knows the user's password 1, they get an unlimited number of attempts on flow B, as the 'PASSWORD' counter can repeatedly be reset to 0 by performing a successful login on flow A.<p>To prevent such attacks, use two different counters by setting the authentication methods, for example, to PASSWORD1 and PASSWORD2, respectively.</p>",
      displayName = "Authentication Method ID",
      defaultValue = "REMEMBER_ME",
      maxLength = 23,
      optional = true
   )
   private String authenticationMethodId;

   public Optional<JspRememberMeConfig> getMigrateJspRememberMeCookies() {
      return Optional.ofNullable(this.migrateJspRememberMeCookies);
   }

   protected RememberMeUserIdentifyingStepConfig(
      FlowConditionConfig skipCondition,
      FlowConditionConfig preCondition,
      boolean requiresActivation,
      List<TagConfig> tagsOnSuccess,
      @Nullable StepIdConfig stepId,
      Map<String, StepIdConfig> onFailureGotos,
      List<ValueMapProviderConfig> customResponseAttributes,
      List<ValueMapProviderConfig> customFailureResponseAttributes,
      List<InteractiveGotoTargetConfig> interactiveGotoTargets,
      List<DynamicStepActivationConfig> dynamicStepActivations,
      String authenticationMethodId,
      @Nullable JspRememberMeConfig migrateJspRememberMeCookies
   ) {
      super(skipCondition, preCondition, requiresActivation, tagsOnSuccess, stepId, onFailureGotos, customResponseAttributes, customFailureResponseAttributes);
      this.authenticationMethodId = authenticationMethodId;
      this.migrateJspRememberMeCookies = migrateJspRememberMeCookies;
   }

   public String getAuthenticationMethodId() {
      return this.authenticationMethodId;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class RememberMeUserIdentifyingStepConfigBuilder {
      @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 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 List<InteractiveGotoTargetConfig> interactiveGotoTargets;
      @SuppressFBWarnings(justification = "generated code")
      private List<DynamicStepActivationConfig> dynamicStepActivations;
      @SuppressFBWarnings(justification = "generated code")
      private String authenticationMethodId;
      @SuppressFBWarnings(justification = "generated code")
      private JspRememberMeConfig migrateJspRememberMeCookies;

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

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

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

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

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

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

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public RememberMeUserIdentifyingStepConfig.RememberMeUserIdentifyingStepConfigBuilder interactiveGotoTargets(
         List<InteractiveGotoTargetConfig> interactiveGotoTargets
      ) {
         this.interactiveGotoTargets = interactiveGotoTargets;
         return this;
      }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public RememberMeUserIdentifyingStepConfig.RememberMeUserIdentifyingStepConfigBuilder migrateJspRememberMeCookies(
         @Nullable JspRememberMeConfig migrateJspRememberMeCookies
      ) {
         this.migrateJspRememberMeCookies = migrateJspRememberMeCookies;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RememberMeUserIdentifyingStepConfig build() {
         return new RememberMeUserIdentifyingStepConfig(
            this.skipCondition,
            this.preCondition,
            this.requiresActivation,
            this.tagsOnSuccess,
            this.stepId,
            this.onFailureGotos,
            this.customResponseAttributes,
            this.customFailureResponseAttributes,
            this.interactiveGotoTargets,
            this.dynamicStepActivations,
            this.authenticationMethodId,
            this.migrateJspRememberMeCookies
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "RememberMeUserIdentifyingStepConfig.RememberMeUserIdentifyingStepConfigBuilder(skipCondition="
            + this.skipCondition
            + ", preCondition="
            + this.preCondition
            + ", requiresActivation="
            + this.requiresActivation
            + ", tagsOnSuccess="
            + this.tagsOnSuccess
            + ", stepId="
            + this.stepId
            + ", onFailureGotos="
            + this.onFailureGotos
            + ", customResponseAttributes="
            + this.customResponseAttributes
            + ", customFailureResponseAttributes="
            + this.customFailureResponseAttributes
            + ", interactiveGotoTargets="
            + this.interactiveGotoTargets
            + ", dynamicStepActivations="
            + this.dynamicStepActivations
            + ", authenticationMethodId="
            + this.authenticationMethodId
            + ", migrateJspRememberMeCookies="
            + this.migrateJspRememberMeCookies
            + ")";
      }
   }
}
