package com.airlock.iam.transactionapproval.domain.model.selection;

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FAAuthTokenIdCoder;
import com.airlock.iam.flow.api.domain.model.step.FlowCondition;
import com.airlock.iam.flow.shared.api.domain.service.FlowAttributeService;
import com.airlock.iam.flow.shared.domain.model.attributes.AuthTokenIdAttribute;
import com.airlock.iam.transactionapproval.application.configuration.selection.Airlock2FAAuthTokenIdSelectionConditionConfig;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;
import lombok.NonNull;

@LogicForConfig(Airlock2FAAuthTokenIdSelectionConditionConfig.class)
public class Airlock2FAAuthTokenIdSelectionCondition implements FlowCondition {
   @NonNull
   private final Provider<FlowAttributeService> attributes;
   @NonNull
   private final Airlock2FAAuthTokenIdCoder coder;
   private final boolean selectableIfNoAuthTokenIdPresent;

   @Inject
   public Airlock2FAAuthTokenIdSelectionCondition(
      @NonNull Provider<FlowAttributeService> attributes,
      @NonNull Airlock2FAAuthTokenIdCoder coder,
      Airlock2FAAuthTokenIdSelectionCondition.Airlock2FAAuthTokenIdSelectionConditionSettings settings
   ) {
      if (attributes == null) {
         throw new NullPointerException("attributes is marked non-null but is null");
      }

      if (coder == null) {
         throw new NullPointerException("coder is marked non-null but is null");
      }

      this.attributes = attributes;
      this.coder = coder;
      this.selectableIfNoAuthTokenIdPresent = settings.isSelectableIfNoAuthTokenIdPresent();
   }

   public boolean isFulfilled() {
      Optional<String> authTokenId = this.extractAuthTokenId();
      return authTokenId.isPresent() ? this.coder.decode(authTokenId.get()).isPresent() : this.selectableIfNoAuthTokenIdPresent;
   }

   private Optional<String> extractAuthTokenId() {
      Optional<AuthTokenIdAttribute> autTokenIdAttribute = ((FlowAttributeService)this.attributes.get()).findAttribute(AuthTokenIdAttribute.class);
      return autTokenIdAttribute.isPresent() ? Optional.of(autTokenIdAttribute.get().getAuthTokenId()) : Optional.empty();
   }

   public String displayName() {
      return "Has Airlock 2FA Auth Token ID";
   }

   public static final class Airlock2FAAuthTokenIdSelectionConditionSettings {
      private final boolean selectableIfNoAuthTokenIdPresent;

      @SuppressFBWarnings(justification = "generated code")
      public boolean isSelectableIfNoAuthTokenIdPresent() {
         return this.selectableIfNoAuthTokenIdPresent;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Airlock2FAAuthTokenIdSelectionConditionSettings(boolean selectableIfNoAuthTokenIdPresent) {
         this.selectableIfNoAuthTokenIdPresent = selectableIfNoAuthTokenIdPresent;
      }
   }
}
