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

import com.airlock.iam.authentication.infrastructure.generated.transfer.response.AuthenticationGotoTargetAttributesDataCollectionDocument;
import com.airlock.iam.authentication.infrastructure.transfer.response.AuthenticationGotoTargetAttributesData;
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.InteractiveGotoTargetCollection;
import com.airlock.iam.flow.domain.model.step.InteractiveGoto;
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("goto-targets")
public final class AuthenticationInteractiveGotoResource {
   private final Provider<InteractiveGoto> interactiveGoto;
   private final FlowResultMapper mapper;
   private final MapperFacade mapperFacade;

   @Inject
   public AuthenticationInteractiveGotoResource(Provider<InteractiveGoto> interactiveGoto, FlowResultMapper mapper, MapperFacade mapperFacade) {
      this.interactiveGoto = interactiveGoto;
      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 = AuthenticationGotoTargetAttributesDataCollectionDocument.class)),
            @Content(mediaType = "application/json", schema = @Schema(implementation = AuthenticationGotoTargetAttributesDataCollectionDocument.class))
      }
   )
   @Operation(
      description = "Retrieves possible target steps of an interactive goto.\n<div class=\"iam-resource-return\">A list of target steps.</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 = ((InteractiveGoto)this.interactiveGoto.get()).retrieveGotoTargets();
      return FlowResultToCollectionDocumentMapper.flowResultDataToCollectionDocumentMapper(this.mapper, this.mapperFacade)
         .map(result, InteractiveGotoTargetCollection.class, AuthenticationGotoTargetAttributesData.class, target -> target.getTargetStepId().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>GOTO_FAILED</td>\n<td>The selected step ID is not available.</td>\n</tr>\n</table>\n</div>\n<br>Possible next step: always the same as before the goto 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 = "Go to the selected flow step.\n<div class=\"iam-resource-return\">The required next step action or an error if the step ID is invalid.</div>",
      tags = "Flow Control",
      summary = "Go to step"
   )
   @POST
   @Path("{stepId}/goto")
   @Produces({"application/vnd.api+json", "application/json;qs=0.9"})
   public Response doGoto(@Parameter(description = "The goto target's step ID.") @PathParam("stepId") @Size(min = 1, max = 30) String stepId) {
      FlowResult result = ((InteractiveGoto)this.interactiveGoto.get()).doGoto(new StepId(stepId));
      return this.mapper.toResponse(result);
   }
}
