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

import com.airlock.iam.common.api.domain.model.persistency.exception.PersisterException;
import com.airlock.iam.elog.api.ELogger;
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.token.OAuth2Token;
import com.airlock.iam.oauth2.domain.service.persistence.OAuth2TokenDeleter;
import com.airlock.iam.plugin.api.config.LogTypes;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.time.Instant;
import java.util.Optional;
import lombok.NonNull;

public class OAuth2TokenValidation {
   @NonNull
   private final AuthorizationServerId authorizationServerId;
   @NonNull
   private final OAuth2TokenDeleter tokenDeleter;
   @NonNull
   private final ELogger logger;

   public boolean isValidTokenCheckAssignment(OAuth2Token token, Optional<OAuth2ClientId> clientId) throws PersisterException {
      if (!token.isValid(clientId, this.authorizationServerId)) {
         if (token.getExpiry().map(exp -> exp.isBefore(Instant.now())).orElse(false)) {
            this.logger.debug("Removing expired OAuth 2.0 Token of type " + token.getOAuth2TokenSubtype());
            this.tokenDeleter.removeToken(token);
         }

         return false;
      } else {
         try {
            token.getUserId();
         } catch (Exception e) {
            this.logger.warn(LogTypes.PLUGIN_INFO, "Deleting this token because state is invalid: " + e.getMessage());
            this.tokenDeleter.removeToken(token);
         }

         return true;
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   public OAuth2TokenValidation(@NonNull AuthorizationServerId authorizationServerId, @NonNull OAuth2TokenDeleter tokenDeleter, @NonNull ELogger logger) {
      if (authorizationServerId == null) {
         throw new NullPointerException("authorizationServerId is marked non-null but is null");
      }

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

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

      this.authorizationServerId = authorizationServerId;
      this.tokenDeleter = tokenDeleter;
      this.logger = logger;
   }
}
