package com.airlock.iam.ssi.application.configuration.step;

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.types.api.application.configuration.step.StepConfigForUserSelfRegFlows;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.ssi.application.configuration.SsiAttributeMapping;
import com.airlock.iam.ssi.application.configuration.SsiServiceConfig;
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 = "SSI issuance step. Instructs the SSI service to issue a verifiable credential based on string values obtained\nfrom the specified value map providers.\nThis step will <em>not</em> automatically persist the issued credentials in the database.\nIn order for credentials to be persisted in a self-registration flow, a 'Verifiable Credential Insertion Handler'\nmust be configured in the 'User Persisting Step' at the end of the flow.<p><b>This feature is incubating. Please consult the documentation for more information.</b></p>",
   displayName = "SSI Self-Registration Issuance Step"
)
public class SsiSelfRegistraionIssuanceStepConfig extends AbstractSsiIssuanceStepConfig implements StepConfigForUserSelfRegFlows {
   public SsiSelfRegistraionIssuanceStepConfig(
      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,
      SsiServiceConfig service,
      String credentialSchemaName,
      List<ValueMapProviderConfig> valueProviders,
      List<SsiAttributeMapping> attributeMappings
   ) {
      super(
         skipCondition,
         preCondition,
         requiresActivation,
         tagsOnSuccess,
         stepId,
         interactiveGotoTargets,
         dynamicStepActivations,
         onFailureGotos,
         customResponseAttributes,
         customFailureResponseAttributes,
         service,
         credentialSchemaName,
         valueProviders,
         attributeMappings
      );
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class SsiSelfRegistraionIssuanceStepConfigBuilder {
      @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 ArrayList<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 SsiServiceConfig service;
      @SuppressFBWarnings(justification = "generated code")
      private String credentialSchemaName;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<ValueMapProviderConfig> valueProviders;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<SsiAttributeMapping> attributeMappings;

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

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

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

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

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

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder 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 SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder clearInteractiveGotoTargets() {
         if (this.interactiveGotoTargets != null) {
            this.interactiveGotoTargets.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder dynamicStepActivation(
         DynamicStepActivationConfig dynamicStepActivation
      ) {
         if (this.dynamicStepActivations == null) {
            this.dynamicStepActivations = new ArrayList<>();
         }

         this.dynamicStepActivations.add(dynamicStepActivation);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder dynamicStepActivations(
         Collection<? extends DynamicStepActivationConfig> dynamicStepActivations
      ) {
         if (dynamicStepActivations == null) {
            throw new NullPointerException("dynamicStepActivations cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder clearDynamicStepActivations() {
         if (this.dynamicStepActivations != null) {
            this.dynamicStepActivations.clear();
         }

         return this;
      }

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder service(SsiServiceConfig service) {
         this.service = service;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder credentialSchemaName(String credentialSchemaName) {
         this.credentialSchemaName = credentialSchemaName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder valueProvider(ValueMapProviderConfig valueProvider) {
         if (this.valueProviders == null) {
            this.valueProviders = new ArrayList<>();
         }

         this.valueProviders.add(valueProvider);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder valueProviders(
         Collection<? extends ValueMapProviderConfig> valueProviders
      ) {
         if (valueProviders == null) {
            throw new NullPointerException("valueProviders cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder clearValueProviders() {
         if (this.valueProviders != null) {
            this.valueProviders.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder attributeMapping(SsiAttributeMapping attributeMapping) {
         if (this.attributeMappings == null) {
            this.attributeMappings = new ArrayList<>();
         }

         this.attributeMappings.add(attributeMapping);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder attributeMappings(
         Collection<? extends SsiAttributeMapping> attributeMappings
      ) {
         if (attributeMappings == null) {
            throw new NullPointerException("attributeMappings cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder clearAttributeMappings() {
         if (this.attributeMappings != null) {
            this.attributeMappings.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SsiSelfRegistraionIssuanceStepConfig build() {
         List interactiveGotoTargets = 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));
         };

         List dynamicStepActivations = switch (this.dynamicStepActivations == null ? 0 : this.dynamicStepActivations.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.dynamicStepActivations.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.dynamicStepActivations));
         };

         List valueProviders = switch (this.valueProviders == null ? 0 : this.valueProviders.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.valueProviders.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.valueProviders));
         };

         return new SsiSelfRegistraionIssuanceStepConfig(
            this.skipCondition,
            this.preCondition,
            this.requiresActivation,
            this.tagsOnSuccess,
            this.stepId,
            interactiveGotoTargets,
            dynamicStepActivations,
            this.onFailureGotos,
            this.customResponseAttributes,
            this.customFailureResponseAttributes,
            this.service,
            this.credentialSchemaName,
            valueProviders,
            switch (this.attributeMappings == null ? 0 : this.attributeMappings.size()) {
               case 0 -> Collections.emptyList();
               case 1 -> Collections.singletonList(this.attributeMappings.get(0));
               default -> Collections.unmodifiableList(new ArrayList<>(this.attributeMappings));
            }
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "SsiSelfRegistraionIssuanceStepConfig.SsiSelfRegistraionIssuanceStepConfigBuilder(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
            + ", service="
            + this.service
            + ", credentialSchemaName="
            + this.credentialSchemaName
            + ", valueProviders="
            + this.valueProviders
            + ", attributeMappings="
            + this.attributeMappings
            + ")";
      }
   }
}
