package com.airlock.iam.oauth2.domain.service.consent;

import com.airlock.iam.flow.shared.api.domain.model.session.UserSession;
import com.airlock.iam.oauth2.api.domain.model.OpenIdConnectSessionManagementSettings;
import com.airlock.iam.oauth2.domain.model.oauth2.session.OpenIDProviderUserAgentStateUserSessionAttribute;
import com.airlock.iam.oauth2.domain.model.session.OpenIDProviderUserAgentState;
import com.airlock.iam.oauth2.domain.model.settings.OpenIdConnectAuthorizationCodeGrantSettings;
import com.airlock.iam.oauth2.domain.service.OpenIdProviderUserAgentStateService;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import java.util.Optional;

public final class OpenIdProviderUserAgentStateServiceImpl implements OpenIdProviderUserAgentStateService {
   private final Optional<OpenIdConnectAuthorizationCodeGrantSettings> grantSettings;
   private final Optional<OpenIdConnectSessionManagementSettings> sessionManagementSettings;
   private final UserSession userSession;

   @Inject
   public OpenIdProviderUserAgentStateServiceImpl(
      Optional<OpenIdConnectAuthorizationCodeGrantSettings> grantSettings,
      Optional<OpenIdConnectSessionManagementSettings> sessionManagementSettings,
      UserSession userSession
   ) {
      this.grantSettings = grantSettings;
      this.sessionManagementSettings = sessionManagementSettings;
      this.userSession = userSession;
   }

   @Override
   public Optional<OpenIDProviderUserAgentState> state() {
      if (this.grantSettings.isEmpty()) {
         return Optional.empty();
      } else {
         return this.sessionManagementSettings.isEmpty() ? Optional.empty() : Optional.of(this.getOrCreateOpenIDProviderUserAgentState());
      }
   }

   private OpenIDProviderUserAgentState getOrCreateOpenIDProviderUserAgentState() {
      return this.userSession
         .findUserSessionAttribute(OpenIDProviderUserAgentStateUserSessionAttribute.class)
         .map(OpenIDProviderUserAgentStateUserSessionAttribute::getState)
         .orElseGet(() -> {
            OpenIDProviderUserAgentState state = OpenIDProviderUserAgentState.generateOpenIDProviderUserAgentState();
            this.userSession.addUserSessionAttribute(new OpenIDProviderUserAgentStateUserSessionAttribute(state));
            return state;
         });
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class OpenIdProviderUserAgentStateServiceImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Optional<OpenIdConnectAuthorizationCodeGrantSettings> grantSettings;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<OpenIdConnectSessionManagementSettings> sessionManagementSettings;
      @SuppressFBWarnings(justification = "generated code")
      private UserSession userSession;

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

      @SuppressFBWarnings(justification = "generated code")
      public OpenIdProviderUserAgentStateServiceImpl.OpenIdProviderUserAgentStateServiceImplBuilder grantSettings(
         Optional<OpenIdConnectAuthorizationCodeGrantSettings> grantSettings
      ) {
         this.grantSettings = grantSettings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OpenIdProviderUserAgentStateServiceImpl.OpenIdProviderUserAgentStateServiceImplBuilder sessionManagementSettings(
         Optional<OpenIdConnectSessionManagementSettings> sessionManagementSettings
      ) {
         this.sessionManagementSettings = sessionManagementSettings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OpenIdProviderUserAgentStateServiceImpl.OpenIdProviderUserAgentStateServiceImplBuilder userSession(UserSession userSession) {
         this.userSession = userSession;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OpenIdProviderUserAgentStateServiceImpl build() {
         return new OpenIdProviderUserAgentStateServiceImpl(this.grantSettings, this.sessionManagementSettings, this.userSession);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "OpenIdProviderUserAgentStateServiceImpl.OpenIdProviderUserAgentStateServiceImplBuilder(grantSettings="
            + this.grantSettings
            + ", sessionManagementSettings="
            + this.sessionManagementSettings
            + ", userSession="
            + this.userSession
            + ")";
      }
   }
}
