package com.airlock.iam.admin.domain.service.user;

import com.airlock.iam.admin.api.domain.model.administrator.CurrentAdministrator;
import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.base.api.domain.model.store.query.Restriction;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.common.api.domain.model.store.user.schema.UserSchema;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Optional;
import java.util.function.Supplier;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;

public final class RealmUserRestrictionProvider {
   @NonNull
   private final UserSchema schema;
   @NonNull
   private final String userContextDataFieldName;
   @NonNull
   private final String adminContextDataFieldName;
   @NonNull
   private final CurrentAdministrator currentAdministrator;

   public Optional<Restriction> getRestriction() {
      return this.adminContextDataValue().map(this.schema.customFields().string(this.userContextDataFieldName)::equal);
   }

   private Optional<String> adminContextDataValue() {
      return this.currentAdministrator
         .contextData(this.adminContextDataFieldName)
         .map(
            contextDataValue -> stringContextDataValueOrThrow(
               contextDataValue,
               () -> new FailureException(
                  String.format(
                     "Context data field %s of admin %s is not of type string - check configuration",
                     LogUtil.quote(this.adminContextDataFieldName),
                     LogUtil.quote(this.currentAdministrator.getName())
                  )
               )
            )
         )
         .filter(StringUtils::isNotBlank);
   }

   private static String stringContextDataValueOrThrow(Object contextDataValue, Supplier<? extends RuntimeException> exceptionSupplier) {
      if (contextDataValue instanceof String) {
         return (String)contextDataValue;
      } else {
         throw (RuntimeException)exceptionSupplier.get();
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   RealmUserRestrictionProvider(
      @NonNull UserSchema schema,
      @NonNull String userContextDataFieldName,
      @NonNull String adminContextDataFieldName,
      @NonNull CurrentAdministrator currentAdministrator
   ) {
      if (schema == null) {
         throw new NullPointerException("schema is marked non-null but is null");
      }

      if (userContextDataFieldName == null) {
         throw new NullPointerException("userContextDataFieldName is marked non-null but is null");
      }

      if (adminContextDataFieldName == null) {
         throw new NullPointerException("adminContextDataFieldName is marked non-null but is null");
      }

      if (currentAdministrator == null) {
         throw new NullPointerException("currentAdministrator is marked non-null but is null");
      }

      this.schema = schema;
      this.userContextDataFieldName = userContextDataFieldName;
      this.adminContextDataFieldName = adminContextDataFieldName;
      this.currentAdministrator = currentAdministrator;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class RealmUserRestrictionProviderBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private UserSchema schema;
      @SuppressFBWarnings(justification = "generated code")
      private String userContextDataFieldName;
      @SuppressFBWarnings(justification = "generated code")
      private String adminContextDataFieldName;
      @SuppressFBWarnings(justification = "generated code")
      private CurrentAdministrator currentAdministrator;

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

      @SuppressFBWarnings(justification = "generated code")
      public RealmUserRestrictionProvider.RealmUserRestrictionProviderBuilder schema(@NonNull UserSchema schema) {
         if (schema == null) {
            throw new NullPointerException("schema is marked non-null but is null");
         }

         this.schema = schema;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RealmUserRestrictionProvider.RealmUserRestrictionProviderBuilder userContextDataFieldName(@NonNull String userContextDataFieldName) {
         if (userContextDataFieldName == null) {
            throw new NullPointerException("userContextDataFieldName is marked non-null but is null");
         }

         this.userContextDataFieldName = userContextDataFieldName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RealmUserRestrictionProvider.RealmUserRestrictionProviderBuilder adminContextDataFieldName(@NonNull String adminContextDataFieldName) {
         if (adminContextDataFieldName == null) {
            throw new NullPointerException("adminContextDataFieldName is marked non-null but is null");
         }

         this.adminContextDataFieldName = adminContextDataFieldName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RealmUserRestrictionProvider.RealmUserRestrictionProviderBuilder currentAdministrator(@NonNull CurrentAdministrator currentAdministrator) {
         if (currentAdministrator == null) {
            throw new NullPointerException("currentAdministrator is marked non-null but is null");
         }

         this.currentAdministrator = currentAdministrator;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public RealmUserRestrictionProvider build() {
         return new RealmUserRestrictionProvider(this.schema, this.userContextDataFieldName, this.adminContextDataFieldName, this.currentAdministrator);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "RealmUserRestrictionProvider.RealmUserRestrictionProviderBuilder(schema="
            + this.schema
            + ", userContextDataFieldName="
            + this.userContextDataFieldName
            + ", adminContextDataFieldName="
            + this.adminContextDataFieldName
            + ", currentAdministrator="
            + this.currentAdministrator
            + ")";
      }
   }
}
