package com.airlock.iam.oauth2.domain.service.clientauthentication.clientsecret;

import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.oauth2.api.domain.model.clientauthentication.OAuth2AuthClientId;
import com.airlock.iam.oauth2.api.domain.model.http.OAuth2HttpRequest;
import com.airlock.iam.oauth2.api.domain.service.clientauthentication.OAuth2ClientAuthenticationParser;
import com.airlock.iam.oauth2.domain.model.OAuth2Param;
import com.airlock.iam.oauth2.domain.model.clientauthentication.OAuth2ClientSecretAuthenticationPayload;
import java.util.Optional;
import java.util.function.Predicate;

public final class OAuth2ClientSecretAuthenticationParser implements OAuth2ClientAuthenticationParser<OAuth2ClientSecretAuthenticationPayload> {
   private static final ELogger LOG = ELoggerFactory.getLogger(OAuth2ClientSecretAuthenticationParser.class);
   private final OAuth2ClientSecretMethod clientSecretMethod;

   public OAuth2ClientSecretAuthenticationParser(OAuth2ClientSecretMethod clientSecretMethod) {
      this.clientSecretMethod = clientSecretMethod;
   }

   @Override
   public Optional<OAuth2ClientSecretAuthenticationPayload> parse(OAuth2HttpRequest request) {
      Optional<String> clientId = this.parseClientId(request);
      Optional<String> clientSecret = this.parseClientSecret(request);
      return !clientId.isEmpty() && !clientSecret.isEmpty()
         ? Optional.of(
            OAuth2ClientSecretAuthenticationPayload.builder()
               .clientId(OAuth2AuthClientId.oAuth2AuthClientId(clientId.get()))
               .clientIdFromRequest(request.getParameter(OAuth2Param.CLIENT_ID.getParameterName()))
               .secret(clientSecret.get())
               .method(this.clientSecretMethod.clientAuthenticationMethod())
               .build()
         )
         : Optional.empty();
   }

   private Optional<String> parseClientId(OAuth2HttpRequest request) {
      Optional<String> clientId = this.clientSecretMethod.getClientIdFromRequest(request).filter(Predicate.not(String::isBlank));
      if (clientId.isEmpty()) {
         LOG.info("Client ID could not be extracted from authentication.");
      }

      return clientId;
   }

   private Optional<String> parseClientSecret(OAuth2HttpRequest request) {
      Optional<String> clientSecret = this.clientSecretMethod.getClientSecretFromRequest(request).filter(Predicate.not(String::isEmpty));
      if (clientSecret.isEmpty()) {
         LOG.info("Client Secret could not be extracted from authentication.");
      }

      return clientSecret;
   }
}
