package com.airlock.iam.servicecontainer.app.domain.service.airlock2fa;

import com.airlock.iam.airlock2fa.api.domain.model.Airlock2FAAccountId;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.base.misc.result.Result;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FALogData;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FAUser;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FAUserAttributes;
import com.airlock.iam.factor.domain.model.airlock2fa.activation.Airlock2FAActivationLetter;
import com.airlock.iam.factor.domain.model.airlock2fa.order.Airlock2FAActivationLetterOrder;
import com.airlock.iam.factor.domain.service.airlock2fa.Airlock2FAActivationLetterPrintingService;
import com.airlock.iam.factor.domain.service.airlock2fa.Airlock2FAActivationLetterService;
import com.airlock.iam.factor.domain.service.airlock2fa.Airlock2FAAdminApiUserService;
import com.airlock.iam.factor.domain.service.airlock2fa.repository.Airlock2FAUserRepository;
import com.airlock.iam.log.api.signing.SigningLogger;
import java.nio.file.Path;
import java.util.Optional;

public class Airlock2FAActivationLetterOrderTaskService {
   private static final ELogger LOG = ELoggerFactory.getLogger(Airlock2FAActivationLetterOrderTaskService.class);
   private final Airlock2FAUserRepository userRepository;
   private final Airlock2FAAdminApiUserService userService;
   private final Airlock2FAActivationLetterService activationLetterService;
   private final Airlock2FAActivationLetterPrintingService activationLetterPrintingService;
   private final SigningLogger signingLogger;

   public Airlock2FAActivationLetterOrderTaskService(
      Airlock2FAUserRepository userRepository,
      Airlock2FAAdminApiUserService userService,
      Airlock2FAActivationLetterService activationLetterService,
      Airlock2FAActivationLetterPrintingService activationLetterPrintingService,
      SigningLogger signingLogger
   ) {
      this.userRepository = userRepository;
      this.userService = userService;
      this.activationLetterService = activationLetterService;
      this.activationLetterPrintingService = activationLetterPrintingService;
      this.signingLogger = signingLogger;
   }

   public Result<Airlock2FAActivationLetter, Airlock2FAActivationLetterOrderTaskService.CreateLetterFailure> createActivationLetter(
      Airlock2FAActivationLetterOrder order
   ) {
      Airlock2FAAccountId accountId = order.getAccountId();
      Optional<Airlock2FAUser> airlock2FAUser = this.userRepository.findBy(accountId);
      if (airlock2FAUser.isEmpty()) {
         LOG.info(String.format("No Airlock 2FA account found with ID %s", LogUtil.quote(accountId)));
         return Result.failure(Airlock2FAActivationLetterOrderTaskService.CreateLetterFailure.ACCOUNT_NOT_FOUND);
      } else {
         Airlock2FAUserAttributes userAttributes = this.userService.getUserAttributes(accountId);
         if (userAttributes.isPermanentlyDisabled()) {
            LOG.info("Cannot create activation letter for permanently disabled account: " + airlock2FAUser.get().getIamUserId().getValue());
            return Result.failure(Airlock2FAActivationLetterOrderTaskService.CreateLetterFailure.ACCOUNT_PERMANENTLY_DISABLED);
         } else {
            Airlock2FAActivationLetter activationLetter = this.activationLetterService
               .create(airlock2FAUser.get(), UserId.userId(order.getCreator().getName()));
            Path printableFile = this.activationLetterPrintingService.printToFile(airlock2FAUser.get().getIamUserId(), activationLetter);
            this.signingLogger
               .log(
                  String.format(
                     "Created a new Airlock 2FA activation letter %s for user %s %s",
                     LogUtil.quote(printableFile),
                     LogUtil.quote(airlock2FAUser.get().getIamUserId()),
                     Airlock2FALogData.airlock2FALogData(airlock2FAUser.get().getAccountId())
                  )
               );
            return Result.result(activationLetter);
         }
      }
   }

   public enum CreateLetterFailure {
      ACCOUNT_NOT_FOUND,
      ACCOUNT_PERMANENTLY_DISABLED,
      EXCEPTION;
   }
}
