package com.airlock.iam.admin.application.configuration.event;

import com.airlock.iam.admin.api.application.configuration.event.AdminappDomainEventSubscriberConfig;
import com.airlock.iam.common.application.configuration.event.OutboxRepositoryConfig;
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.BooleanProperty;
import com.airlock.iam.plugin.api.annotation.property.GroupProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginListProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
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 = "Event settings for the Adminapp.")
@Groups(groupSequence = {"Basic Settings", "Outbox Settings"}, openGroups = {"Basic Settings", "Outbox Settings"})
public final class AdminappEventSettingsConfig {
   static final String OUTBOX_SETTINGS = "Outbox Settings";
   @PluginListProperty(
      description = "List of event subscribers. These subscribers receive events exactly once, but since they are\nnot connected to the outbox, no retries are attempted if a subscriber fails (e.g. because a remote\nserver is not available.)",
      optional = false
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private List<AdminappDomainEventSubscriberConfig> eventSubscribers;
   @PluginProperty(
      description = "Settings for the event outbox repository. If configured, all events are stored in an outbox database table until they\nhave successfully been forwarded to a message broker.",
      optional = true
   )
   @GroupProperty(groupIdentifier = "Outbox Settings")
   private OutboxRepositoryConfig outboxRepository;
   @BooleanProperty(
      description = "<p>If enabled, the context data of the managed user is added as <code>customData</code> to the event.</p>\n<p>The data contains all context data values configured in the User Store for loading the managed users.\nNote that these values might contain sensitive information such as email addresses or phone numbers.</p>",
      defaultValue = "false",
      optional = true
   )
   @GroupProperty(groupIdentifier = "Outbox Settings")
   private boolean addContextData;

   public List<AdminappDomainEventSubscriberConfig> getEventSubscribers() {
      return this.eventSubscribers;
   }

   public Optional<OutboxRepositoryConfig> getOutboxRepository() {
      return Optional.ofNullable(this.outboxRepository);
   }

   public boolean isAddContextData() {
      return this.addContextData;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public AdminappEventSettingsConfig(
      List<AdminappDomainEventSubscriberConfig> eventSubscribers, OutboxRepositoryConfig outboxRepository, boolean addContextData
   ) {
      this.eventSubscribers = eventSubscribers;
      this.outboxRepository = outboxRepository;
      this.addContextData = addContextData;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class AdminappEventSettingsConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<AdminappDomainEventSubscriberConfig> eventSubscribers;
      @SuppressFBWarnings(justification = "generated code")
      private OutboxRepositoryConfig outboxRepository;
      @SuppressFBWarnings(justification = "generated code")
      private boolean addContextData;

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

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEventSettingsConfig.AdminappEventSettingsConfigBuilder eventSubscriber(AdminappDomainEventSubscriberConfig eventSubscriber) {
         if (this.eventSubscribers == null) {
            this.eventSubscribers = new ArrayList<>();
         }

         this.eventSubscribers.add(eventSubscriber);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEventSettingsConfig.AdminappEventSettingsConfigBuilder eventSubscribers(
         Collection<? extends AdminappDomainEventSubscriberConfig> eventSubscribers
      ) {
         if (eventSubscribers == null) {
            throw new NullPointerException("eventSubscribers cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEventSettingsConfig.AdminappEventSettingsConfigBuilder clearEventSubscribers() {
         if (this.eventSubscribers != null) {
            this.eventSubscribers.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEventSettingsConfig.AdminappEventSettingsConfigBuilder outboxRepository(OutboxRepositoryConfig outboxRepository) {
         this.outboxRepository = outboxRepository;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEventSettingsConfig.AdminappEventSettingsConfigBuilder addContextData(boolean addContextData) {
         this.addContextData = addContextData;
         return this;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "AdminappEventSettingsConfig.AdminappEventSettingsConfigBuilder(eventSubscribers="
            + this.eventSubscribers
            + ", outboxRepository="
            + this.outboxRepository
            + ", addContextData="
            + this.addContextData
            + ")";
      }
   }
}
