package com.airlock.iam.common.domain.service.jwt;

import com.airlock.iam.base.misc.time.RealTimeProvider;
import com.airlock.iam.base.misc.time.TimeProvider;
import com.airlock.iam.common.domain.model.jwt.JwtKeys;
import com.airlock.iam.common.domain.service.jwt.encryption.JwtTicketDecrypter;
import com.airlock.iam.common.domain.service.jwt.encryption.JwtTicketDirectAesEncrypterDecrypter;
import com.airlock.iam.common.domain.service.jwt.signature.JwtSignatureVerifier;
import com.airlock.iam.common.domain.service.jwt.signature.JwtSignatureVerifierImpl;
import com.airlock.iam.core.misc.util.ticket.Ticket;
import com.airlock.iam.core.misc.util.ticket.TicketEncodingException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

public final class DecryptingJwtTicketDecoderImpl implements DecryptingJwtTicketDecoder {
   private final JwtTicketDecoderImpl decoder;

   public DecryptingJwtTicketDecoderImpl(
      String usernameTicketKey,
      Boolean notBeforeIsMandatory,
      Integer validNotBeforeSkew,
      Optional<String> notBeforeTicketKey,
      Boolean issuedAtIsMandatory,
      Optional<String> issuedAtTicketKey,
      Boolean issuerIsMandatory,
      List<String> allowedIssuers,
      Optional<String> issuerTicketKey,
      Boolean audienceIsMandatory,
      List<String> allowedAudiences,
      Optional<String> audienceTicketKey,
      Boolean jwtIdIsMandatory,
      Optional<String> jwtIdTicketKey,
      JwtSignatureVerifier signatureVerifier,
      JwtTicketDecrypter decrypter,
      TimeProvider timeProvider,
      boolean expirationTimeIsMandatory,
      boolean isSubjectMandatory
   ) {
      this.decoder = JwtTicketDecoderImpl.builder(usernameTicketKey, signatureVerifier, timeProvider)
         .notBeforeIsMandatory(notBeforeIsMandatory)
         .issuedAtIsMandatory(issuedAtIsMandatory)
         .issuerIsMandatory(issuerIsMandatory)
         .audienceIsMandatory(audienceIsMandatory)
         .jwtIdIsMandatory(jwtIdIsMandatory)
         .validNotBeforeSkew(validNotBeforeSkew)
         .notBeforeTicketKey(notBeforeTicketKey)
         .issuedAtTicketKey(issuedAtTicketKey)
         .allowedIssuers(allowedIssuers)
         .issuerTicketKey(issuerTicketKey)
         .allowedAudiences(allowedAudiences)
         .audienceTicketKey(audienceTicketKey)
         .jwtIdTicketKey(jwtIdTicketKey)
         .decrypter(Optional.of(decrypter))
         .expirationTimeIsMandatory(expirationTimeIsMandatory)
         .isSubjectMandatory(isSubjectMandatory)
         .build();
   }

   public static DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder builder(JwtKeys jwtKeys) {
      return new DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder()
         .usernameTicketKey("username")
         .signatureVerifier(JwtSignatureVerifierImpl.builder().hmacAlgorithm(DefaultSecureJwtConfig.DEFAULT_HMAC_ALGORITHM).hmacKey(jwtKeys.hmacKey()).build())
         .decrypter(JwtTicketDirectAesEncrypterDecrypter.createDefaultEncryptorDecryptor(jwtKeys.encryptionKey()))
         .timeProvider(new RealTimeProvider())
         .notBeforeIsMandatory(true)
         .issuedAtIsMandatory(true)
         .issuerIsMandatory(true)
         .audienceIsMandatory(false)
         .jwtIdIsMandatory(false)
         .expirationTimeIsMandatory(true)
         .isSubjectMandatory(true)
         .validNotBeforeSkew(5)
         .notBeforeTicketKey(Optional.empty())
         .issuedAtTicketKey(Optional.empty())
         .allowedIssuers(Collections.emptyList())
         .issuerTicketKey(Optional.empty())
         .allowedAudiences(Collections.emptyList())
         .audienceTicketKey(Optional.empty())
         .jwtIdTicketKey(Optional.empty());
   }

   @Override
   public Ticket decode(String ticketString, @Nullable String urlEncodingScheme) throws TicketEncodingException {
      return this.decoder.decode(ticketString, urlEncodingScheme);
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class DecryptingJwtTicketDecoderImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String usernameTicketKey;
      @SuppressFBWarnings(justification = "generated code")
      private Boolean notBeforeIsMandatory;
      @SuppressFBWarnings(justification = "generated code")
      private Integer validNotBeforeSkew;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<String> notBeforeTicketKey;
      @SuppressFBWarnings(justification = "generated code")
      private Boolean issuedAtIsMandatory;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<String> issuedAtTicketKey;
      @SuppressFBWarnings(justification = "generated code")
      private Boolean issuerIsMandatory;
      @SuppressFBWarnings(justification = "generated code")
      private List<String> allowedIssuers;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<String> issuerTicketKey;
      @SuppressFBWarnings(justification = "generated code")
      private Boolean audienceIsMandatory;
      @SuppressFBWarnings(justification = "generated code")
      private List<String> allowedAudiences;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<String> audienceTicketKey;
      @SuppressFBWarnings(justification = "generated code")
      private Boolean jwtIdIsMandatory;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<String> jwtIdTicketKey;
      @SuppressFBWarnings(justification = "generated code")
      private JwtSignatureVerifier signatureVerifier;
      @SuppressFBWarnings(justification = "generated code")
      private JwtTicketDecrypter decrypter;
      @SuppressFBWarnings(justification = "generated code")
      private TimeProvider timeProvider;
      @SuppressFBWarnings(justification = "generated code")
      private boolean expirationTimeIsMandatory;
      @SuppressFBWarnings(justification = "generated code")
      private boolean isSubjectMandatory;

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

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder usernameTicketKey(String usernameTicketKey) {
         this.usernameTicketKey = usernameTicketKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder notBeforeIsMandatory(Boolean notBeforeIsMandatory) {
         this.notBeforeIsMandatory = notBeforeIsMandatory;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder validNotBeforeSkew(Integer validNotBeforeSkew) {
         this.validNotBeforeSkew = validNotBeforeSkew;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder notBeforeTicketKey(Optional<String> notBeforeTicketKey) {
         this.notBeforeTicketKey = notBeforeTicketKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder issuedAtIsMandatory(Boolean issuedAtIsMandatory) {
         this.issuedAtIsMandatory = issuedAtIsMandatory;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder issuedAtTicketKey(Optional<String> issuedAtTicketKey) {
         this.issuedAtTicketKey = issuedAtTicketKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder issuerIsMandatory(Boolean issuerIsMandatory) {
         this.issuerIsMandatory = issuerIsMandatory;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder allowedIssuers(List<String> allowedIssuers) {
         this.allowedIssuers = allowedIssuers;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder issuerTicketKey(Optional<String> issuerTicketKey) {
         this.issuerTicketKey = issuerTicketKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder audienceIsMandatory(Boolean audienceIsMandatory) {
         this.audienceIsMandatory = audienceIsMandatory;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder allowedAudiences(List<String> allowedAudiences) {
         this.allowedAudiences = allowedAudiences;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder audienceTicketKey(Optional<String> audienceTicketKey) {
         this.audienceTicketKey = audienceTicketKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder jwtIdIsMandatory(Boolean jwtIdIsMandatory) {
         this.jwtIdIsMandatory = jwtIdIsMandatory;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder jwtIdTicketKey(Optional<String> jwtIdTicketKey) {
         this.jwtIdTicketKey = jwtIdTicketKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder signatureVerifier(JwtSignatureVerifier signatureVerifier) {
         this.signatureVerifier = signatureVerifier;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder decrypter(JwtTicketDecrypter decrypter) {
         this.decrypter = decrypter;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder timeProvider(TimeProvider timeProvider) {
         this.timeProvider = timeProvider;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder expirationTimeIsMandatory(boolean expirationTimeIsMandatory) {
         this.expirationTimeIsMandatory = expirationTimeIsMandatory;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder isSubjectMandatory(boolean isSubjectMandatory) {
         this.isSubjectMandatory = isSubjectMandatory;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DecryptingJwtTicketDecoderImpl build() {
         return new DecryptingJwtTicketDecoderImpl(
            this.usernameTicketKey,
            this.notBeforeIsMandatory,
            this.validNotBeforeSkew,
            this.notBeforeTicketKey,
            this.issuedAtIsMandatory,
            this.issuedAtTicketKey,
            this.issuerIsMandatory,
            this.allowedIssuers,
            this.issuerTicketKey,
            this.audienceIsMandatory,
            this.allowedAudiences,
            this.audienceTicketKey,
            this.jwtIdIsMandatory,
            this.jwtIdTicketKey,
            this.signatureVerifier,
            this.decrypter,
            this.timeProvider,
            this.expirationTimeIsMandatory,
            this.isSubjectMandatory
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "DecryptingJwtTicketDecoderImpl.DecryptingJwtTicketDecoderImplBuilder(usernameTicketKey="
            + this.usernameTicketKey
            + ", notBeforeIsMandatory="
            + this.notBeforeIsMandatory
            + ", validNotBeforeSkew="
            + this.validNotBeforeSkew
            + ", notBeforeTicketKey="
            + this.notBeforeTicketKey
            + ", issuedAtIsMandatory="
            + this.issuedAtIsMandatory
            + ", issuedAtTicketKey="
            + this.issuedAtTicketKey
            + ", issuerIsMandatory="
            + this.issuerIsMandatory
            + ", allowedIssuers="
            + this.allowedIssuers
            + ", issuerTicketKey="
            + this.issuerTicketKey
            + ", audienceIsMandatory="
            + this.audienceIsMandatory
            + ", allowedAudiences="
            + this.allowedAudiences
            + ", audienceTicketKey="
            + this.audienceTicketKey
            + ", jwtIdIsMandatory="
            + this.jwtIdIsMandatory
            + ", jwtIdTicketKey="
            + this.jwtIdTicketKey
            + ", signatureVerifier="
            + this.signatureVerifier
            + ", decrypter="
            + this.decrypter
            + ", timeProvider="
            + this.timeProvider
            + ", expirationTimeIsMandatory="
            + this.expirationTimeIsMandatory
            + ", isSubjectMandatory="
            + this.isSubjectMandatory
            + ")";
      }
   }
}
