package com.airlock.iam.flow.shared.application.configuration.step;

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.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.flow.types.api.application.configuration.step.StepConfigForAuthorizationFlows;
import com.airlock.iam.flow.types.api.application.configuration.step.StepConfigForPublicSelfServiceFlows;
import com.airlock.iam.flow.types.api.application.configuration.step.StepConfigForSelfServiceFlows;
import com.airlock.iam.flow.types.api.application.configuration.step.StepConfigForTechClientRegFlows;
import com.airlock.iam.flow.types.api.application.configuration.step.StepConfigForTransactionApprovalFlows;
import com.airlock.iam.flow.types.api.application.configuration.step.StepConfigForUserSelfRegFlows;
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.StringProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Plugin(
   description = "A flow step to abort and fail the current flow. This step always fails with the configured error code and increments the number of failed attempts for the configured authentication method. If no failed attempts should be counted, use the \"Abort Step\" instead.",
   displayName = "Failure Step"
)
@Groups(openGroups = "Basic Settings", groupSequence = {"Basic Settings", "Tags/Guards", "Flow Control"})
public final class FailureStepConfig
   extends AbstractFlowStepConfig
   implements StepConfigForAuthorizationFlows,
   StepConfigForAuthenticationFlows,
   StepConfigForUserSelfRegFlows,
   StepConfigForPublicSelfServiceFlows,
   StepConfigForTechClientRegFlows,
   StepConfigForTransactionApprovalFlows,
   StepConfigForSelfServiceFlows,
   NonInteractiveStepConfig {
   public static final String FAILURE_STEP_PLUGIN_NAME = "Failure Step";
   private final List<TagConfig> tagsOnSuccess = Collections.emptyList();
   private final Map<String, StepIdConfig> onFailureGotos = Collections.emptyMap();
   @StringProperty(
      description = "The error code which will be included in the response. Allows specifying the reason for aborting the current flow.",
      exampleValues = "FLOW_ABORTED_INTENTIONALLY",
      optional = false
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private String errorCode;
   @StringProperty(
      displayName = "Authentication Method Identifier",
      description = "Identifies which failed factor attempts counter should be increased.",
      exampleValues = {"PASSWORD", "MTAN", "CRONTO", "FIDO", "AIRLOCK_2FA"},
      optional = false
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private String authMethod;

   public FailureStepConfig(
      FlowConditionConfig skipCondition,
      FlowConditionConfig preCondition,
      boolean requiresActivation,
      @Nullable StepIdConfig stepId,
      List<ValueMapProviderConfig> customResponseAttributes,
      List<ValueMapProviderConfig> customFailureResponseAttributes,
      String errorCode,
      String authMethod
   ) {
      super(
         skipCondition,
         preCondition,
         requiresActivation,
         Collections.emptyList(),
         stepId,
         Collections.emptyMap(),
         customResponseAttributes,
         customFailureResponseAttributes
      );
      this.errorCode = errorCode;
      this.authMethod = authMethod;
   }

   @Override
   public List<TagConfig> getTagsOnSuccess() {
      return this.tagsOnSuccess;
   }

   @Override
   public Map<String, StepIdConfig> getOnFailureGotos() {
      return this.onFailureGotos;
   }

   public String getErrorCode() {
      return this.errorCode;
   }

   public String getAuthMethod() {
      return this.authMethod;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class FailureStepConfigBuilder {
      @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 StepIdConfig stepId;
      @SuppressFBWarnings(justification = "generated code")
      private List<ValueMapProviderConfig> customResponseAttributes;
      @SuppressFBWarnings(justification = "generated code")
      private List<ValueMapProviderConfig> customFailureResponseAttributes;
      @SuppressFBWarnings(justification = "generated code")
      private String errorCode;
      @SuppressFBWarnings(justification = "generated code")
      private String authMethod;

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

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

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

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

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public FailureStepConfig.FailureStepConfigBuilder errorCode(String errorCode) {
         this.errorCode = errorCode;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FailureStepConfig.FailureStepConfigBuilder authMethod(String authMethod) {
         this.authMethod = authMethod;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public FailureStepConfig build() {
         return new FailureStepConfig(
            this.skipCondition,
            this.preCondition,
            this.requiresActivation,
            this.stepId,
            this.customResponseAttributes,
            this.customFailureResponseAttributes,
            this.errorCode,
            this.authMethod
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "FailureStepConfig.FailureStepConfigBuilder(skipCondition="
            + this.skipCondition
            + ", preCondition="
            + this.preCondition
            + ", requiresActivation="
            + this.requiresActivation
            + ", stepId="
            + this.stepId
            + ", customResponseAttributes="
            + this.customResponseAttributes
            + ", customFailureResponseAttributes="
            + this.customFailureResponseAttributes
            + ", errorCode="
            + this.errorCode
            + ", authMethod="
            + this.authMethod
            + ")";
      }
   }
}
