package com.airlock.iam.authentication.application.service.flow.session;

import com.airlock.iam.common.application.service.DefaultSessionTerminationService;
import com.airlock.iam.common.application.service.session.SessionTerminationService;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.core.application.configuration.waf.AirlockGatewayConfig;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.login.domain.model.existingsessionbehavior.ExistingUserSessionBehaviorLogic;
import com.airlock.iam.saml2.domain.model.session.FlowFederationSession;
import com.airlock.iam.saml2.domain.model.session.FlowFederationSessionRepository;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

public class AuthenticationSessionTerminationService implements SessionTerminationService {
   private static final ELogger LOG = ELoggerFactory.getLogger(AuthenticationSessionTerminationService.class);
   private final Provider<PrincipalInfo> principalInfo;
   private final Provider<Optional<AirlockGatewayConfig>> airlockConfig;
   private final Provider<ExistingUserSessionBehaviorLogic> existingUserSessionBehavior;
   private final Provider<DefaultSessionTerminationService> defaultSessionTerminationService;
   private final Provider<FlowFederationSessionRepository> federationSessionRepository;

   @Inject
   public AuthenticationSessionTerminationService(
      Provider<PrincipalInfo> principalInfo,
      Provider<Optional<AirlockGatewayConfig>> airlockConfig,
      Provider<ExistingUserSessionBehaviorLogic> existingUserSessionBehavior,
      Provider<DefaultSessionTerminationService> defaultSessionTerminationService,
      Provider<FlowFederationSessionRepository> federationSessionRepository
   ) {
      this.principalInfo = principalInfo;
      this.airlockConfig = airlockConfig;
      this.existingUserSessionBehavior = existingUserSessionBehavior;
      this.defaultSessionTerminationService = defaultSessionTerminationService;
      this.federationSessionRepository = federationSessionRepository;
   }

   @Override
   public void terminateSessions() {
      this.handleExistingUserSessionBehavior();
      Optional<FlowFederationSession> federationSession = ((FlowFederationSessionRepository)this.federationSessionRepository.get()).getFederationSession();
      if (federationSession.isPresent()) {
         if (federationSession.get().isClearGatewaySessionOnSlo()) {
            ((DefaultSessionTerminationService)this.defaultSessionTerminationService.get()).terminateSessionsUsingClear();
         } else {
            ((DefaultSessionTerminationService)this.defaultSessionTerminationService.get()).terminateOnlyIamSession();
         }
      } else {
         ((DefaultSessionTerminationService)this.defaultSessionTerminationService.get()).terminateSessions();
      }
   }

   @Override
   public void terminateSessionsUsingClear() {
      this.handleExistingUserSessionBehavior();
      ((DefaultSessionTerminationService)this.defaultSessionTerminationService.get()).terminateSessionsUsingClear();
   }

   private void handleExistingUserSessionBehavior() {
      if (((PrincipalInfo)this.principalInfo.get()).getKnownIdentity().isPresent() && ((Optional)this.airlockConfig.get()).isPresent()) {
         ((PrincipalInfo)this.principalInfo.get())
            .getKnownIdentity()
            .ifPresent(userIdentity -> ((ExistingUserSessionBehaviorLogic)this.existingUserSessionBehavior.get()).handleLogout(userIdentity.id()));
      } else {
         LOG.debug("Logging out unauthenticated user. Hence no deletion of the GSID is needed");
      }
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class AuthenticationSessionTerminationServiceBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Provider<PrincipalInfo> principalInfo;
      @SuppressFBWarnings(justification = "generated code")
      private Provider<Optional<AirlockGatewayConfig>> airlockConfig;
      @SuppressFBWarnings(justification = "generated code")
      private Provider<ExistingUserSessionBehaviorLogic> existingUserSessionBehavior;
      @SuppressFBWarnings(justification = "generated code")
      private Provider<DefaultSessionTerminationService> defaultSessionTerminationService;
      @SuppressFBWarnings(justification = "generated code")
      private Provider<FlowFederationSessionRepository> federationSessionRepository;

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

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationSessionTerminationService.AuthenticationSessionTerminationServiceBuilder principalInfo(Provider<PrincipalInfo> principalInfo) {
         this.principalInfo = principalInfo;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationSessionTerminationService.AuthenticationSessionTerminationServiceBuilder airlockConfig(
         Provider<Optional<AirlockGatewayConfig>> airlockConfig
      ) {
         this.airlockConfig = airlockConfig;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationSessionTerminationService.AuthenticationSessionTerminationServiceBuilder existingUserSessionBehavior(
         Provider<ExistingUserSessionBehaviorLogic> existingUserSessionBehavior
      ) {
         this.existingUserSessionBehavior = existingUserSessionBehavior;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationSessionTerminationService.AuthenticationSessionTerminationServiceBuilder defaultSessionTerminationService(
         Provider<DefaultSessionTerminationService> defaultSessionTerminationService
      ) {
         this.defaultSessionTerminationService = defaultSessionTerminationService;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationSessionTerminationService.AuthenticationSessionTerminationServiceBuilder federationSessionRepository(
         Provider<FlowFederationSessionRepository> federationSessionRepository
      ) {
         this.federationSessionRepository = federationSessionRepository;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationSessionTerminationService build() {
         return new AuthenticationSessionTerminationService(
            this.principalInfo, this.airlockConfig, this.existingUserSessionBehavior, this.defaultSessionTerminationService, this.federationSessionRepository
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "AuthenticationSessionTerminationService.AuthenticationSessionTerminationServiceBuilder(principalInfo="
            + this.principalInfo
            + ", airlockConfig="
            + this.airlockConfig
            + ", existingUserSessionBehavior="
            + this.existingUserSessionBehavior
            + ", defaultSessionTerminationService="
            + this.defaultSessionTerminationService
            + ", federationSessionRepository="
            + this.federationSessionRepository
            + ")";
      }
   }
}
