package com.airlock.iam.flow.shared.domain.model.condition;

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.common.api.domain.model.persistency.exception.PersisterException;
import com.airlock.iam.common.api.domain.model.user.UserIdentity;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.core.misc.impl.token.VascoToken;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.flow.api.domain.model.step.FlowCondition;
import com.airlock.iam.flow.shared.application.configuration.condition.VascoActivationPossibleConditionConfig;
import com.airlock.iam.flow.shared.domain.service.vasco.VascoOtpDeviceRepository;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.List;
import java.util.Optional;

@LogicForConfig(VascoActivationPossibleConditionConfig.class)
public final class VascoActivationPossibleCondition implements FlowCondition {
   private static final ELogger LOG = ELoggerFactory.getLogger(VascoActivationPossibleCondition.class);
   private final Provider<PrincipalInfo> user;
   private final Provider<VascoOtpDeviceRepository> deviceActivationRepository;

   @Inject
   public VascoActivationPossibleCondition(Provider<PrincipalInfo> user, Provider<VascoOtpDeviceRepository> deviceActivationRepository) {
      this.user = user;
      this.deviceActivationRepository = deviceActivationRepository;
   }

   @Override
   public boolean isFulfilled() {
      Optional<UserId> userId = ((PrincipalInfo)this.user.get()).getKnownIdentity().map(UserIdentity::id);
      if (userId.isEmpty()) {
         LOG.debug("User not identified - has no activatable Vasco OTP devices.");
         return false;
      }

      try {
         return this.hasUserActivatableDevices(userId.get());
      } catch (PersisterException e) {
         throw new FailureException("error while trying to load Vasco OTP devices for user " + LogUtil.quote(userId.get()), e);
      }
   }

   @Override
   public String displayName() {
      return "Vasco Activation Possible";
   }

   private boolean hasUserActivatableDevices(UserId userId) throws PersisterException {
      List<VascoToken> hasInactiveDevices = ((VascoOtpDeviceRepository)this.deviceActivationRepository.get()).getAllActivatableDevicesForUser(userId);
      if (hasInactiveDevices.isEmpty()) {
         LOG.debug(String.format("User %s does not have any activatable Vasco OTP devices", LogUtil.quote(userId)));
         return false;
      } else {
         LOG.debug(String.format("User %s has activatable Vasco OTP devices", LogUtil.quote(userId)));
         return true;
      }
   }
}
