package com.airlock.iam.common.application.configuration.credential;

import com.airlock.iam.common.api.application.configuration.credential.GenericRequestAuthenticationConfig;
import com.airlock.iam.common.api.domain.model.user.ProvidedUsername;
import com.airlock.iam.core.application.configuration.store.user.UserStoreProvider;
import com.airlock.iam.core.misc.authen.UsernameTransformer;
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.GroupProperty;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

@Plugin(
   description = "<p>Provides a static username and roles for the authentee.</p><p><b>Security warning:</b>With this plugin, all requests to the REST API are considered authenticated and authorized accoring to the granted roles. Use this only for testing or in a trusted enviroment.</p>",
   displayName = "Static Request Authentication"
)
@Groups(openGroups = "Basic Settings", groupSequence = {"Basic Settings", "Advanced Settings"})
public final class StaticRequestAuthenticationConfig extends BaseRequestAuthenticationConfig implements GenericRequestAuthenticationConfig {
   private List<UsernameTransformer> usernameTransformers;
   @StringProperty(description = "The username to authenticate with.", optional = false)
   @GroupProperty(groupIdentifier = "Basic Settings")
   private String username;

   public StaticRequestAuthenticationConfig(UserStoreProvider userStore, List<String> staticRoles, List<String> rolesBlocklist, String username) {
      super(userStore, null, staticRoles, rolesBlocklist);
      this.username = username;
   }

   public ProvidedUsername getProvidedUsername() {
      return ProvidedUsername.providedUsernameOf(this.username);
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class StaticRequestAuthenticationConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private UserStoreProvider userStore;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<String> staticRoles;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<String> rolesBlocklist;
      @SuppressFBWarnings(justification = "generated code")
      private String username;

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

      @SuppressFBWarnings(justification = "generated code")
      public StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder userStore(UserStoreProvider userStore) {
         this.userStore = userStore;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder staticRole(String staticRole) {
         if (this.staticRoles == null) {
            this.staticRoles = new ArrayList<>();
         }

         this.staticRoles.add(staticRole);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder staticRoles(Collection<? extends String> staticRoles) {
         if (staticRoles == null) {
            throw new NullPointerException("staticRoles cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder clearStaticRoles() {
         if (this.staticRoles != null) {
            this.staticRoles.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder roleForBlocklist(String roleForBlocklist) {
         if (this.rolesBlocklist == null) {
            this.rolesBlocklist = new ArrayList<>();
         }

         this.rolesBlocklist.add(roleForBlocklist);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder rolesBlocklist(Collection<? extends String> rolesBlocklist) {
         if (rolesBlocklist == null) {
            throw new NullPointerException("rolesBlocklist cannot be null");
         }

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

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

      @SuppressFBWarnings(justification = "generated code")
      public StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder clearRolesBlocklist() {
         if (this.rolesBlocklist != null) {
            this.rolesBlocklist.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder username(String username) {
         this.username = username;
         return this;
      }

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

         return new StaticRequestAuthenticationConfig(this.userStore, staticRoles, switch (this.rolesBlocklist == null ? 0 : this.rolesBlocklist.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.rolesBlocklist.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.rolesBlocklist));
         }, this.username);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "StaticRequestAuthenticationConfig.StaticRequestAuthenticationConfigBuilder(userStore="
            + this.userStore
            + ", staticRoles="
            + this.staticRoles
            + ", rolesBlocklist="
            + this.rolesBlocklist
            + ", username="
            + this.username
            + ")";
      }
   }
}
