package com.airlock.iam.login.app.misc.oneshot;

import com.airlock.iam.common.api.domain.model.request.IpAddress;
import com.airlock.iam.common.domain.model.session.SessionId;
import com.airlock.iam.core.misc.authen.Authentee;
import com.airlock.iam.core.misc.util.ticket.KeyMultiValue;
import com.airlock.iam.login.app.misc.session.UserIdentityInformation;
import com.airlock.iam.plugin.api.config.ConfigurationContext;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nullable;
import java.time.Instant;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;

public final class OneShotContext {
   private final ConfigurationContext context;
   private final Optional<String> sslSessionId;
   private final IpAddress clientIp;
   private final Locale displayLanguage;
   private final SessionId sessionId;
   private final Map<String, Object> idPropagationParameterMap = new HashMap<>();
   private final Map<String, KeyMultiValue> idPropagationAdditionalValues = new HashMap<>();
   private Optional<String> authPlugin = Optional.empty();
   private Optional<Instant> authInstant = Optional.empty();
   private Optional<UserIdentityInformation> userIdentityInformation = Optional.empty();
   private Optional<Authentee> authentee = Optional.empty();

   public OneShotContext(
      @NonNull ConfigurationContext context,
      @NonNull Optional<String> sslSessionId,
      @NonNull IpAddress clientIp,
      @NonNull Locale displayLanguage,
      @NonNull SessionId sessionId
   ) {
      if (context == null) {
         throw new NullPointerException("context is marked non-null but is null");
      }

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

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

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

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

      this.context = context;
      this.sslSessionId = sslSessionId;
      this.clientIp = clientIp;
      this.displayLanguage = displayLanguage;
      this.sessionId = sessionId;
   }

   public void setUserIdentityInformation(@NonNull UserIdentityInformation info) {
      if (info == null) {
         throw new NullPointerException("info is marked non-null but is null");
      }

      this.userIdentityInformation = Optional.of(info);
   }

   public void setAuthentee(@NonNull Authentee newAuthentee) {
      if (newAuthentee == null) {
         throw new NullPointerException("newAuthentee is marked non-null but is null");
      }

      this.authentee = Optional.of(newAuthentee);
   }

   public void setAuthInstant(@NonNull Instant instant) {
      if (instant == null) {
         throw new NullPointerException("instant is marked non-null but is null");
      }

      this.authInstant = Optional.of(instant);
   }

   public void setAuthPlugin(@NonNull String pluginName) {
      if (pluginName == null) {
         throw new NullPointerException("pluginName is marked non-null but is null");
      }

      this.authPlugin = Optional.of(pluginName);
   }

   public void addIdentityPropagationParameter(String key, @Nullable Object value) {
      if (!StringUtils.isEmpty(key)) {
         if (value != null) {
            this.idPropagationParameterMap.put(key, value);
         } else {
            this.idPropagationParameterMap.remove(key);
         }
      }
   }

   public void clearUserIdentityInformation() {
      this.userIdentityInformation = Optional.empty();
   }

   @SuppressFBWarnings(justification = "generated code")
   public ConfigurationContext getContext() {
      return this.context;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Optional<String> getSslSessionId() {
      return this.sslSessionId;
   }

   @SuppressFBWarnings(justification = "generated code")
   public IpAddress getClientIp() {
      return this.clientIp;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Locale getDisplayLanguage() {
      return this.displayLanguage;
   }

   @SuppressFBWarnings(justification = "generated code")
   public SessionId getSessionId() {
      return this.sessionId;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Map<String, Object> getIdPropagationParameterMap() {
      return this.idPropagationParameterMap;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Map<String, KeyMultiValue> getIdPropagationAdditionalValues() {
      return this.idPropagationAdditionalValues;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Optional<String> getAuthPlugin() {
      return this.authPlugin;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Optional<Instant> getAuthInstant() {
      return this.authInstant;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Optional<UserIdentityInformation> getUserIdentityInformation() {
      return this.userIdentityInformation;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Optional<Authentee> getAuthentee() {
      return this.authentee;
   }
}
