package com.airlock.iam.authentication.api.domain.service.username;

import com.airlock.iam.authentication.api.domain.model.error.TemporaryLockError;
import com.airlock.iam.authentication.api.domain.model.error.UserValidityError;
import com.airlock.iam.authentication.api.domain.model.step.AuthenticationStepResultBuilder;
import com.airlock.iam.authentication.api.domain.model.step.AuthenticationStepResultFactory;
import com.airlock.iam.authentication.api.domain.model.step.IdentityProvidingFlowStep;
import com.airlock.iam.authentication.api.domain.model.step.UserIdentifyingStep;
import com.airlock.iam.flow.api.domain.model.step.GenericStepError;
import com.airlock.iam.flow.api.domain.model.step.StepAction;
import com.airlock.iam.flow.api.domain.model.step.StepError;
import com.airlock.iam.flow.api.domain.model.step.StepResultBuilder;
import com.airlock.iam.flow.api.domain.model.step.StepResultFactory;

public final class IdentificationResultConverter {
   public static AuthenticationStepResultBuilder convertToAuthStepResult(
      IdentificationResult.IdentificationFailure result, AuthenticationStepResultFactory factory, StepAction retryAction
   ) {
      return ((AuthenticationStepResultBuilder)convertToStepResult(result, factory, retryAction)).isFailedFactor(false);
   }

   public static StepResultBuilder convertToStepResult(IdentificationResult.IdentificationFailure result, StepResultFactory factory, StepAction retryAction) {
      StepResultBuilder builder = result.retryAllowed()
         ? factory.failRetry(convertToStepError(result.error()), retryAction)
         : factory.fail(convertToStepError(result.error()));
      result.additionalAttributes().forEach(builder::addAdditionalAttribute);
      return builder;
   }

   public static AuthenticationStepResultBuilder convertToAuthStepResult(IdentificationResult.IdentificationFailure result, StepResultFactory factory) {
      StepResultBuilder builder = factory.fail(convertToStepError(result.error()));
      result.additionalAttributes().forEach(builder::addAdditionalAttribute);
      return ((AuthenticationStepResultBuilder)builder).isFailedFactor(false);
   }

   private static StepError convertToStepError(IdentificationResult.IdentificationFailure.IdentificationError error) {
      return switch (error) {
         case DIFFERENT_USERNAME -> GenericStepError.UNEXPECTED_CALL;
         case USERNAME_INVALID, USER_NOT_FOUND -> UserIdentifyingStep.UserIdentifyingStepError.USER_NOT_FOUND;
         case USER_LOCKED -> UserValidityError.USER_LOCKED;
         case USER_INVALID -> UserValidityError.USER_INVALID;
         case USER_TEMP_LOCKED -> TemporaryLockError.USER_TEMPORARILY_LOCKED;
         case CONCURRENT_ACCESS -> IdentityProvidingFlowStep.IdentityProvidingStepErrors.CONCURRENT_ACCESS;
      };
   }

   private IdentificationResultConverter() {
   }
}
