package com.airlock.iam.admin.domain.model.token.generic;

import com.airlock.iam.admin.api.domain.model.token.generic.ActivationLetterOrderStatus;
import com.airlock.iam.admin.api.domain.model.token.generic.GenericToken;
import com.airlock.iam.admin.api.domain.model.user.AuthenticationMethods;
import com.airlock.iam.admin.api.domain.service.user.ManagedUserRepository;
import com.airlock.iam.admin.application.service.token.generic.GenericTokenService;
import com.airlock.iam.admin.domain.model.authmethod.AuthenticationMethod;
import com.airlock.iam.admin.infrastructure.factory.TokenServiceFactory;
import com.airlock.iam.base.api.domain.model.user.UserId;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Provider;
import java.util.List;
import java.util.Optional;

public class GenericAuthenticationMethod implements AuthenticationMethod {
   private AuthenticationMethod.TokenType tokenType;
   private Provider<TokenServiceFactory> tokenServiceFactory;
   private ManagedUserRepository userRepository;
   private boolean allowedAsActive;
   private boolean allowedAsNew;
   private boolean allowedForMigration;
   private final boolean autoOrderOnAuthMethodAdd;
   private final boolean autoOrderOnUserCreate;
   private final boolean hasGenericUi;

   @Override
   public AuthenticationMethod.TokenType getTokenType() {
      return this.tokenType;
   }

   @Override
   public AuthenticationMethods.AuthenticationMethodId getConfiguredId() {
      return AuthenticationMethods.AuthenticationMethodId.authMethodId(this.tokenType.getId());
   }

   @Override
   public boolean isAllowedAsActiveAuthMethodForUser(UserId userId) {
      return this.allowedAsActive && this.hasAuthMethodOrTokensOrOrders(userId);
   }

   @Override
   public boolean isAllowedAsNextAuthMethod() {
      return this.allowedForMigration;
   }

   @Override
   public boolean isAllowedAsNewAuthMethod(UserId userId) {
      return this.allowedAsNew && !this.hasAuthMethodOrTokensOrOrders(userId);
   }

   @Override
   public boolean isVisible(UserId userId) {
      return this.hasGenericUi && this.hasAuthMethodOrTokensOrOrders(userId);
   }

   private boolean hasAuthMethodOrTokensOrOrders(UserId userId) {
      List<GenericToken> tokens = this.tokenService().getTokens(userId);
      ActivationLetterOrderStatus order = this.tokenService().getActivationLetterOrderStatus(userId);
      AuthenticationMethods userAuthMethods = this.userRepository.getById(userId).getAuthenticationMethods();
      return userAuthMethods.hasActiveAuthMethod(this.getConfiguredId()) || !tokens.isEmpty() || order.isOrdered();
   }

   @Override
   public Optional<AuthenticationMethod.AddAuthMethodErrorCode> addToUser(UserId userId) {
      if (this.autoOrderOnAuthMethodAdd) {
         this.tokenService().orderNewActivationLetter(userId);
      }

      return Optional.empty();
   }

   @Override
   public void handleUserCreated(UserId userId) {
      if (this.autoOrderOnUserCreate) {
         this.tokenService().orderNewActivationLetter(userId);
      }
   }

   @Override
   public boolean isGeneric() {
      return true;
   }

   private GenericTokenService tokenService() {
      return ((TokenServiceFactory)this.tokenServiceFactory.get()).getServiceForType(this.getTokenType());
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public GenericAuthenticationMethod(
      AuthenticationMethod.TokenType tokenType,
      Provider<TokenServiceFactory> tokenServiceFactory,
      ManagedUserRepository userRepository,
      boolean allowedAsActive,
      boolean allowedAsNew,
      boolean allowedForMigration,
      boolean autoOrderOnAuthMethodAdd,
      boolean autoOrderOnUserCreate,
      boolean hasGenericUi
   ) {
      this.tokenType = tokenType;
      this.tokenServiceFactory = tokenServiceFactory;
      this.userRepository = userRepository;
      this.allowedAsActive = allowedAsActive;
      this.allowedAsNew = allowedAsNew;
      this.allowedForMigration = allowedForMigration;
      this.autoOrderOnAuthMethodAdd = autoOrderOnAuthMethodAdd;
      this.autoOrderOnUserCreate = autoOrderOnUserCreate;
      this.hasGenericUi = hasGenericUi;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class GenericAuthenticationMethodBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private AuthenticationMethod.TokenType tokenType;
      @SuppressFBWarnings(justification = "generated code")
      private Provider<TokenServiceFactory> tokenServiceFactory;
      @SuppressFBWarnings(justification = "generated code")
      private ManagedUserRepository userRepository;
      @SuppressFBWarnings(justification = "generated code")
      private boolean allowedAsActive;
      @SuppressFBWarnings(justification = "generated code")
      private boolean allowedAsNew;
      @SuppressFBWarnings(justification = "generated code")
      private boolean allowedForMigration;
      @SuppressFBWarnings(justification = "generated code")
      private boolean autoOrderOnAuthMethodAdd;
      @SuppressFBWarnings(justification = "generated code")
      private boolean autoOrderOnUserCreate;
      @SuppressFBWarnings(justification = "generated code")
      private boolean hasGenericUi;

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

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder tokenType(AuthenticationMethod.TokenType tokenType) {
         this.tokenType = tokenType;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder tokenServiceFactory(Provider<TokenServiceFactory> tokenServiceFactory) {
         this.tokenServiceFactory = tokenServiceFactory;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder userRepository(ManagedUserRepository userRepository) {
         this.userRepository = userRepository;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder allowedAsActive(boolean allowedAsActive) {
         this.allowedAsActive = allowedAsActive;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder allowedAsNew(boolean allowedAsNew) {
         this.allowedAsNew = allowedAsNew;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder allowedForMigration(boolean allowedForMigration) {
         this.allowedForMigration = allowedForMigration;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder autoOrderOnAuthMethodAdd(boolean autoOrderOnAuthMethodAdd) {
         this.autoOrderOnAuthMethodAdd = autoOrderOnAuthMethodAdd;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder autoOrderOnUserCreate(boolean autoOrderOnUserCreate) {
         this.autoOrderOnUserCreate = autoOrderOnUserCreate;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod.GenericAuthenticationMethodBuilder hasGenericUi(boolean hasGenericUi) {
         this.hasGenericUi = hasGenericUi;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public GenericAuthenticationMethod build() {
         return new GenericAuthenticationMethod(
            this.tokenType,
            this.tokenServiceFactory,
            this.userRepository,
            this.allowedAsActive,
            this.allowedAsNew,
            this.allowedForMigration,
            this.autoOrderOnAuthMethodAdd,
            this.autoOrderOnUserCreate,
            this.hasGenericUi
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "GenericAuthenticationMethod.GenericAuthenticationMethodBuilder(tokenType="
            + this.tokenType
            + ", tokenServiceFactory="
            + this.tokenServiceFactory
            + ", userRepository="
            + this.userRepository
            + ", allowedAsActive="
            + this.allowedAsActive
            + ", allowedAsNew="
            + this.allowedAsNew
            + ", allowedForMigration="
            + this.allowedForMigration
            + ", autoOrderOnAuthMethodAdd="
            + this.autoOrderOnAuthMethodAdd
            + ", autoOrderOnUserCreate="
            + this.autoOrderOnUserCreate
            + ", hasGenericUi="
            + this.hasGenericUi
            + ")";
      }
   }
}
