package com.airlock.iam.publicselfservice.domain.service.restrictions;

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.common.domain.model.principal.UserPrincipal;
import com.airlock.iam.common.domain.model.token.secretquestions.SecretQuestionsRepository;
import com.airlock.iam.publicselfservice.api.domain.model.PublicSelfServiceRestriction;
import com.airlock.iam.publicselfservice.application.configuration.restrictions.DisabledOrMissingSecretQuestionsRestrictionConfig;
import com.airlock.iam.publicselfservice.domain.model.restrictions.DisabledOrMissingSecretQuestionsRestrictionSettings;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

@LogicForConfig(DisabledOrMissingSecretQuestionsRestrictionConfig.class)
public class DisabledOrMissingSecretQuestionsRestriction implements PublicSelfServiceRestriction {
   private final Provider<UserPrincipal> userPrincipal;
   private final DisabledOrMissingSecretQuestionsRestrictionSettings settings;
   private final Provider<SecretQuestionsRepository> repository;

   @Inject
   public DisabledOrMissingSecretQuestionsRestriction(
      Provider<UserPrincipal> userPrincipal, DisabledOrMissingSecretQuestionsRestrictionSettings settings, Provider<SecretQuestionsRepository> repository
   ) {
      this.userPrincipal = userPrincipal;
      this.settings = settings;
      this.repository = repository;
   }

   @Override
   public Optional<PublicSelfServiceRestriction.RestrictionViolation> getViolation() {
      if (!((UserPrincipal)this.userPrincipal.get()).exists()) {
         return Optional.empty();
      } else if (!((UserPrincipal)this.userPrincipal.get()).user().isSecretQuestionsEnabled()) {
         return restriction(DisabledOrMissingSecretQuestionsRestriction.NoSecretQuestionsRestrictionCode.SECRET_QUESTIONS_DISABLED);
      } else {
         return this.numProvisionedQuestions() < this.settings.getNumRequiredQuestions()
            ? restriction(DisabledOrMissingSecretQuestionsRestriction.NoSecretQuestionsRestrictionCode.NOT_ENOUGH_SECRET_QUESTIONS)
            : Optional.empty();
      }
   }

   private static Optional<PublicSelfServiceRestriction.RestrictionViolation> restriction(
      DisabledOrMissingSecretQuestionsRestriction.NoSecretQuestionsRestrictionCode code
   ) {
      return Optional.of(new PublicSelfServiceRestriction.RestrictionViolation(code, true));
   }

   private int numProvisionedQuestions() {
      return ((SecretQuestionsRepository)this.repository.get())
         .query()
         .forUser(((UserPrincipal)this.userPrincipal.get()).getName())
         .withoutRemovedQuestions()
         .getResults()
         .size();
   }

   public enum NoSecretQuestionsRestrictionCode implements PublicSelfServiceRestriction.ViolationCode {
      NOT_ENOUGH_SECRET_QUESTIONS,
      SECRET_QUESTIONS_DISABLED;
   }
}
