package com.airlock.iam.oauth2.domain.model.resource;

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.api.domain.model.user.PersistentUser;
import com.airlock.iam.oauth2.api.domain.model.OAuth2ClientId;
import com.airlock.iam.oauth2.api.domain.model.OAuth2Scope;
import com.airlock.iam.oauth2.api.domain.model.claims.conditions.ClaimCondition;
import com.airlock.iam.oauth2.api.domain.service.roles.RoleTransformationProvider;
import com.airlock.iam.oauth2.application.configuration.resource.OAuth2UserRolesResourceProviderConfig;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;
import java.util.Set;

@LogicForConfig(OAuth2UserRolesResourceProviderConfig.class)
public final class OAuth2UserRolesResourceProvider implements OAuth2ResourceProvider {
   private final Provider<OAuth2ResourceIdentifier> identifier;
   private final Provider<RoleTransformationProvider> roleTransformation;
   private final Provider<Optional<ClaimCondition>> condition;

   @Inject
   public OAuth2UserRolesResourceProvider(
      Provider<OAuth2ResourceIdentifier> identifier, Provider<RoleTransformationProvider> roleTransformation, Provider<Optional<ClaimCondition>> condition
   ) {
      this.identifier = identifier;
      this.roleTransformation = roleTransformation;
      this.condition = condition;
   }

   @Override
   public Optional<OAuth2ResourceResult> getResourceResult(PersistentUser user, Set<OAuth2Scope> givenScopes, OAuth2ClientId clientId) {
      if (((Optional)this.condition.get()).isPresent() && !((ClaimCondition)((Optional)this.condition.get()).get()).isSatisfied(givenScopes)) {
         return Optional.empty();
      }

      Set<Role> roles = user.getRoles();
      Object[] transformedRoles = ((RoleTransformationProvider)this.roleTransformation.get())
         .roleTransformation(clientId)
         .apply(roles)
         .stream()
         .map(Role::formatRole)
         .toArray();
      return Optional.of(OAuth2ResourceResult.resourceResult().add((OAuth2ResourceIdentifier)this.identifier.get(), transformedRoles));
   }
}
