package com.airlock.iam.saml2.infrastructure.service;

import com.airlock.iam.common.application.service.session.AirlockControlCookieService;
import com.airlock.iam.common.domain.model.auth.idpropagation.WafCredential;
import com.airlock.iam.login.domain.model.targetapp.WafCredentialProvider;
import com.airlock.iam.saml2.domain.model.session.FlowFederationSessionRepository;
import com.airlock.iam.saml2.domain.service.Saml2SloCredentialService;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import lombok.NonNull;

public final class Saml2SloCredentialServiceImpl implements Saml2SloCredentialService {
   private final Provider<FlowFederationSessionRepository> repository;
   private final Provider<AirlockControlCookieService> controlCookieService;
   private final Optional<WafCredentialProvider> temporaryLogoutCredential;

   @Inject
   Saml2SloCredentialServiceImpl(
      @NonNull Provider<FlowFederationSessionRepository> repository,
      @NonNull Provider<AirlockControlCookieService> controlCookieService,
      @NonNull Optional<WafCredentialProvider> temporaryLogoutCredential
   ) {
      if (repository == null) {
         throw new NullPointerException("repository is marked non-null but is null");
      }

      if (controlCookieService == null) {
         throw new NullPointerException("controlCookieService is marked non-null but is null");
      }

      if (temporaryLogoutCredential == null) {
         throw new NullPointerException("temporaryLogoutCredential is marked non-null but is null");
      }

      this.repository = repository;
      this.controlCookieService = controlCookieService;
      this.temporaryLogoutCredential = temporaryLogoutCredential;
   }

   @Override
   public void addTemporaryLogoutCredential() {
      if (this.isFederationSessionPresent()) {
         this.getWafCredentials()
            .forEach(c -> ((AirlockControlCookieService)this.controlCookieService.get()).addCredentialsWithKeepSessionId(Collections.singleton(c)));
      }
   }

   @Override
   public void setTemporaryLogoutCredential() {
      if (this.isFederationSessionPresent()) {
         ((AirlockControlCookieService)this.controlCookieService.get()).setCredentials(this.getConfiguredCredentialsOrEmptyCredential());
      }
   }

   private List<WafCredential> getConfiguredCredentialsOrEmptyCredential() {
      List<WafCredential> wafCredentials = this.getWafCredentials();
      return wafCredentials.isEmpty() ? List.of(WafCredential.builder("").build()) : wafCredentials;
   }

   private List<WafCredential> getWafCredentials() {
      return this.temporaryLogoutCredential.isEmpty() ? Collections.emptyList() : this.temporaryLogoutCredential.get().getCredentials();
   }

   private boolean isFederationSessionPresent() {
      return ((FlowFederationSessionRepository)this.repository.get()).getFederationSession().isPresent();
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class Saml2SloCredentialServiceImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Provider<FlowFederationSessionRepository> repository;
      @SuppressFBWarnings(justification = "generated code")
      private Provider<AirlockControlCookieService> controlCookieService;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<WafCredentialProvider> temporaryLogoutCredential;

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

      @SuppressFBWarnings(justification = "generated code")
      public Saml2SloCredentialServiceImpl.Saml2SloCredentialServiceImplBuilder repository(@NonNull Provider<FlowFederationSessionRepository> repository) {
         if (repository == null) {
            throw new NullPointerException("repository is marked non-null but is null");
         }

         this.repository = repository;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Saml2SloCredentialServiceImpl.Saml2SloCredentialServiceImplBuilder controlCookieService(
         @NonNull Provider<AirlockControlCookieService> controlCookieService
      ) {
         if (controlCookieService == null) {
            throw new NullPointerException("controlCookieService is marked non-null but is null");
         }

         this.controlCookieService = controlCookieService;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Saml2SloCredentialServiceImpl.Saml2SloCredentialServiceImplBuilder temporaryLogoutCredential(
         @NonNull Optional<WafCredentialProvider> temporaryLogoutCredential
      ) {
         if (temporaryLogoutCredential == null) {
            throw new NullPointerException("temporaryLogoutCredential is marked non-null but is null");
         }

         this.temporaryLogoutCredential = temporaryLogoutCredential;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Saml2SloCredentialServiceImpl build() {
         return new Saml2SloCredentialServiceImpl(this.repository, this.controlCookieService, this.temporaryLogoutCredential);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "Saml2SloCredentialServiceImpl.Saml2SloCredentialServiceImplBuilder(repository="
            + this.repository
            + ", controlCookieService="
            + this.controlCookieService
            + ", temporaryLogoutCredential="
            + this.temporaryLogoutCredential
            + ")";
      }
   }
}
