package com.airlock.iam.publicselfservice.application.configuration.ui;

import com.airlock.iam.flow.api.domain.model.flow.FlowId;
import com.airlock.iam.flow.application.configuration.validation.FlowIdConfigValidator;
import com.airlock.iam.plugin.api.annotation.config.ConfigurationValidator;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.PluginListProperty;
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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Plugin(description = "User interface configurations for public self-service flows.", displayName = "Public Self-Service UIs")
public class PublicSelfServiceUiConfigs {
   @PluginListProperty(
      description = "Allows to configure the user interface for the steps belonging to a flow.",
      displayName = "Flow UIs",
      optional = true,
      minElements = 1
   )
   private List<PublicSelfServiceUiConfig> flowUis;
   public static final String FLOW_USER_INTERFACES_PROPERTY = "flowUis";

   public Optional<PublicSelfServiceUiConfig> byFlowId(FlowId flowId) {
      return this.flowUis.stream().filter(config -> this.matchesId(config, flowId)).findFirst();
   }

   private boolean matchesId(PublicSelfServiceUiConfig config, FlowId id) {
      return config.getFlowId().equals(id);
   }

   public List<PublicSelfServiceUiConfig> getFlowUis() {
      return this.flowUis;
   }

   @ConfigurationValidator
   public static void validateUniqueFlows(
      PluginConfiguration config, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment
   ) throws ConfigurationException {
      new FlowIdConfigValidator(config, env, context, "flowUis", "flowId").validateFlowIdsUniqueForUis();
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public PublicSelfServiceUiConfigs.PublicSelfServiceUiConfigsBuilder toBuilder() {
      PublicSelfServiceUiConfigs.PublicSelfServiceUiConfigsBuilder builder = new PublicSelfServiceUiConfigs.PublicSelfServiceUiConfigsBuilder();
      if (this.flowUis != null) {
         builder.flowUis(this.flowUis);
      }

      return builder;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public PublicSelfServiceUiConfigs(List<PublicSelfServiceUiConfig> flowUis) {
      this.flowUis = flowUis;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class PublicSelfServiceUiConfigsBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<PublicSelfServiceUiConfig> flowUis;

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

      @SuppressFBWarnings(justification = "generated code")
      public PublicSelfServiceUiConfigs.PublicSelfServiceUiConfigsBuilder flowUi(PublicSelfServiceUiConfig flowUi) {
         if (this.flowUis == null) {
            this.flowUis = new ArrayList<>();
         }

         this.flowUis.add(flowUi);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public PublicSelfServiceUiConfigs.PublicSelfServiceUiConfigsBuilder flowUis(Collection<? extends PublicSelfServiceUiConfig> flowUis) {
         if (flowUis == null) {
            throw new NullPointerException("flowUis cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public PublicSelfServiceUiConfigs.PublicSelfServiceUiConfigsBuilder clearFlowUis() {
         if (this.flowUis != null) {
            this.flowUis.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public PublicSelfServiceUiConfigs build() {
         return new PublicSelfServiceUiConfigs(switch (this.flowUis == null ? 0 : this.flowUis.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.flowUis.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.flowUis));
         });
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "PublicSelfServiceUiConfigs.PublicSelfServiceUiConfigsBuilder(flowUis=" + this.flowUis + ")";
      }
   }
}
