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

import com.airlock.iam.common.api.infrastructure.annotation.RequiresWritableSession;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.saml2.application.service.sp.Saml2SpAssertionConsumerService;
import com.airlock.iam.saml2.application.service.sp.Saml2SpInitiatedSsoService;
import com.airlock.iam.saml2.domain.model.sp.Saml2SpInitiatedSsoId;
import com.airlock.iam.saml2.infrastructure.util.Saml2RequestThreadContext;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import java.net.URI;

@Path("/sp/sso")
public final class Saml2SpSsoResource {
   private static final ELogger LOG = ELoggerFactory.getLogger(Saml2SpSsoResource.class);
   private final Provider<Saml2SpInitiatedSsoService> spInitiatedSsoService;
   private final Provider<Saml2SpAssertionConsumerService> acsService;

   @Inject
   Saml2SpSsoResource(Provider<Saml2SpInitiatedSsoService> spInitiatedSsoService, Provider<Saml2SpAssertionConsumerService> acsService) {
      this.spInitiatedSsoService = spInitiatedSsoService;
      this.acsService = acsService;
   }

   @Path("metaAlias/{metaAlias}")
   @GET
   @Produces("text/html")
   @RequiresWritableSession
   public Response ssoRequestByGet(
      @NotNull(message = "{metaAlias.notNull}") @Size(min = 1, max = 100, message = "{metaAlias.size}") @Pattern(
   regexp = "[a-zA-Z0-9][a-zA-Z0-9-_.]{1,99}",
   message = "{metaAlias.pattern}"
) @PathParam("metaAlias") String metaAlias
   ) {
      return this.handleSsoRequest();
   }

   @Path("metaAlias/{metaAlias}")
   @POST
   @Produces("text/html")
   public Response ssoRequestByPost(
      @NotNull(message = "{metaAlias.notNull}") @Size(min = 1, max = 100, message = "{metaAlias.size}") @Pattern(
   regexp = "[a-zA-Z0-9][a-zA-Z0-9-_.]{1,99}",
   message = "{metaAlias.pattern}"
) @PathParam("metaAlias") String metaAlias
   ) {
      return this.handleSsoRequest();
   }

   private Response handleSsoRequest() {
      URI redirectUri = ((Saml2SpAssertionConsumerService)this.acsService.get()).consumeAssertion();
      LOG.info("Redirecting to UI: " + redirectUri.toASCIIString());
      return Response.status(Status.FOUND).header("Location", redirectUri).build();
   }

   @Path("init")
   @GET
   @RequiresWritableSession
   public Response ssoInit(@NotNull(message = "{id.notNull}") @Size(min = 1, max = 50, message = "{id.size}") @QueryParam("id") String ssoId) {
      ((Saml2SpInitiatedSsoService)this.spInitiatedSsoService.get()).createAuthnRequest(Saml2SpInitiatedSsoId.parseSpInitiatedSsoId(ssoId));
      return Response.status(Saml2RequestThreadContext.getResponse().getStatus()).build();
   }
}
