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

import com.airlock.iam.oauth2.api.domain.model.AuthorizationServerId;
import com.airlock.iam.oauth2.application.service.authorization.OAuth2CheckSessionEndpointService;
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.core.Response;
import jakarta.ws.rs.core.Response.Status;

@Path("/{authorizationServerId}/check-session")
public class OAuth2CheckSessionEndpointResource {
   private final Provider<OAuth2CheckSessionEndpointService> checkSessionEndpointService;
   private final Provider<AuthorizationServerIdValidator> authorizationServerIdValidator;

   @Inject
   public OAuth2CheckSessionEndpointResource(
      Provider<OAuth2CheckSessionEndpointService> checkSessionEndpointService, Provider<AuthorizationServerIdValidator> authorizationServerIdValidator
   ) {
      this.checkSessionEndpointService = checkSessionEndpointService;
      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 check-session 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>Specification Reference</th></tr>\n<tr><td>OAuth 2.0 / OpenID Connect: OP iframe endpoint </td><td>OP iframe</td><td>see <a href=\"https://openid.net/specs/openid-connect-session-1_0.html#OPiframe\" target=\"_blank\">OpenID Connect Session Management 1.0, Chapter 3.2</a></td></tr>\n</table>\n</div>",
      extensions = @Extension(properties = @ExtensionProperty(name = "x-internal", value = "true")),
      tags = "OAuth 2.0/OIDC",
      summary = "Check session"
   )
   @Produces("text/html")
   public Response checkSessionEndpoint(
      @Parameter(description = "The authorization server ID.") @PathParam("authorizationServerId") String authorizationServerId
   ) {
      ((AuthorizationServerIdValidator)this.authorizationServerIdValidator.get()).validateAuthorizationServer(authorizationServerId);
      return !((OAuth2CheckSessionEndpointService)this.checkSessionEndpointService.get())
            .hasOpenIDConnectSessionManagement(AuthorizationServerId.authorizationServerId(authorizationServerId))
         ? Response.status(Status.NOT_FOUND).build()
         : Response.status(Status.FOUND)
            .header(
               "Location",
               ((OAuth2CheckSessionEndpointService)this.checkSessionEndpointService.get())
                  .checkSessionRedirect(AuthorizationServerId.authorizationServerId(authorizationServerId))
            )
            .type("text/plain")
            .build();
   }
}
