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

import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.common.api.domain.model.store.user.UserStore;
import com.airlock.iam.common.api.domain.model.user.PersistentUser;
import com.airlock.iam.flow.shared.api.domain.model.session.UserSession;
import com.airlock.iam.oauth2.api.application.configuration.claims.OAuth2UsernameTransformer;
import com.airlock.iam.oauth2.api.domain.model.AuthorizationServerId;
import com.airlock.iam.oauth2.api.domain.model.OAuth2ClientId;
import com.airlock.iam.oauth2.domain.model.oauth2.session.OAuth2UserAgentSessions;
import com.airlock.iam.oauth2.domain.model.oidc.OidcUserAgentSessions;
import com.airlock.iam.oauth2.domain.model.session.OAuth2SessionId;
import jakarta.inject.Provider;
import java.util.Optional;

public class UserAgentSessionService {
   private final Provider<UserSession> userSession;
   private final Provider<OAuth2UsernameTransformer> usernameTransformer;
   private final Provider<UserStore> userStore;

   public UserAgentSessionService(Provider<UserSession> userSession, Provider<OAuth2UsernameTransformer> usernameTransformer, Provider<UserStore> userStore) {
      this.userSession = userSession;
      this.usernameTransformer = usernameTransformer;
      this.userStore = userStore;
   }

   public void addOAuth2UserAgentSession(AuthorizationServerId authorizationServerId, OAuth2SessionId sessionId) {
      OAuth2UserAgentSessions.OAuth2UserAgentSession userAgentSession = new OAuth2UserAgentSessions.OAuth2UserAgentSession(authorizationServerId, sessionId);
      OAuth2UserAgentSessions currentUserAgentSession = this.getOrCreateOAuth2UserAgentSessions();
      OAuth2UserAgentSessions updatedUserAgentSessions = currentUserAgentSession.withAddedSession(userAgentSession);
      ((UserSession)this.userSession.get()).addUserSessionAttribute(updatedUserAgentSessions);
   }

   public OidcUserAgentSessions addOidcUserAgentSession(
      AuthorizationServerId authorizationServerId, OAuth2ClientId oAuth2ClientId, OAuth2SessionId sessionId, UserId userId
   ) {
      OidcUserAgentSessions.OidcUserAgentSession userAgentSession = new OidcUserAgentSessions.OidcUserAgentSession(
         authorizationServerId, oAuth2ClientId, sessionId, this.subjectClaim(userId)
      );
      OidcUserAgentSessions currentUserAgentSessions = this.getOrCreateOidcUserAgentSessions();
      OidcUserAgentSessions updatedUserAgentSessions = currentUserAgentSessions.withAddedSession(userAgentSession);
      ((UserSession)this.userSession.get()).addUserSessionAttribute(updatedUserAgentSessions);
      return updatedUserAgentSessions;
   }

   private OAuth2UserAgentSessions getOrCreateOAuth2UserAgentSessions() {
      Optional<OAuth2UserAgentSessions> existingAttribute = ((UserSession)this.userSession.get()).findUserSessionAttribute(OAuth2UserAgentSessions.class);
      OAuth2UserAgentSessions attribute = existingAttribute.orElse(new OAuth2UserAgentSessions());
      if (existingAttribute.isEmpty()) {
         ((UserSession)this.userSession.get()).addUserSessionAttribute(attribute);
      }

      return attribute;
   }

   private String subjectClaim(UserId userId) {
      PersistentUser user = ((UserStore)this.userStore.get()).getByIdentity(userId);
      return ((OAuth2UsernameTransformer)this.usernameTransformer.get()).apply(user);
   }

   private OidcUserAgentSessions getOrCreateOidcUserAgentSessions() {
      Optional<OidcUserAgentSessions> existingAttribute = ((UserSession)this.userSession.get()).findUserSessionAttribute(OidcUserAgentSessions.class);
      OidcUserAgentSessions attribute = existingAttribute.orElse(new OidcUserAgentSessions());
      if (existingAttribute.isEmpty()) {
         ((UserSession)this.userSession.get()).addUserSessionAttribute(attribute);
      }

      return attribute;
   }
}
