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

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.misc.log.LogUtil;
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.FlowCondition;
import com.airlock.iam.flow.shared.application.configuration.condition.RoleMatchingConditionConfig;
import com.airlock.iam.flow.shared.domain.model.valueprovider.RoleProvider;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

@LogicForConfig(RoleMatchingConditionConfig.class)
public class RoleMatchingCondition implements FlowCondition {
   private final Provider<List<RoleProvider>> roleProviders;
   private final Provider<PrincipalInfo> principalInfo;
   private final RoleMatchingConditionConfig config;

   @Inject
   public RoleMatchingCondition(Provider<List<RoleProvider>> roleProviders, Provider<PrincipalInfo> principalInfo, RoleMatchingConditionConfig config) {
      this.roleProviders = roleProviders;
      this.principalInfo = principalInfo;
      this.config = config;
   }

   @Override
   public boolean isFulfilled() {
      Optional<UserIdentity> userIdentity = ((PrincipalInfo)this.principalInfo.get()).getKnownIdentity();
      return ((List)this.roleProviders.get())
         .stream()
         .flatMap(p -> userIdentity.stream().map(p::provideRoles).flatMap(Collection::stream))
         .anyMatch(role -> role.formatRole().matches(this.config.getRolePattern().pattern()));
   }

   @Override
   public String displayName() {
      return "User Role Matches " + LogUtil.quote(this.config.getRolePattern());
   }
}
