package com.airlock.iam.authentication.infrastructure.resource;

import com.airlock.iam.authentication.infrastructure.generated.transfer.response.AuthenticationDynamicStepActivationDataCollectionDocument;
import com.airlock.iam.authentication.infrastructure.transfer.response.AuthenticationDynamicStepActivationData;
import com.airlock.iam.flow.api.domain.model.flow.FlowResult;
import com.airlock.iam.flow.api.domain.model.step.StepId;
import com.airlock.iam.flow.api.infrastructure.mapper.FlowResultMapper;
import com.airlock.iam.flow.auth.api.infrastructure.generated.transfer.response.AuthenticationFlowResultDataResourceDocument;
import com.airlock.iam.flow.domain.model.dynamicactivation.DynamicStepActivation;
import com.airlock.iam.flow.domain.model.dynamicactivation.DynamicStepActivationCollection;
import com.airlock.iam.flow.infrastructure.mapper.FlowResultToCollectionDocumentMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
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.validation.constraints.Size;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Response;
import ma.glasnost.orika.MapperFacade;

@Path("dynamic-steps")
public final class AuthenticationDynamicStepActivationResource {
   private final Provider<DynamicStepActivation> dynamicActivation;
   private final FlowResultMapper mapper;
   private final MapperFacade mapperFacade;

   @Inject
   public AuthenticationDynamicStepActivationResource(Provider<DynamicStepActivation> dynamicActivation, FlowResultMapper mapper, MapperFacade mapperFacade) {
      this.dynamicActivation = dynamicActivation;
      this.mapper = mapper;
      this.mapperFacade = mapperFacade;
   }

   @ApiResponse(
      responseCode = "200",
      description = "The information has been successfully returned.",
      content = {
            @Content(
               mediaType = "application/vnd.api+json",
               schema = @Schema(implementation = AuthenticationDynamicStepActivationDataCollectionDocument.class)
            ),
            @Content(mediaType = "application/json", schema = @Schema(implementation = AuthenticationDynamicStepActivationDataCollectionDocument.class))
      }
   )
   @Operation(
      description = "Retrieves list of all steps that can be dynamically activated or deactivated on the current step.\n<div class=\"iam-resource-return\">A list of dynamic steps with their activation information.</div>",
      tags = "Flow Control",
      summary = "List steps"
   )
   @POST
   @Path("retrieve")
   @Produces({"application/vnd.api+json", "application/json;qs=0.9"})
   public Response retrieve() {
      FlowResult result = ((DynamicStepActivation)this.dynamicActivation.get()).retrieveDynamicStepActivationInformation();
      return FlowResultToCollectionDocumentMapper.flowResultDataToCollectionDocumentMapper(this.mapper, this.mapperFacade)
         .map(result, DynamicStepActivationCollection.class, AuthenticationDynamicStepActivationData.class, activation -> activation.getStepId().getStepId());
   }

   @ApiResponses(
      {
            @ApiResponse(
               responseCode = "200",
               description = "Authentication successful or further steps required.",
               content = {
                     @Content(mediaType = "application/vnd.api+json", schema = @Schema(implementation = AuthenticationFlowResultDataResourceDocument.class)),
                     @Content(mediaType = "application/json", schema = @Schema(implementation = AuthenticationFlowResultDataResourceDocument.class))
               }
            ),
            @ApiResponse(
               responseCode = "400",
               description = "<div class=\"iam-error-code\"><table>\n<tr>\n<td>INVALID_STEP_ID</td>\n<td>The selected step ID is not available.</td>\n</tr>\n<tr>\n<td>STEP_ACTIVATION_NOT_ALLOWED</td>\n<td>The selected step cannot be activated.</td>\n</tr>\n</table>\n</div>\n<br>Possible next step: always the same as before the activate call.\n",
               content = {
                     @Content(mediaType = "application/vnd.api+json", schema = @Schema(ref = "json-api.yaml#/components/schemas/ErrorDocumentResponse")),
                     @Content(mediaType = "application/json", schema = @Schema(ref = "json-api.yaml#/components/schemas/ErrorDocumentResponse"))
               }
            )
      }
   )
   @Operation(
      description = "Activates a flow step.\n<div class=\"iam-resource-return\">The required next step action or an error if the step ID is invalid or the step could not be activated.</div>",
      tags = "Flow Control",
      summary = "Activate step"
   )
   @POST
   @Path("{stepId}/activate")
   @Produces({"application/vnd.api+json", "application/json;qs=0.9"})
   public Response activate(@Parameter(description = "The ID of the step to be activated.") @PathParam("stepId") @Size(min = 1, max = 30) String stepId) {
      FlowResult result = ((DynamicStepActivation)this.dynamicActivation.get()).activateStep(new StepId(stepId));
      return this.mapper.toResponse(result);
   }

   @ApiResponses(
      {
            @ApiResponse(
               responseCode = "200",
               description = "Authentication successful or further steps required.",
               content = {
                     @Content(mediaType = "application/vnd.api+json", schema = @Schema(implementation = AuthenticationFlowResultDataResourceDocument.class)),
                     @Content(mediaType = "application/json", schema = @Schema(implementation = AuthenticationFlowResultDataResourceDocument.class))
               }
            ),
            @ApiResponse(
               responseCode = "400",
               description = "<div class=\"iam-error-code\"><table>\n<tr>\n<td>INVALID_STEP_ID</td>\n<td>The selected step ID is not available.</td>\n</tr>\n<tr>\n<td>STEP_DEACTIVATION_NOT_ALLOWED</td>\n<td>The selected step cannot be deactivated.</td>\n</tr>\n</table>\n</div>\n<br>Possible next step: always the same as before the deactivate call.\n",
               content = {
                     @Content(mediaType = "application/vnd.api+json", schema = @Schema(ref = "json-api.yaml#/components/schemas/ErrorDocumentResponse")),
                     @Content(mediaType = "application/json", schema = @Schema(ref = "json-api.yaml#/components/schemas/ErrorDocumentResponse"))
               }
            )
      }
   )
   @Operation(
      description = "Deactivates a flow step.\n<div class=\"iam-resource-return\">The required next step action or an error if the step ID is invalid or the step could not be deactivated.</div>",
      tags = "Flow Control",
      summary = "Deactivate step"
   )
   @POST
   @Path("{stepId}/deactivate")
   @Produces({"application/vnd.api+json", "application/json;qs=0.9"})
   public Response deactivate(@Parameter(description = "The ID of the step to be deactivated") @PathParam("stepId") @Size(min = 1, max = 30) String stepId) {
      FlowResult result = ((DynamicStepActivation)this.dynamicActivation.get()).deactivateStep(new StepId(stepId));
      return this.mapper.toResponse(result);
   }
}
