package com.airlock.iam.common.infrastructure.exception;

import ch.ergon.restal.jsonapi.document.error.ErrorData;
import com.airlock.iam.base.api.infrastructure.uri.ExternalUriInfo;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.common.application.service.session.SessionTerminationService;
import com.airlock.iam.common.infrastructure.exceptions.DeserializationFailedException;
import com.airlock.iam.common.infrastructure.exceptions.DeserializationFailedType;
import com.airlock.iam.elog.api.EDefaultLogType;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;

@jakarta.ws.rs.ext.Provider
public class DeserializationFailedExceptionMapper extends BaseExceptionMapper<DeserializationFailedException> {
   private final Provider<SessionTerminationService> sessionTerminationService;

   @Inject
   protected DeserializationFailedExceptionMapper(Provider<ExternalUriInfo> uriInfo, Provider<SessionTerminationService> sessionTerminationService) {
      super(Status.INTERNAL_SERVER_ERROR, IamRestErrorCode.SESSION_TERMINATED, uriInfo);
      this.sessionTerminationService = sessionTerminationService;
   }

   protected void mapCode(DeserializationFailedException exception, ErrorData data) {
      String code = switch (exception.getType()) {
         case FLOW_FROM_OLD_VERSION -> IamRestErrorCode.FLOW_SESSION_EXPIRED.name();
         case SESSION_NOT_DESERIALIZABLE -> IamRestErrorCode.SESSION_TERMINATED.name();
      };
      data.setCode(code);
   }

   public Response toResponse(DeserializationFailedException exception) {
      if (exception.getType() == DeserializationFailedType.SESSION_NOT_DESERIALIZABLE) {
         ((SessionTerminationService)this.sessionTerminationService.get()).terminateSessions();
      }

      return super.toResponse(exception);
   }

   protected void logException(DeserializationFailedException exception, ErrorData data) {
      LOG.info(
         EDefaultLogType.GENERIC_LOG_TYPE,
         "Answered request to %s with %s due to deserialization failure: %s"
            .formatted(
               LogUtil.logSafeQuote(((ExternalUriInfo)this.getUriInfo().get()).getAbsolutePath()),
               Status.INTERNAL_SERVER_ERROR + " / " + data.getCode(),
               exception.getMessage()
            )
      );
   }
}
