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

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.common.api.domain.model.user.PersistentUser;
import com.airlock.iam.common.domain.model.principal.UserPrincipal;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.publicselfservice.api.domain.model.PublicSelfServiceRestriction;
import com.airlock.iam.publicselfservice.application.configuration.restrictions.LockedUserRestrictionConfig;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;

@LogicForConfig(LockedUserRestrictionConfig.class)
public final class LockedUserRestriction implements PublicSelfServiceRestriction {
   private static final ELogger LOG = ELoggerFactory.getLogger(LockedUserRestriction.class);
   private final Provider<LockedUserRestrictionConfig> config;
   private final Provider<UserPrincipal> userPrincipal;

   @Inject
   public LockedUserRestriction(Provider<LockedUserRestrictionConfig> config, Provider<UserPrincipal> userPrincipal) {
      this.config = config;
      this.userPrincipal = userPrincipal;
   }

   @Override
   public Optional<PublicSelfServiceRestriction.RestrictionViolation> getViolation() {
      if (!((UserPrincipal)this.userPrincipal.get()).exists()) {
         return Optional.empty();
      }

      PersistentUser user = ((UserPrincipal)this.userPrincipal.get()).user();
      if (!user.isLocked()) {
         return Optional.empty();
      }

      String lockReason = user.getLockReason();
      if (StringUtils.isBlank(lockReason)) {
         LOG.info("User is locked without a lock reason.");
         return this.restricted();
      }

      List<String> allowedReasons = ((LockedUserRestrictionConfig)this.config.get()).getAllowedLockReasons();
      if (allowedReasons.contains(lockReason)) {
         return Optional.empty();
      }

      LOG.info("User is locked with reason " + lockReason + " (allowed reasons: " + String.join(",", allowedReasons) + ")");
      return this.restricted();
   }

   private Optional<PublicSelfServiceRestriction.RestrictionViolation> restricted() {
      return Optional.of(
         new PublicSelfServiceRestriction.RestrictionViolation(
            LockedUserRestriction.LockedUserRestrictionCode.USER_LOCKED, ((LockedUserRestrictionConfig)this.config.get()).isEnableFeedback()
         )
      );
   }

   public enum LockedUserRestrictionCode implements PublicSelfServiceRestriction.ViolationCode {
      USER_LOCKED;
   }
}
