package com.airlock.iam.authentication.domain.model.migration;

import com.airlock.iam.authentication.application.configuration.migration.CompleteMigrationStepConfig;
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.user.PersistentUser;
import com.airlock.iam.common.domain.model.event.AuthenticationMethodChangedEventFactory;
import com.airlock.iam.common.domain.model.principal.UserPrincipal;
import com.airlock.iam.core.misc.impl.authen.SimpleAuthenticationMethod;
import com.airlock.iam.flow.api.domain.model.step.FlowStep;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.log.api.signing.SigningLogger;
import com.airlock.iam.log.usertrail.UserTrailLogger;
import jakarta.inject.Inject;
import jakarta.inject.Provider;

@LogicForConfig(CompleteMigrationStepConfig.class)
public class CompleteMigrationStep implements FlowStep {
   private final Provider<UserPrincipal> principal;
   private final Provider<CompleteMigrationStepConfig> config;
   private final Provider<AuthenticationMethodChangedEventFactory> authenticationMethodChangedEventFactory;
   private final SigningLogger signingLogger;

   @Inject
   public CompleteMigrationStep(
      Provider<UserPrincipal> principal,
      Provider<CompleteMigrationStepConfig> config,
      Provider<AuthenticationMethodChangedEventFactory> authenticationMethodChangedEventFactory,
      SigningLogger signingLogger
   ) {
      this.principal = principal;
      this.config = config;
      this.authenticationMethodChangedEventFactory = authenticationMethodChangedEventFactory;
      this.signingLogger = signingLogger;
   }

   @Override
   public StepResult initialize() {
      PersistentUser user = ((UserPrincipal)this.principal.get()).user();
      String previousAuthMethod = user.getAuthMethod();
      user.setAuthMethod(((CompleteMigrationStepConfig)this.config.get()).getTargetAuthMethod());
      user.setNextAuthMethod(null);
      user.setAuthMigrationDate(null);
      ((AuthenticationMethodChangedEventFactory)this.authenticationMethodChangedEventFactory.get())
         .publishAuthenticationMethodChanged(UserId.userId(user.getName()), authMethodOf(user.getAuthMethod()), authMethodOf(previousAuthMethod));
      this.signingLogger.log("Migrated user '%s' to the authentication method '%s'", new Object[]{user.getName(), user.getAuthMethod()});
      UserTrailLogger.log(user.getName(), "Successfully migrated to the authentication method " + user.getAuthMethod() + ".");
      return this.stepResultFactory().success().build();
   }

   private static SimpleAuthenticationMethod authMethodOf(String authMethod) {
      return authMethod == null ? null : new SimpleAuthenticationMethod(authMethod, authMethod);
   }

   @Override
   public String getDescription() {
      return "Complete " + ((CompleteMigrationStepConfig)this.config.get()).getTargetAuthMethod() + " Migration Step";
   }
}
