package com.airlock.iam.saml2.domain.model.assertion.attribute;

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.common.api.domain.model.role.Role;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.flow.shared.domain.model.valueprovider.RoleProvider;
import com.airlock.iam.saml2.application.configuration.assertion.attribute.RolesFlowAttributeConfig;
import com.airlock.iam.saml2.domain.model.assertion.FlowSaml2Attribute;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@LogicForConfig(RolesFlowAttributeConfig.class)
public class Saml2RolesAttributeImpl implements Saml2AttributeProvider {
   private final RolesFlowAttributeConfig config;
   private final Provider<PrincipalInfo> principalInfo;
   private final Provider<List<RoleProvider>> roleProviders;

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

   @Override
   public Optional<FlowSaml2Attribute> getAttribute() {
      Set<Role> roles = this.collectRolesFromProviders();
      return roles.isEmpty()
         ? Optional.empty()
         : Optional.of(new FlowSaml2Attribute(this.config.getSamlAttributeName(), roles.stream().map(Role::formatRole).toList(), this.config.getNameFormat()));
   }

   private Set<Role> collectRolesFromProviders() {
      return ((List)this.roleProviders.get())
         .stream()
         .flatMap(provider -> provider.provideRoles(((PrincipalInfo)this.principalInfo.get()).tryGetAuthenticatedIdentity()).stream())
         .collect(Collectors.toSet());
   }
}
