package com.airlock.iam.admin.application.service.user;

import com.airlock.iam.admin.api.domain.model.user.ManagedUser;
import com.airlock.iam.admin.api.domain.service.user.ManagedUserRepository;
import com.airlock.iam.admin.application.configuration.users.LockingSettings;
import com.airlock.iam.base.api.domain.model.exception.ServiceConfigurationException;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.base.misc.adapt.Adapter;
import com.airlock.iam.base.misc.time.TimeProvider;
import com.airlock.iam.common.api.domain.model.locking.LockReason;
import com.airlock.iam.common.api.domain.model.user.PersistentUser;
import com.airlock.iam.common.application.configuration.templock.TemporaryLockingConfig;
import com.airlock.iam.common.application.service.session.AirlockControlCookieService;
import com.airlock.iam.common.domain.model.templock.TemporaryLocking;
import com.airlock.iam.common.domain.model.templock.TemporaryLockingImpl;
import com.airlock.iam.common.domain.model.templock.TemporaryLocking.TemporaryLock;
import com.airlock.iam.common.domain.model.user.UserLockState;
import com.airlock.iam.common.domain.service.user.UserLockService;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import java.util.Optional;

public class AdminUserLockService {
   private final UserLockService userLockService;
   private final LockingSettings lockingSettings;
   private final ManagedUserRepository userRepository;
   private final AirlockControlCookieService controlCookieService;
   private final TimeProvider timeProvider;

   @Inject
   public AdminUserLockService(
      UserLockService userLockService,
      LockingSettings lockingSettings,
      ManagedUserRepository userRepository,
      AirlockControlCookieService controlCookieService,
      TimeProvider timeProvider
   ) {
      this.userLockService = userLockService;
      this.lockingSettings = lockingSettings;
      this.userRepository = userRepository;
      this.controlCookieService = controlCookieService;
      this.timeProvider = timeProvider;
   }

   public UserLockState lockUser(UserId userId, String reason) {
      UserLockState state = this.userLockService.lockUser(userId, reason);
      this.handleLockBehavior(userId);
      return state;
   }

   public UserLockState lockUser(UserId userId, LockReason reason) {
      UserLockState state = this.userLockService.lockUser(userId, reason);
      this.handleLockBehavior(userId);
      return state;
   }

   private void handleLockBehavior(UserId userId) {
      Optional<SessionLockBehavior> lockBehavior = this.lockingSettings.getSessionLockBehavior();
      if (lockBehavior.isPresent()) {
         lockBehavior.get().handleUserLocked(userId.getValue(), this.controlCookieService);
      }
   }

   public Optional<TemporaryLock> getTemporaryLockState(UserId userId) {
      TemporaryLockingConfig tempLockConfig = (TemporaryLockingConfig)ServiceConfigurationException.checkPresent(
         this.lockingSettings.getTemporaryLockingConfig(), "temporary locking not configured"
      );
      TemporaryLocking tempLocking = new TemporaryLockingImpl(tempLockConfig.getTemporaryLockingStrategyConfig().getLogic(), this.timeProvider);
      ManagedUser user = this.userRepository.getById(userId);
      return tempLocking.checkTemporaryLock((PersistentUser)Adapter.adapt(user).to(PersistentUser.class));
   }

   public UserLockState getUserLockState(UserId userId) {
      return this.userLockService.getUserLockState(userId);
   }

   public boolean isLockedForReason(UserId userId, LockReason reason) {
      return this.userLockService.isLockedForReason(userId, reason);
   }

   public UserLockState unlockUser(UserId userId) {
      return this.userLockService.unlockUser(userId);
   }

   @SuppressFBWarnings(justification = "generated code")
   public static AdminUserLockService.AdminUserLockServiceBuilder builder() {
      return new AdminUserLockService.AdminUserLockServiceBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class AdminUserLockServiceBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private UserLockService userLockService;
      @SuppressFBWarnings(justification = "generated code")
      private LockingSettings lockingSettings;
      @SuppressFBWarnings(justification = "generated code")
      private ManagedUserRepository userRepository;
      @SuppressFBWarnings(justification = "generated code")
      private AirlockControlCookieService controlCookieService;
      @SuppressFBWarnings(justification = "generated code")
      private TimeProvider timeProvider;

      @SuppressFBWarnings(justification = "generated code")
      AdminUserLockServiceBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminUserLockService.AdminUserLockServiceBuilder userLockService(UserLockService userLockService) {
         this.userLockService = userLockService;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminUserLockService.AdminUserLockServiceBuilder lockingSettings(LockingSettings lockingSettings) {
         this.lockingSettings = lockingSettings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminUserLockService.AdminUserLockServiceBuilder userRepository(ManagedUserRepository userRepository) {
         this.userRepository = userRepository;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminUserLockService.AdminUserLockServiceBuilder controlCookieService(AirlockControlCookieService controlCookieService) {
         this.controlCookieService = controlCookieService;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminUserLockService.AdminUserLockServiceBuilder timeProvider(TimeProvider timeProvider) {
         this.timeProvider = timeProvider;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminUserLockService build() {
         return new AdminUserLockService(this.userLockService, this.lockingSettings, this.userRepository, this.controlCookieService, this.timeProvider);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "AdminUserLockService.AdminUserLockServiceBuilder(userLockService="
            + this.userLockService
            + ", lockingSettings="
            + this.lockingSettings
            + ", userRepository="
            + this.userRepository
            + ", controlCookieService="
            + this.controlCookieService
            + ", timeProvider="
            + this.timeProvider
            + ")";
      }
   }
}
