package com.airlock.iam.transactionapproval.infrastructure.resource.selection;

import ch.ergon.restal.jsonapi.document.data.ResourceObject;
import com.airlock.iam.flow.api.domain.model.flow.FlowResult;
import com.airlock.iam.flow.api.domain.model.selection.Option;
import com.airlock.iam.flow.api.infrastructure.mapper.FlowResultMapper;
import com.airlock.iam.flow.application.configuration.selection.step.SelectionOptions;
import com.airlock.iam.flow.domain.model.selection.step.InteractiveSelection;
import com.airlock.iam.flow.infrastructure.mapper.FlowResultToCollectionDocumentMapper;
import com.airlock.iam.transactionapproval.api.infrastructure.generated.transfer.response.TransactionApprovalFlowResultDataResourceDocument;
import com.airlock.iam.transactionapproval.infrastructure.generated.transfer.response.TransactionApprovalSelectionOptionDataCollectionDocument;
import com.airlock.iam.transactionapproval.infrastructure.transfer.response.TransactionApprovalSelectionOptionData;
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.validation.constraints.Size;
import jakarta.ws.rs.Consumes;
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("transaction-approval/selection")
public final class TransactionApprovalInteractiveSelectionResource {
   private final FlowResultMapper mapper;
   private final InteractiveSelection selection;
   private final MapperFacade mapperFacade;

   @Inject
   public TransactionApprovalInteractiveSelectionResource(FlowResultMapper mapper, InteractiveSelection selection, MapperFacade mapperFacade) {
      this.mapper = mapper;
      this.selection = selection;
      this.mapperFacade = mapperFacade;
   }

   @ApiResponse(
      responseCode = "200",
      description = "Available selection options retrieved.",
      content = {
            @Content(mediaType = "application/vnd.api+json", schema = @Schema(implementation = TransactionApprovalSelectionOptionDataCollectionDocument.class)),
            @Content(mediaType = "application/json", schema = @Schema(implementation = TransactionApprovalSelectionOptionDataCollectionDocument.class))
      }
   )
   @Deprecated
   @POST
   @Path("options/retrieve")
   @Produces({"application/vnd.api+json", "application/json;qs=0.9"})
   @Operation(
      description = "> [!caution]\n> This endpoint is deprecated. The selection options are returned as\n<a href=\"#additionalTransactionApprovalAttributes\">additional attribute</a> with the <tt>SELECTION_REQUIRED</tt> next step code.\n<p>Retrieval of available options for selection.</p>\n<p>Retrieves the available selection options in a transaction approval flow.</p>\n<div class=\"iam-resource-return\">The available options.</div>",
      tags = "Flow Control",
      summary = "List options"
   )
   public Response retrieveOptions() {
      FlowResult result = this.selection.getOptions();
      return FlowResultToCollectionDocumentMapper.flowResultDataToCollectionDocumentMapper(this.mapper, this.mapperFacade)
         .map(result, SelectionOptions.class, TransactionApprovalSelectionOptionData.class, Option::getName);
   }

   @ApiResponses(
      {
            @ApiResponse(
               responseCode = "200",
               description = "Selected the chosen step and requires next step actions.",
               content = {
                     @Content(
                        mediaType = "application/vnd.api+json",
                        schema = @Schema(implementation = TransactionApprovalFlowResultDataResourceDocument.class)
                     ),
                     @Content(mediaType = "application/json", schema = @Schema(implementation = TransactionApprovalFlowResultDataResourceDocument.class))
               }
            ),
            @ApiResponse(
               responseCode = "400",
               description = "<div class=\"iam-error-code\"><table>\n<tr>\n<td>SELECTION_FAILED</td>\n<td>The selected option is not available.</td>\n</tr>\n</table>\n</div>\n<br>Possible next step: <tt>SELECTION_REQUIRED</tt> (as documented <a href=\"#nextApprovalStepCodes\">here</a>).\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"))
               }
            )
      }
   )
   @POST
   @Path("options/{id}/select")
   @Consumes("application/json")
   @Produces({"application/vnd.api+json", "application/json;qs=0.9"})
   @Operation(
      description = "Selects the given option if available.\n<div class=\"iam-resource-return\">The selected next step or an error if the option is invalid.</div>",
      tags = "Flow Control",
      summary = "Select option"
   )
   public Response selectOption(@Parameter(description = "option to select.") @PathParam("id") @Size(min = 1, max = 1000) String id) {
      FlowResult result = this.selection.select(Option.of(id));
      return this.mapper.toResponse(result, new ResourceObject[0]);
   }
}
