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

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.core.misc.authen.credential.PasswordCredential;
import com.airlock.iam.core.misc.authen.credential.UserCredential;
import com.airlock.iam.core.misc.authen.credential.UserPasswordCredential;
import com.airlock.iam.core.misc.impl.authen.credential.UserPasswordCredentialImpl;
import com.airlock.iam.oauth2.api.domain.model.clientauthentication.ClientAuthenticationMethod;
import com.airlock.iam.oauth2.api.domain.model.http.OAuth2HttpRequest;
import com.airlock.iam.oauth2.application.configuration.clientauthentication.OAuth2BasicAuthClientSecretMethodConfig;
import com.airlock.iam.oauth2.domain.model.clientauthentication.method.KnownClientAuthenticationMethod;
import com.airlock.iam.oauth2.domain.service.OAuth2BasicAuthHeaderUtils;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

@LogicForConfig(OAuth2BasicAuthClientSecretMethodConfig.class)
public final class OAuth2BasicAuthClientSecretMethod implements OAuth2ClientSecretMethod {
   private final Provider<OAuth2BasicAuthClientSecretMethodSettings> settings;

   @Inject
   public OAuth2BasicAuthClientSecretMethod(Provider<OAuth2BasicAuthClientSecretMethodSettings> settings) {
      this.settings = settings;
   }

   @Override
   public Optional<String> getClientIdFromRequest(OAuth2HttpRequest request) {
      return this.getCredentialFromRequest(request).map(UserCredential::getUserName);
   }

   @Override
   public Optional<String> getClientSecretFromRequest(OAuth2HttpRequest request) {
      return this.getCredentialFromRequest(request).map(PasswordCredential::getPassword);
   }

   @Override
   public ClientAuthenticationMethod clientAuthenticationMethod() {
      return KnownClientAuthenticationMethod.BASIC_AUTH_CLIENT_SECRET;
   }

   private Optional<UserPasswordCredential> getCredentialFromRequest(OAuth2HttpRequest request) {
      return OAuth2BasicAuthHeaderUtils.parseOAuth2BasicAuthHeader(
            request.getHeader("Authorization"), ((OAuth2BasicAuthClientSecretMethodSettings)this.settings.get()).charset()
         )
         .map(header -> new UserPasswordCredentialImpl(header.username().getValue(), header.password().getValue()));
   }
}
