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

import com.airlock.iam.common.api.domain.model.otp.UnverifiedOtp;
import com.airlock.iam.flow.api.domain.model.flow.FlowResult;
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.shared.domain.model.email.EmailVerification;
import com.airlock.iam.flow.shared.infrastructure.transfer.request.GenericOtpCheckRequest;
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.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Response;

@Path("/email/verification")
public class EmailVerificationAuthFlowResource {
   private final FlowResultMapper mapper;
   private final Provider<EmailVerification> emailVerification;

   @Inject
   public EmailVerificationAuthFlowResource(FlowResultMapper mapper, Provider<EmailVerification> emailVerification) {
      this.mapper = mapper;
      this.emailVerification = emailVerification;
   }

   @ApiResponses(
      {
            @ApiResponse(
               responseCode = "200",
               description = "OTP successfully verified and authentication completed if no 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>EMAIL_OTP_WRONG</td>\n<td>OTP could not be validated successfully. Retry with correct OTP.</td>\n</tr>\n</table>\n</div>\n<br>Possible next step: <tt>EMAIL_OTP_REQUIRED</tt> (as documented <a href=\"#nextAuthStepCodes\">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"))
               }
            ),
            @ApiResponse(
               responseCode = "403",
               description = "<div class=\"iam-error-code\"><table>\n<tr>\n<td>EMAIL_OTP_WRONG</td>\n<td>OTP could not be validated successfully and no retries are allowed.</td>\n</tr>\n<tr>\n<td>EMAIL_OTP_EXPIRED</td>\n<td>OTP has expired.</td>\n</tr>\n</table>\n</div>\n<br>The current authentication flow has been aborted.\n<br>Possible next step: none.\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 = "Checks the OTP for the email channel verification.\n<div class=\"iam-resource-return\">Whether the OTP was accepted.</div>",
      tags = "Email OTP",
      summary = "Verify OTP"
   )
   @Path("otp/check")
   @POST
   @Consumes("application/json")
   @Produces({"application/vnd.api+json", "application/json;qs=0.9"})
   public Response verifyEmailOtp(@Parameter(description = "Contains the OTP to be verified.") @NotNull @Valid GenericOtpCheckRequest request) {
      FlowResult result = ((EmailVerification)this.emailVerification.get()).verifyEmailOtp(UnverifiedOtp.unverifiedOtp(request.getOtp()));
      return this.mapper.toResponse(result);
   }
}
