package com.airlock.iam.common.infrastructure.request;

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.common.application.configuration.gateway.extractor.RequestMtlsClientCertificateExtractorConfig;
import com.airlock.iam.common.domain.model.gateway.ClientCertificateExtractionFormat;
import com.airlock.iam.common.domain.model.gateway.HttpRequestMtlsClientCertificateExtractor;
import com.airlock.iam.common.domain.model.request.ClientTlsCertificate;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Optional;

@LogicForConfig(RequestMtlsClientCertificateExtractorConfig.class)
public final class HttpRequestMtlsClientCertificateExtractorImpl implements HttpRequestMtlsClientCertificateExtractor {
   private static final ELogger LOG = ELoggerFactory.getLogger(HttpRequestMtlsClientCertificateExtractorImpl.class);
   private final RequestMtlsClientCertificateExtractorConfig config;
   private final Provider<HttpServletRequest> request;
   private final Provider<ClientCertificateExtractionFormat> clientCertificateExtractionStrategy;

   @Inject
   public HttpRequestMtlsClientCertificateExtractorImpl(
      RequestMtlsClientCertificateExtractorConfig config,
      Provider<HttpServletRequest> request,
      Provider<ClientCertificateExtractionFormat> clientCertificateExtractionStrategy
   ) {
      this.request = request;
      this.config = config;
      this.clientCertificateExtractionStrategy = clientCertificateExtractionStrategy;
   }

   @Override
   public Optional<ClientTlsCertificate> getMtlsClientCertificate() {
      LOG.debug(String.format("Trying to extract mTLS client certificate from HTTP request header %s.", LogUtil.quote(this.config.getHttpHeaderName())));
      return Optional.ofNullable(((HttpServletRequest)this.request.get()).getHeader(this.config.getHttpHeaderName()))
         .map(String::trim)
         .map(headerValue -> ((ClientCertificateExtractionFormat)this.clientCertificateExtractionStrategy.get()).extractCertificate(headerValue));
   }
}
