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

import com.airlock.iam.common.api.domain.model.role.Role;
import com.airlock.iam.common.api.domain.model.store.user.UserStore;
import com.airlock.iam.common.domain.model.role.RolesUtil;
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.property.GroupProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginListProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import com.airlock.iam.plugin.api.annotation.property.StringListProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;

public abstract class BaseRequestAuthenticationConfig {
   @PluginProperty(
      description = "If configured, the user is loaded from local persistence and checked for validity.\nAuthentication fails if the user is not found or is invalid. If no user store is configured,\nno persistency look-up takes place and the authentication is performed on data contained\nwithin the credential only.",
      optional = true
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private UserStoreProvider userStore;
   @PluginListProperty(
      displayName = "Username Transformation",
      description = "Transforms the provided username from the credential to a technical user ID.",
      optional = true
   )
   @GroupProperty(groupIdentifier = "Advanced Settings")
   private List<UsernameTransformer> usernameTransformers;
   static final String USERNAME_TRANSFORMERS_FIELD = "usernameTransformers";
   @StringListProperty(
      description = "Static list of roles granted to the authenticated user.",
      optional = true,
      validationRegex = "[\\w-_.:]+",
      exampleElements = {"sso", "weak", "authenticated", "sso:300"}
   )
   @GroupProperty(groupIdentifier = "Basic Settings")
   private List<String> staticRoles;
   @StringListProperty(
      description = "List of role names that won't be granted to the authenticated user. The block list is also applied to persistent roles (if available).",
      optional = true,
      validationRegex = "[\\w-_.]+",
      exampleElements = {"superadmin", "special"}
   )
   @GroupProperty(groupIdentifier = "Advanced Settings")
   private List<String> rolesBlocklist;

   public Optional<UserStore> getUserStore() {
      return Optional.ofNullable(this.userStore).map(UserStoreProvider::getUserStore);
   }

   public Set<Role> getStaticRoles() {
      return RolesUtil.rolesFrom(this.staticRoles);
   }

   public Set<String> getRolesBlockList() {
      return new HashSet<>(this.rolesBlocklist);
   }

   public OptionalInt getMaxFailedAttempts() {
      return OptionalInt.empty();
   }

   public List<UsernameTransformer> getUsernameTransformers() {
      return this.usernameTransformers;
   }

   @SuppressFBWarnings(justification = "generated code")
   public BaseRequestAuthenticationConfig(
      UserStoreProvider userStore, List<UsernameTransformer> usernameTransformers, List<String> staticRoles, List<String> rolesBlocklist
   ) {
      this.userStore = userStore;
      this.usernameTransformers = usernameTransformers;
      this.staticRoles = staticRoles;
      this.rolesBlocklist = rolesBlocklist;
   }

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