package com.airlock.iam.oauth2.application.configuration.client;

import com.airlock.iam.oauth2.domain.model.client.OAuth2ClientSideCredentials;
import com.airlock.iam.oauth2.domain.model.client.communication.OpenIDConnectIdTokenSignatureValidator;
import com.airlock.iam.oauth2.domain.model.token.IdToken;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.license.PluginLicenseRestriction;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import com.google.common.annotations.VisibleForTesting;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.lang3.StringUtils;

@Plugin(description = "OpenID Connect ID Token signature validation plugin for HS256 signatures.", displayName = "OIDC HS256 Signature Validator")
@PluginLicenseRestriction(moduleAffiliation = "OAuthClient")
public class OpenIDConnectHS256SignatureValidator implements OpenIDConnectIdTokenSignatureValidator {
   @StringProperty(
      description = "Static key to use in place of the client secret. Must be at least 32 characters long. If left blank, the client secret is used as signature key and SHOULD be manually verified to be at least 32 characters long.",
      optional = true,
      isSensitive = true,
      minLength = 32
   )
   private String staticKey;

   @Override
   public boolean validateIdTokenSignature(IdToken idToken, OAuth2ClientSideCredentials clientCredentials) {
      String signatureKey = this.getKey(clientCredentials);
      return idToken.validateHS256Signature(signatureKey);
   }

   private String getKey(OAuth2ClientSideCredentials clientCredentials) {
      return StringUtils.isNotBlank(this.staticKey)
         ? this.staticKey
         : clientCredentials.clientSecret().orElseThrow(() -> new IllegalArgumentException("Client secret missing. Unable to validate signature."));
   }

   @VisibleForTesting
   void setStaticKey(String staticKey) {
      this.staticKey = staticKey;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static OpenIDConnectHS256SignatureValidator.OpenIDConnectHS256SignatureValidatorBuilder builder() {
      return new OpenIDConnectHS256SignatureValidator.OpenIDConnectHS256SignatureValidatorBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public OpenIDConnectHS256SignatureValidator() {
   }

   @SuppressFBWarnings(justification = "generated code")
   public OpenIDConnectHS256SignatureValidator(String staticKey) {
      this.staticKey = staticKey;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class OpenIDConnectHS256SignatureValidatorBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String staticKey;

      @SuppressFBWarnings(justification = "generated code")
      OpenIDConnectHS256SignatureValidatorBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public OpenIDConnectHS256SignatureValidator.OpenIDConnectHS256SignatureValidatorBuilder staticKey(String staticKey) {
         this.staticKey = staticKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OpenIDConnectHS256SignatureValidator build() {
         return new OpenIDConnectHS256SignatureValidator(this.staticKey);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "OpenIDConnectHS256SignatureValidator.OpenIDConnectHS256SignatureValidatorBuilder(staticKey=" + this.staticKey + ")";
      }
   }
}
