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

import com.airlock.iam.core.misc.cronto.CrontoHandler;
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.AbstractInteractiveFlowStepConfig;
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.domain.model.cronto.CrontoPushActivationStep;
import com.airlock.iam.flow.types.api.application.configuration.step.StepConfigForAuthenticationFlows;
import com.airlock.iam.flow.types.api.application.configuration.step.StepConfigForSelfServiceFlows;
import com.airlock.iam.plugin.api.annotation.config.ConfigurationValidator;
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 com.airlock.iam.plugin.api.annotation.license.PluginLicenseRestriction;
import com.airlock.iam.plugin.api.annotation.property.GroupProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.Environment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.api.exception.ConfigurationException;
import com.airlock.iam.plugin.api.exception.PropertyConstraintViolationException;
import com.airlock.iam.plugin.api.valuereader.PluginPropertyValueReader;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

@Plugin(
   description = "<p>A step that allows push activation on the CrontoSign Swiss app.</p><p>In an authentication flow, it is typically used together with the \"CrontoSign Swiss Push Activation Possible\" condition, which is fulfilled if the currently used device (for login or newly registered) qualifies for push activation.</p><p>In self-service flows, it can be used without a condition, allowing the user to activate any Cronto device.</p>",
   displayName = "CrontoSign Swiss Push Activation Step"
)
@PluginLicenseRestriction(moduleAffiliation = "Cronto")
@Groups(openGroups = "Basic Settings", groupSequence = {"Basic Settings", "Tags/Guards", "Flow Control", "Advanced Settings"})
@NextActions(CrontoPushActivationStep.CrontoPushActivationStepActions.class)
public class CrontoPushActivationStepConfig
   extends AbstractInteractiveFlowStepConfig
   implements StepConfigForAuthenticationFlows,
   StepConfigForSelfServiceFlows {
   @PluginProperty(description = "Plugin to handle all Cronto-specific actions.", globalPluginReference = "globalCrontoSettings", optional = false)
   @GroupProperty(groupIdentifier = "Basic Settings")
   private CrontoHandler crontoHandler;
   private static final String CRONTO_HANDLER_PROPERTY = "crontoHandler";

   protected CrontoPushActivationStepConfig(
      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,
      CrontoHandler crontoHandler
   ) {
      super(
         skipCondition,
         preCondition,
         requiresActivation,
         tagsOnSuccess,
         stepId,
         interactiveGotoTargets,
         dynamicStepActivations,
         onFailureGotos,
         customResponseAttributes,
         customFailureResponseAttributes
      );
      this.crontoHandler = crontoHandler;
   }

   @ConfigurationValidator
   static void validatePushActivationIsPossible(
      PluginConfiguration stepConfig, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment
   ) throws ConfigurationException {
      PluginConfiguration crontoHandlerConfig = PluginPropertyValueReader.effectivePluginPropertyValue(stepConfig, "crontoHandler", env, context);
      Function<String, ConfigurationException> toException = msg -> new PropertyConstraintViolationException("crontoHandler", stepConfig, env, context, msg);
      CrontoPushConfigValidation.validateCrontoEngineHandlerHasPushEnabled(crontoHandlerConfig, env, context, toException);
   }

   public CrontoHandler getCrontoHandler() {
      return this.crontoHandler;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class CrontoPushActivationStepConfigBuilder {
      @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 List<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 CrontoHandler crontoHandler;

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

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

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

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

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

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

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

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

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

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

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

      @SuppressFBWarnings(justification = "generated code")
      public CrontoPushActivationStepConfig.CrontoPushActivationStepConfigBuilder crontoHandler(CrontoHandler crontoHandler) {
         this.crontoHandler = crontoHandler;
         return this;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "CrontoPushActivationStepConfig.CrontoPushActivationStepConfigBuilder(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
            + ", crontoHandler="
            + this.crontoHandler
            + ")";
      }
   }
}
