package com.airlock.iam.admin.application.service.token.secretquestions;

import com.airlock.iam.common.api.domain.model.store.user.UserStore;
import com.airlock.iam.common.api.domain.model.user.PersistentUser;
import com.airlock.iam.common.application.configuration.secretquestion.SecretQuestionsSettings;
import com.airlock.iam.common.domain.model.token.secretquestions.SecretQuestion;
import com.airlock.iam.common.domain.model.token.secretquestions.SecretQuestionAnswer;
import com.airlock.iam.common.domain.model.token.secretquestions.SecretQuestionsRepository;
import com.airlock.iam.common.domain.service.exception.FeatureDisabledException;
import com.airlock.iam.common.domain.service.secretquestions.SecretQuestionsService;
import com.airlock.iam.log.api.signing.SigningLogger;
import com.google.common.base.Preconditions;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import java.util.List;
import java.util.Optional;

public class SecretQuestionsAdminService {
   private final SecretQuestionsService commonService;
   private final UserStore userStore;
   private final SecretQuestionsRepository secretQuestionsRepository;
   private final SecretQuestionsSettings settings;
   private final SigningLogger signingLogger;

   @Inject
   public SecretQuestionsAdminService(
      SecretQuestionsService commonService, UserStore userStore, SecretQuestionsRepository repository, SecretQuestionsSettings settings, SigningLogger logger
   ) {
      this.commonService = commonService;
      this.secretQuestionsRepository = repository;
      this.userStore = userStore;
      this.settings = settings;
      this.signingLogger = logger;
   }

   public SecretQuestionsAdminService(
      SecretQuestionsSettings secretQuestionsSettings, UserStore userStore, SecretQuestionsRepository secretQuestionsRepository, SigningLogger logger
   ) {
      this.commonService = SecretQuestionsService.builder()
         .userStore(userStore)
         .secretQuestionsSettings(secretQuestionsSettings)
         .secretQuestionsRepository(secretQuestionsRepository)
         .signingLogger(logger)
         .build();
      this.settings = secretQuestionsSettings;
      this.secretQuestionsRepository = secretQuestionsRepository;
      this.userStore = userStore;
      this.signingLogger = logger;
   }

   public boolean isSecretQuestionsEnabled(String userId) {
      return this.commonService.isSecretQuestionsEnabled(userId);
   }

   public boolean isCheckAnswerForAdminEnabled() {
      return this.settings.isAllowAdminAnswerCheck();
   }

   public void enableSecretQuestions(String userId) {
      Preconditions.checkNotNull(userId);
      PersistentUser user = (PersistentUser)this.userStore.getByIdentity(userId);
      user.setSecretQuestionsEnabled(true);
      this.userStore.update(user);
      this.signingLogger.log("enabling secret questions feature for user \"%s\"", new Object[]{userId});
   }

   public void disableSecretQuestions(String userId) {
      Preconditions.checkNotNull(userId);
      PersistentUser user = (PersistentUser)this.userStore.getByIdentity(userId);
      user.setSecretQuestionsEnabled(false);
      this.userStore.update(user);
      this.signingLogger.log("disabling secret questions feature for user \"%s\"", new Object[]{userId});
   }

   public List<SecretQuestion> getAnsweredQuestions(String userId) {
      return this.secretQuestionsRepository.query().forUser(userId).withoutRemovedQuestions().getResults();
   }

   public int getNumberOfMissingAnswers(String userId) {
      return this.commonService.getNumberOfMissingAnswers(userId);
   }

   public boolean deleteAnswer(String userId, String questionResourceKey) {
      Preconditions.checkNotNull(userId);
      Preconditions.checkNotNull(questionResourceKey);
      this.checkSecretQuestionsEnabled(userId);
      return this.deleteAnswerInternal(userId, questionResourceKey);
   }

   public boolean verifyAnswer(SecretQuestionAnswer answer) {
      return this.commonService.verifyAnswer(answer);
   }

   public boolean unblockAnswer(String userId, String questionResourceKey) {
      Preconditions.checkNotNull(userId);
      Preconditions.checkNotNull(questionResourceKey);
      this.checkSecretQuestionsEnabled(userId);
      Optional<SecretQuestion> secretQuestionOptional = this.secretQuestionsRepository
         .query()
         .forUser(userId)
         .withQuestionResourceKey(new String[]{questionResourceKey})
         .getResult();
      if (secretQuestionOptional.isPresent()) {
         SecretQuestion secretQuestion = secretQuestionOptional.get().withoutFailedAttempts().withoutBlock();
         this.secretQuestionsRepository.update(userId, secretQuestion);
         this.signingLogger.log("unblocked Secret Question token for user \"%s\"", new Object[]{userId});
         return true;
      } else {
         this.signingLogger.log("could not unblock Secret Question token for user \"%s\"", new Object[]{userId});
         return false;
      }
   }

   private boolean deleteAnswerInternal(String userId, String questionResourceKey) {
      if (this.secretQuestionsRepository.delete(userId, questionResourceKey)) {
         this.signingLogger.log("deleted Secret Question token for user \"%s\"", new Object[]{userId});
         return true;
      } else {
         this.signingLogger.log("could not delete Secret Question token for user \"%s\"", new Object[]{userId});
         return false;
      }
   }

   private void checkSecretQuestionsEnabled(String userId) {
      boolean enabled = this.isSecretQuestionsEnabled(userId);
      FeatureDisabledException.checkTrue(enabled, userId, "Secret Questions are not enabled for user '" + userId + "'");
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class SecretQuestionsAdminServiceBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private SecretQuestionsSettings secretQuestionsSettings;
      @SuppressFBWarnings(justification = "generated code")
      private UserStore userStore;
      @SuppressFBWarnings(justification = "generated code")
      private SecretQuestionsRepository secretQuestionsRepository;
      @SuppressFBWarnings(justification = "generated code")
      private SigningLogger logger;

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

      @SuppressFBWarnings(justification = "generated code")
      public SecretQuestionsAdminService.SecretQuestionsAdminServiceBuilder secretQuestionsSettings(SecretQuestionsSettings secretQuestionsSettings) {
         this.secretQuestionsSettings = secretQuestionsSettings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SecretQuestionsAdminService.SecretQuestionsAdminServiceBuilder userStore(UserStore userStore) {
         this.userStore = userStore;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SecretQuestionsAdminService.SecretQuestionsAdminServiceBuilder secretQuestionsRepository(SecretQuestionsRepository secretQuestionsRepository) {
         this.secretQuestionsRepository = secretQuestionsRepository;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SecretQuestionsAdminService.SecretQuestionsAdminServiceBuilder logger(SigningLogger logger) {
         this.logger = logger;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public SecretQuestionsAdminService build() {
         return new SecretQuestionsAdminService(this.secretQuestionsSettings, this.userStore, this.secretQuestionsRepository, this.logger);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "SecretQuestionsAdminService.SecretQuestionsAdminServiceBuilder(secretQuestionsSettings="
            + this.secretQuestionsSettings
            + ", userStore="
            + this.userStore
            + ", secretQuestionsRepository="
            + this.secretQuestionsRepository
            + ", logger="
            + this.logger
            + ")";
      }
   }
}
