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

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.common.api.domain.model.user.User;
import com.airlock.iam.core.misc.cronto.CrontoHandler;
import com.airlock.iam.core.misc.impl.token.cronto.CrontoDeviceToken;
import com.airlock.iam.core.misc.token.Token;
import com.airlock.iam.flow.api.domain.model.step.FlowCondition;
import com.airlock.iam.flow.shared.application.configuration.condition.CrontoActivationRequiredConditionConfig;
import com.airlock.iam.flow.shared.domain.model.cronto.CrontoActivationPossibleCondition;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.stream.Stream;

@LogicForConfig(CrontoActivationRequiredConditionConfig.class)
public class CrontoActivationRequiredCondition implements FlowCondition {
   private final boolean includeInactiveDevices;
   private final CrontoHandler crontoHandler;
   private final CrontoActivationPossibleCondition activationPossible;
   private final Provider<User> user;

   @Inject
   public CrontoActivationRequiredCondition(
      boolean includeInactiveDevices, CrontoHandler crontoHandler, CrontoActivationPossibleCondition activationPossible, Provider<User> user
   ) {
      this.includeInactiveDevices = includeInactiveDevices;
      this.crontoHandler = crontoHandler;
      this.activationPossible = activationPossible;
      this.user = user;
   }

   @Override
   public boolean isFulfilled() {
      return this.activationPossible.isFulfilled() && !this.hasCrontoDevice();
   }

   private boolean hasCrontoDevice() {
      Stream<CrontoDeviceToken> deviceStream = this.loadDevices();
      if (!this.includeInactiveDevices) {
         deviceStream = deviceStream.filter(Token::isActive);
      }

      return deviceStream.findAny().isPresent();
   }

   private Stream<CrontoDeviceToken> loadDevices() {
      return this.crontoHandler.getAllDevicesForUser(this.user().getId()).stream();
   }

   @Override
   public String displayName() {
      return "Cronto Activation Required";
   }

   private User user() {
      return (User)this.user.get();
   }
}
