package com.airlock.iam.admin.application.service.token.oauth;

import com.airlock.iam.admin.api.domain.model.administrator.CurrentAdministrator;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.common.domain.service.oauth.OAuth2UserTokenService;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.oauth2.domain.model.session.OperationStatistics;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.List;

public final class OAuthAdminTokenService implements OAuth2UserTokenService {
   private static final ELogger LOG = ELoggerFactory.getLogger(OAuthAdminTokenService.class);
   private final Provider<List<OAuth2AdminTokenServiceSettings>> settings;
   private final Provider<CurrentAdministrator> administrator;

   @Inject
   public OAuthAdminTokenService(Provider<List<OAuth2AdminTokenServiceSettings>> settings, Provider<CurrentAdministrator> administrator) {
      this.settings = settings;
      this.administrator = administrator;
   }

   public void handleLogout(UserId userId) {
   }

   public void handlePasswordChange(UserId userId) {
      ((List)this.settings.get())
         .stream()
         .filter(OAuth2AdminTokenServiceSettings::deleteTokensOnPasswordChange)
         .forEach(
            serverSettings -> deleteAndLogAction(
               userId,
               serverSettings,
               String.format("a password change by admin %s", LogUtil.logSafeQuote(((CurrentAdministrator)this.administrator.get()).getName()))
            )
         );
   }

   public void handleUserLocked(UserId userId) {
      ((List)this.settings.get())
         .stream()
         .filter(OAuth2AdminTokenServiceSettings::deleteTokensOnUserLocked)
         .forEach(
            serverSettings -> deleteAndLogAction(
               userId,
               serverSettings,
               String.format("the user being locked by admin %s", LogUtil.logSafeQuote(((CurrentAdministrator)this.administrator.get()).getName()))
            )
         );
   }

   private static void deleteAndLogAction(UserId userId, OAuth2AdminTokenServiceSettings serverSettings, String reason) {
      OperationStatistics statistics = serverSettings.sessionRepository().deleteAllSessionsByUser(userId);
      if (statistics.getTokenCount() > 0 || statistics.getSessionCount() > 0) {
         LOG.info(
            String.format(
               "Deleted %s and %s for user %s on authorization server %s as result of %s",
               LogUtil.pluralize(statistics.getTokenCount(), "OAuth 2.0 token"),
               LogUtil.pluralize(statistics.getSessionCount(), "session"),
               LogUtil.logSafeQuote(userId.getValue()),
               LogUtil.logSafeQuote(serverSettings.authorizationServerId().id()),
               reason
            )
         );
      }
   }
}
