package com.airlock.iam.techclientreg.domain.model.registration;

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.techclient.api.domain.model.oauth2.OAuth2TechnicalClientMetadataBuilder;
import com.airlock.iam.techclientreg.api.domain.model.oauth2.OAuth2ClientRegistrationError;
import com.airlock.iam.techclientreg.api.domain.model.oauth2.OAuth2ClientRegistrationRequest;
import com.airlock.iam.techclientreg.api.domain.service.oauth2.OAuth2ClientMetadataProcessor;
import com.airlock.iam.techclientreg.application.configuration.registration.TokenEndpointAuthMethodProcessorConfig;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

@LogicForConfig(TokenEndpointAuthMethodProcessorConfig.class)
public class TokenEndpointAuthMethodProcessor implements OAuth2ClientMetadataProcessor {
   private static final ELogger LOG = ELoggerFactory.getLogger(TokenEndpointAuthMethodProcessor.class);
   private final Provider<TokenEndpointAuthMethodProcessorConfig> config;
   private final ClientMetadataAttributeValidator validator;

   @Inject
   public TokenEndpointAuthMethodProcessor(Provider<TokenEndpointAuthMethodProcessorConfig> config, ClientMetadataAttributeValidator validator) {
      this.config = config;
      this.validator = validator;
   }

   @Override
   public Optional<OAuth2ClientRegistrationError> updateClient(OAuth2ClientRegistrationRequest request, OAuth2TechnicalClientMetadataBuilder clientBuilder) {
      Optional<String> authMethod = this.extractValidTokenEndpointAuthMethod(request);
      if (authMethod.isEmpty()) {
         return ((TokenEndpointAuthMethodProcessorConfig)this.config.get()).isMandatory()
            ? Optional.of(OAuth2ClientRegistrationError.invalidClientMetadata("token_endpoint_auth_method missing or invalid"))
            : Optional.empty();
      }

      clientBuilder.tokenEndpointAuthMethod(authMethod);
      LOG.debug("Using token_endpoint_auth_method value received from the client: " + LogUtil.logSafeString(authMethod.get()));
      return Optional.empty();
   }

   private Optional<String> extractValidTokenEndpointAuthMethod(OAuth2ClientRegistrationRequest request) {
      return request.getMetadata().tokenEndpointAuthMethod().filter(this::isValid);
   }

   private boolean isValid(String requestedAuthMethod) {
      return this.validator
         .isValidMetadataAttribute(
            "token_endpoint_auth_method", requestedAuthMethod, 50, ((TokenEndpointAuthMethodProcessorConfig)this.config.get()).getAllowedValues()
         );
   }
}
