package com.airlock.iam.oauth2.domain.model.metadata;

import com.airlock.iam.base.api.domain.model.exception.ViolationException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.URI;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OAuth2AsCentricEndpointUriComposer implements OAuth2EndpointUriComposer {
   private static final Pattern PROVIDER_URI_PATTERN = Pattern.compile("^(.*)/rest/oauth2/authorization-servers/([^/]+)/?$");
   private final URI servletBaseUri;
   private final URI oauth2RestBaseUri;
   private final URI oauth2DynamicClientRegistrationUri;

   public static OAuth2AsCentricEndpointUriComposer asCentricEndpointUriComposer(URI providerBaseUri) {
      Matcher matcher = PROVIDER_URI_PATTERN.matcher(providerBaseUri.toString());
      ViolationException.checkTrue(matcher.matches(), "Cannot derive provider URI from metadata/discovery endpoint request: " + providerBaseUri);
      URI servletBaseUri = URI.create(matcher.replaceFirst("$1/oauth2/v3/$2"));
      URI oauth2RestBaseUri = URI.create(matcher.replaceFirst("$1/rest/oauth2/authorization-servers/$2"));
      URI oauth2DynamicClientRegistrationUri = URI.create(matcher.replaceFirst("$1/rest/public/tech-client-registration/oauth2/$2/register"));
      return new OAuth2AsCentricEndpointUriComposer(servletBaseUri, oauth2RestBaseUri, oauth2DynamicClientRegistrationUri);
   }

   @Override
   public URI providerBaseURI() {
      return this.oauth2RestBaseUri;
   }

   @Override
   public URI registrationEndpointURI() {
      return this.oauth2DynamicClientRegistrationUri;
   }

   @Override
   public URI jwksURI() {
      return this.oAuth2RestEndpointURI("jwks");
   }

   @Override
   public URI authorizationEndpointURI() {
      return this.servletUri("authorize");
   }

   @Override
   public URI tokenEndpointURI() {
      return this.oAuth2RestEndpointURI("token");
   }

   @Override
   public URI pushedAuthorizationRequestURI() {
      return this.oAuth2RestEndpointURI("par");
   }

   @Override
   public URI revocationEndpointURI() {
      return this.oAuth2RestEndpointURI("revoke");
   }

   @Override
   public URI introspectionEndpointURI() {
      return this.oAuth2RestEndpointURI("introspect");
   }

   @Override
   public URI userInfoEndpointURI() {
      return this.oAuth2RestEndpointURI("userinfo");
   }

   @Override
   public URI checkSessionIframeURI() {
      return this.servletUri("check-session");
   }

   private URI servletUri(String path) {
      return this.servletBaseUri.resolve(this.servletBaseUri.getPath() + "/").normalize().resolve(path);
   }

   private URI oAuth2RestEndpointURI(String resourcePath) {
      return this.oauth2RestBaseUri.resolve(this.oauth2RestBaseUri.getPath() + "/").normalize().resolve(resourcePath);
   }

   @SuppressFBWarnings(justification = "generated code")
   private OAuth2AsCentricEndpointUriComposer(URI servletBaseUri, URI oauth2RestBaseUri, URI oauth2DynamicClientRegistrationUri) {
      this.servletBaseUri = servletBaseUri;
      this.oauth2RestBaseUri = oauth2RestBaseUri;
      this.oauth2DynamicClientRegistrationUri = oauth2DynamicClientRegistrationUri;
   }
}
