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

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.domain.model.user.PrincipalInfo;
import com.airlock.iam.core.misc.cronto.CrontoHandler;
import com.airlock.iam.core.misc.impl.authen.CrontoUsedDeviceInfo;
import com.airlock.iam.core.misc.impl.cronto.CrontoChallengeResult;
import com.airlock.iam.core.misc.impl.cronto.pushnotification.PushAppHandlerWithActivation;
import com.airlock.iam.core.misc.impl.token.cronto.CrontoDeviceToken;
import com.airlock.iam.flow.api.domain.model.step.FlowCondition;
import com.airlock.iam.flow.shared.application.configuration.cronto.CrontoPushActivationConditionConfig;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

@LogicForConfig(CrontoPushActivationConditionConfig.class)
public class CrontoPushActivationCondition implements FlowCondition {
   private final Provider<Optional<CrontoUsedDeviceInfo>> usedDevice;
   private final Provider<PrincipalInfo> user;
   private final Provider<CrontoHandler> crontoHandler;
   private final Provider<PushAppHandlerWithActivation> pushAppHandler;

   @Inject
   public CrontoPushActivationCondition(
      Provider<Optional<CrontoUsedDeviceInfo>> usedDevice,
      Provider<PrincipalInfo> user,
      Provider<CrontoHandler> crontoHandler,
      Provider<PushAppHandlerWithActivation> pushAppHandler
   ) {
      this.usedDevice = usedDevice;
      this.user = user;
      this.crontoHandler = crontoHandler;
      this.pushAppHandler = pushAppHandler;
   }

   @Override
   public boolean isFulfilled() {
      return ((Optional)this.usedDevice.get()).isPresent() && this.isPushActivationPossible((CrontoUsedDeviceInfo)((Optional)this.usedDevice.get()).get());
   }

   private boolean isPushActivationPossible(CrontoUsedDeviceInfo deviceInfo) {
      if (deviceInfo.getMethod() == CrontoChallengeResult.CrontoMethod.PUSH) {
         return false;
      } else {
         CrontoDeviceToken device = this.loadDevice(deviceInfo);
         if (!device.isPushNotificationAllowed()) {
            return false;
         } else if (!((PushAppHandlerWithActivation)this.pushAppHandler.get()).canPushBeManuallyActivated(device)) {
            return false;
         } else {
            return device.getTotalUsages() == 0
               ? true
               : device.getUsagesSincePushActivationSkipped() >= ((PushAppHandlerWithActivation)this.pushAppHandler.get()).getPushNotificationsReminderPeriod();
         }
      }
   }

   private CrontoDeviceToken loadDevice(CrontoUsedDeviceInfo deviceInfo) {
      return ((CrontoHandler)this.crontoHandler.get()).getTokenByDeviceId(this.userId(), deviceInfo.getDeviceId());
   }

   @Override
   public String displayName() {
      return "Can Activate Cronto Push";
   }

   private UserId userId() {
      return ((PrincipalInfo)this.user.get()).getKnownIdentity().orElseThrow().id();
   }
}
