package com.airlock.iam.oauth2.infrastructure.resource.v3;

import com.airlock.iam.common.api.infrastructure.annotation.RequiresWritableSession;
import com.airlock.iam.oauth2.api.domain.model.AuthorizationServerId;
import com.airlock.iam.oauth2.application.service.authorization.OAuth2AuthorizationEndpointService;
import com.airlock.iam.oauth2.infrastructure.validation.AuthorizationServerIdValidator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import java.net.URI;
import java.util.List;

@Path("/{authorizationServerId}/authorize")
public class OAuth2AuthorizationEndpointResource {
   private final Provider<OAuth2AuthorizationEndpointService> authorizationEndpointService;
   private final Provider<AuthorizationServerIdValidator> authorizationServerIdValidator;

   @Inject
   public OAuth2AuthorizationEndpointResource(
      Provider<OAuth2AuthorizationEndpointService> authorizationEndpointService, Provider<AuthorizationServerIdValidator> authorizationServerIdValidator
   ) {
      this.authorizationEndpointService = authorizationEndpointService;
      this.authorizationServerIdValidator = authorizationServerIdValidator;
   }

   @ApiResponses(
      {
            @ApiResponse(
               responseCode = "302",
               description = "The request was processed successfully and the response contains the destination url in the location header.",
               content = @Content(mediaType = "text/html")
            ),
            @ApiResponse(
               responseCode = "400",
               description = "An error has occurred and the response body may contain an error object.",
               content = {
                     @Content(mediaType = "application/vnd.api+json", schema = @Schema(ref = "json-api.yaml#/components/schemas/ErrorDocumentResponse")),
                     @Content(mediaType = "application/json", schema = @Schema(ref = "#/components/schemas/OAuth2ErrorResponse"))
               }
            ),
            @ApiResponse(
               responseCode = "404",
               description = "<div class=\"iam-error-code\"><table>\n<tr>\n<td>AUTHORIZATION_SERVER_NOT_FOUND</td>\n<td>The authorization server ID does not exist.</td>\n</tr>\n</table>\n</div>\n",
               content = {
                     @Content(mediaType = "application/vnd.api+json", schema = @Schema(ref = "json-api.yaml#/components/schemas/ErrorDocumentResponse")),
                     @Content(mediaType = "application/json", schema = @Schema(ref = "#/components/schemas/OAuth2ErrorResponse"))
               }
            )
      }
   )
   @GET
   @Operation(
      description = "The authorization endpoint that will redirect to the configured application UI.\n<div class=\"iam-docu\">\n<table>\n<tr><th>Use-Case</th><th>Format</th><th>RFC Reference</th></tr>\n<tr><td>OAuth 2.0 / OpenID Connect: Authorization Code Grant</td><td>Authorization Request</td><td>see <a href=\"https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1\" target=\"_blank\">RFC 6749, Chapter 4.1.1</a></td></tr>\n</table>\n</div>",
      extensions = @Extension(properties = @ExtensionProperty(name = "x-internal", value = "true")),
      tags = "OAuth 2.0/OIDC",
      summary = "Redirect to UI"
   )
   @Produces("text/html")
   @RequiresWritableSession
   public Response authorizationEndpoint(
      @Parameter(description = "The authorization server ID.") @PathParam("authorizationServerId") String authorizationServerId,
      @Parameter(description = "Refer to the referenced RFCs in the use-case table above to see which query parameters must be provided.") @QueryParam(
   "parameters"
) List<String> parameters
   ) {
      ((AuthorizationServerIdValidator)this.authorizationServerIdValidator.get()).validateAuthorizationServer(authorizationServerId);
      URI redirectUri = ((OAuth2AuthorizationEndpointService)this.authorizationEndpointService.get())
         .authorizationEndpointRedirect(AuthorizationServerId.authorizationServerId(authorizationServerId));
      return Response.status(Status.FOUND).header("Location", redirectUri).type("text/plain").build();
   }
}
