package com.airlock.iam.authentication.domain.model.risk;

import com.airlock.iam.authentication.api.domain.model.risk.extractor.RiskTag;
import com.airlock.iam.authentication.application.configuration.risk.RiskAssessmentStepConfig;
import com.airlock.iam.authentication.domain.service.risk.RiskExtractorService;
import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.common.api.domain.model.request.RequestAttributes;
import com.airlock.iam.common.api.domain.model.user.UserIdentity;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.flow.api.domain.model.step.FlowStep;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.flow.api.domain.model.tag.Tag;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@LogicForConfig(RiskAssessmentStepConfig.class)
public final class RiskAssessmentStep implements FlowStep {
   private final Provider<RiskExtractorService> riskExtractorService;
   private final Provider<PrincipalInfo> user;
   private final Provider<RequestAttributes> requestAttributes;

   @Inject
   public RiskAssessmentStep(Provider<RiskExtractorService> riskExtractorService, Provider<PrincipalInfo> user, Provider<RequestAttributes> requestAttributes) {
      this.riskExtractorService = riskExtractorService;
      this.user = user;
      this.requestAttributes = requestAttributes;
   }

   @Override
   public StepResult initialize() {
      Optional<UserId> userId = ((PrincipalInfo)this.user.get()).getKnownIdentity().map(UserIdentity::id);
      RiskTags riskTags = ((RiskExtractorService)this.riskExtractorService.get()).extractRiskTags(userId, (RequestAttributes)this.requestAttributes.get());
      return this.stepResultFactory().success().addObtainedTags(toTags(riskTags)).build();
   }

   @Override
   public String getDescription() {
      return "Risk Assessment Step";
   }

   private static Set<Tag> toTags(RiskTags riskTags) {
      return riskTags.getRiskTags().stream().map(RiskTag::getTag).flatMap(Optional::stream).collect(Collectors.toSet());
   }
}
