package com.airlock.iam.flow.shared.domain.model.cronto;

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.common.api.domain.model.persistency.exception.PersisterException;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.core.misc.cronto.CrontoHandler;
import com.airlock.iam.core.misc.impl.token.cronto.CrontoAccountToken;
import com.airlock.iam.flow.api.domain.model.step.FlowStep;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.flow.shared.application.configuration.cronto.CrontoDeviceResetStepConfig;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

@LogicForConfig(CrontoDeviceResetStepConfig.class)
public final class CrontoDeviceResetStep implements FlowStep {
   private final Provider<PrincipalInfo> user;
   private final Provider<CrontoHandler> crontoHandler;
   private final Provider<CrontoDeviceResetStep.CrontoDeviceResetSettings> settings;

   @Inject
   public CrontoDeviceResetStep(
      Provider<PrincipalInfo> user, Provider<CrontoHandler> crontoHandler, Provider<CrontoDeviceResetStep.CrontoDeviceResetSettings> settings
   ) {
      this.user = user;
      this.crontoHandler = crontoHandler;
      this.settings = settings;
   }

   @Override
   public StepResult initialize() {
      UserId userId = ((PrincipalInfo)this.user.get()).getKnownIdentity().orElseThrow().id();

      try {
         Optional<? extends CrontoAccountToken> account = ((CrontoHandler)this.crontoHandler.get()).getAccountForUser(userId);
         if (account.isPresent()) {
            if (((CrontoDeviceResetStep.CrontoDeviceResetSettings)this.settings.get()).isRemoveAccount()) {
               ((CrontoHandler)this.crontoHandler.get()).deleteAccount(account.get());
            } else {
               ((CrontoHandler)this.crontoHandler.get()).deleteAllDevices(userId);
            }
         }

         return this.stepResultFactory().success().build();
      } catch (PersisterException e) {
         throw new FailureException("Exception while resetting Cronto devices for " + userId, e);
      }
   }

   @Override
   public String getDescription() {
      return "Cronto Device Reset Step";
   }

   public static final class CrontoDeviceResetSettings {
      private final boolean removeAccount;

      @SuppressFBWarnings(justification = "generated code")
      public CrontoDeviceResetSettings(boolean removeAccount) {
         this.removeAccount = removeAccount;
      }

      @SuppressFBWarnings(justification = "generated code")
      public boolean isRemoveAccount() {
         return this.removeAccount;
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public boolean equals(Object o) {
         if (o == this) {
            return true;
         } else {
            return !(o instanceof CrontoDeviceResetStep.CrontoDeviceResetSettings other) ? false : this.removeAccount == other.removeAccount;
         }
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public int hashCode() {
         int PRIME = 59;
         int result = 1;
         return result * 59 + (this.removeAccount ? 79 : 97);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "CrontoDeviceResetStep.CrontoDeviceResetSettings(removeAccount=" + this.isRemoveAccount() + ")";
      }
   }
}
