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

import com.airlock.iam.common.application.configuration.event.AdminappUserSubscribedEventConfig;
import com.airlock.iam.common.application.configuration.event.GatewayRestApiConnectionConfig;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.PluginListProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

@Plugin(
   description = "<p>This event subscriber terminates a user's Airlock Gateway sessions. Upon an event trigger, the plugin contacts one or more\nAirlock Gateways via their REST APIs, terminating all sessions of the affected user. In clustered gateway deployments, it is sufficient\nto contact a single gateway node to invalidate the user’s sessions across the cluster.</p>\n<p>For consistency, consider subscribing to the same events used by the 'Gateway Session Terminator Subscriber (Loginapp)'.</p>\n<p>Prerequisites:</p>\n<ul><li>The Gateway Audit Token in the Loginapp must be configured to contain only the <tt>username</tt></li>\n<li>IAM must be able to open HTTP(S) connections to the Airlock Gateways. This may require changes to your network topology.</li></ul>\n<p><em>Security Advisory:</em> Certain events can be triggered without an authenticated user session. Under Denial-of-Service conditions,\nsuch events may result in unintended session terminations and should therefore be selected with caution.</p>",
   displayName = "Gateway Session Terminator Subscriber (Adminapp)"
)
public class AdminappGatewaySessionTerminatorEventSubscriberConfig extends AdminappUserEventSubscriberConfig {
   @PluginListProperty(
      description = "The Airlock Gateway REST APIs that are invoked to terminate the user's sessions.",
      displayName = "Gateway REST APIs",
      optional = false,
      minElements = 1
   )
   private List<GatewayRestApiConnectionConfig> gatewayRestApiConnections;

   public AdminappGatewaySessionTerminatorEventSubscriberConfig(
      AdminappUserSubscribedEventConfig event, @Nonnull List<GatewayRestApiConnectionConfig> gatewayRestApiConnections
   ) {
      super(event);
      this.gatewayRestApiConnections = gatewayRestApiConnections;
   }

   @Nonnull
   public List<GatewayRestApiConnectionConfig> getGatewayRestApiConnections() {
      return this.gatewayRestApiConnections;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class AdminappGatewaySessionTerminatorEventSubscriberConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private AdminappUserSubscribedEventConfig event;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<GatewayRestApiConnectionConfig> gatewayRestApiConnections;

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

      @SuppressFBWarnings(justification = "generated code")
      public AdminappGatewaySessionTerminatorEventSubscriberConfig.AdminappGatewaySessionTerminatorEventSubscriberConfigBuilder event(
         AdminappUserSubscribedEventConfig event
      ) {
         this.event = event;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappGatewaySessionTerminatorEventSubscriberConfig.AdminappGatewaySessionTerminatorEventSubscriberConfigBuilder gatewayRestApiConnection(
         GatewayRestApiConnectionConfig gatewayRestApiConnection
      ) {
         if (this.gatewayRestApiConnections == null) {
            this.gatewayRestApiConnections = new ArrayList<>();
         }

         this.gatewayRestApiConnections.add(gatewayRestApiConnection);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappGatewaySessionTerminatorEventSubscriberConfig.AdminappGatewaySessionTerminatorEventSubscriberConfigBuilder gatewayRestApiConnections(
         Collection<? extends GatewayRestApiConnectionConfig> gatewayRestApiConnections
      ) {
         if (gatewayRestApiConnections == null) {
            throw new NullPointerException("gatewayRestApiConnections cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public AdminappGatewaySessionTerminatorEventSubscriberConfig.AdminappGatewaySessionTerminatorEventSubscriberConfigBuilder clearGatewayRestApiConnections() {
         if (this.gatewayRestApiConnections != null) {
            this.gatewayRestApiConnections.clear();
         }

         return this;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "AdminappGatewaySessionTerminatorEventSubscriberConfig.AdminappGatewaySessionTerminatorEventSubscriberConfigBuilder(event="
            + this.event
            + ", gatewayRestApiConnections="
            + this.gatewayRestApiConnections
            + ")";
      }
   }
}
