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

import com.airlock.iam.authentication.application.configuration.migration.condition.NextAuthMethodBasedMigrationConditionConfig;
import com.airlock.iam.authentication.application.configuration.migration.condition.SkipMigrationConditionConfig;
import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.common.api.domain.model.user.PersistentUser;
import com.airlock.iam.common.domain.model.principal.UserPrincipal;
import com.airlock.iam.flow.api.application.configuration.selection.CommonSelectionOptionConfig;
import com.airlock.iam.flow.api.domain.model.step.FlowCondition;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.time.Duration;
import java.util.Date;
import java.util.Optional;

@LogicForConfig(SkipMigrationConditionConfig.class)
public class SkipMigrationCondition implements FlowCondition {
   private final Provider<UserPrincipal> principal;
   private final SkipMigrationConditionConfig config;

   @Inject
   public SkipMigrationCondition(SkipMigrationConditionConfig config, Provider<UserPrincipal> principal) {
      this.principal = principal;
      this.config = config;
   }

   @Override
   public boolean isFulfilled() {
      PersistentUser user = ((UserPrincipal)this.principal.get()).user();
      Optional<Duration> maxHintPeriod = this.getMaxHintPeriod(user);
      return maxHintPeriod.isEmpty() ? false : HintPeriodHelper.isUserWithinMigrationHintPeriod(user, maxHintPeriod.get()) && !this.isUserForcedToMigrate(user);
   }

   private Optional<Duration> getMaxHintPeriod(PersistentUser user) {
      return this.config
         .getOptions()
         .stream()
         .map(CommonSelectionOptionConfig::getCondition)
         .filter(NextAuthMethodBasedMigrationConditionConfig.class::isInstance)
         .map(NextAuthMethodBasedMigrationConditionConfig.class::cast)
         .filter(x -> user.getMultipleNextAuthMethods().contains(x.getTargetAuthMethod()))
         .map(NextAuthMethodBasedMigrationConditionConfig::getHintPeriodDuration)
         .max(Duration::compareTo);
   }

   private boolean isUserForcedToMigrate(PersistentUser user) {
      return user.getAuthMigrationDate() != null && new Date().after(user.getAuthMigrationDate());
   }

   @Override
   public String displayName() {
      return "Skip Migration Possible";
   }
}
