package com.airlock.iam.saml2.domain.model;

import com.airlock.iam.flow.shared.api.domain.service.FlowAttributeService;
import com.airlock.iam.login.domain.model.targetapp.TargetApplicationAccessForwardURI;
import com.airlock.iam.saml2.domain.model.sp.Saml2SpSettings;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.net.URI;
import java.util.Optional;
import lombok.NonNull;

public final class Saml2IdpInitiatedRelayStateProviderImpl implements Saml2IdpInitiatedRelayStateProvider {
   @NonNull
   private final Provider<Saml2SpSettings> defaultSpSettings;
   @NonNull
   private final Provider<FlowAttributeService> attributes;

   @Inject
   Saml2IdpInitiatedRelayStateProviderImpl(@NonNull Provider<Saml2SpSettings> defaultSpSettings, @NonNull Provider<FlowAttributeService> attributes) {
      if (defaultSpSettings == null) {
         throw new NullPointerException("defaultSpSettings is marked non-null but is null");
      }

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

      this.defaultSpSettings = defaultSpSettings;
      this.attributes = attributes;
   }

   @Override
   public Optional<Saml2RelayState> provide() {
      return this.getTargetUri().map(Saml2RelayState::relayState);
   }

   private Optional<URI> getTargetUri() {
      return ((Saml2SpSettings)this.defaultSpSettings.get())
         .getIdpInitiatedRelayStateResolver()
         .map(resolver -> resolver.resolveTargetUri(this.forwardLocationFromSession()));
   }

   private Optional<URI> forwardLocationFromSession() {
      return ((FlowAttributeService)this.attributes.get())
         .findAttribute(TargetApplicationAccessForwardURI.class)
         .map(TargetApplicationAccessForwardURI::getUnverifiedForwardUri);
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class Saml2IdpInitiatedRelayStateProviderImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Provider<Saml2SpSettings> defaultSpSettings;
      @SuppressFBWarnings(justification = "generated code")
      private Provider<FlowAttributeService> attributes;

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

      @SuppressFBWarnings(justification = "generated code")
      public Saml2IdpInitiatedRelayStateProviderImpl.Saml2IdpInitiatedRelayStateProviderImplBuilder defaultSpSettings(
         @NonNull Provider<Saml2SpSettings> defaultSpSettings
      ) {
         if (defaultSpSettings == null) {
            throw new NullPointerException("defaultSpSettings is marked non-null but is null");
         }

         this.defaultSpSettings = defaultSpSettings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Saml2IdpInitiatedRelayStateProviderImpl.Saml2IdpInitiatedRelayStateProviderImplBuilder attributes(
         @NonNull Provider<FlowAttributeService> attributes
      ) {
         if (attributes == null) {
            throw new NullPointerException("attributes is marked non-null but is null");
         }

         this.attributes = attributes;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Saml2IdpInitiatedRelayStateProviderImpl build() {
         return new Saml2IdpInitiatedRelayStateProviderImpl(this.defaultSpSettings, this.attributes);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "Saml2IdpInitiatedRelayStateProviderImpl.Saml2IdpInitiatedRelayStateProviderImplBuilder(defaultSpSettings="
            + this.defaultSpSettings
            + ", attributes="
            + this.attributes
            + ")";
      }
   }
}
