package com.airlock.iam.oauth2.domain.service.scopepolicy;

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.oauth2.api.domain.model.OAuth2Scope;
import com.airlock.iam.oauth2.domain.model.scopepolicy.ScopePolicyInput;
import java.util.List;
import java.util.stream.Collectors;

public final class ScopePolicyScopesMandatory implements ScopePolicy {
   private static final ELogger LOG = ELoggerFactory.getLogger(ScopePolicyScopesMandatory.class);

   @Override
   public boolean isValidRequestedScope(List<OAuth2Scope> requestedScopes) {
      return !requestedScopes.isEmpty();
   }

   @Override
   public List<OAuth2Scope> processScopes(ScopePolicyInput scopesToProcess) {
      if (scopesToProcess.requestedScopes().isEmpty()) {
         throw new FailureException("Requested scopes are mandatory in this scope policy");
      }

      if (!scopesToProcess.allowedScopes().isFilterRequestedScopes()) {
         return scopesToProcess.requestedScopes();
      }

      List<OAuth2Scope> filteredScopes = scopesToProcess.requestedScopes()
         .stream()
         .filter(scopesToProcess.allowedScopes().explicitlyAllowedScopes()::contains)
         .collect(Collectors.toList());
      if (filteredScopes.size() != scopesToProcess.requestedScopes().size()) {
         LOG.debug(
            "Filtered the requested scopes %s against the allowed scopes of this client, resulting in %s"
               .formatted(ScopePolicy.toScopeString(scopesToProcess.requestedScopes()), ScopePolicy.toScopeString(filteredScopes))
         );
      }

      return filteredScopes;
   }
}
