package com.airlock.iam.flow.shared.domain.model.devicetoken;

import com.airlock.iam.base.misc.util.Base64Util;
import com.airlock.iam.common.api.domain.model.device.DeviceTokenId;
import com.airlock.iam.common.domain.model.jwk.ECJsonWebKey;
import com.airlock.iam.core.misc.persistency.token.TokenBean;
import com.airlock.iam.core.misc.util.DateRange;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;

public final class DeviceToken {
   private final TokenBean delegate;

   public DeviceToken(TokenBean tokenBean) {
      this.delegate = tokenBean;
   }

   public DeviceToken(TokenBean newTokenBean, Duration validity, ECJsonWebKey ecJwk) {
      this.delegate = newTokenBean;
      this.setMandatoryDeviceTokenAttributes(validity, ecJwk);
   }

   private void setMandatoryDeviceTokenAttributes(Duration validity, ECJsonWebKey ecJwk) {
      this.delegate.setTokenData(Base64Util.encodeToString(ecJwk.toJsonString()));
      Instant now = Instant.now();
      this.delegate.setValidityRange(DateRange.ofInstants(now, now.plus(validity)));
      this.extractAttributesFromPublicKey(ecJwk);
   }

   private void extractAttributesFromPublicKey(ECJsonWebKey publicKey) {
      this.delegate.setGenericDataElement2(publicKey.keyType().value());
   }

   public TokenBean asTokenBean() {
      return this.delegate;
   }

   public ECJsonWebKey getJwk() {
      return this.delegate.getTokenData() == null ? null : this.getJwkFromJsonBase64(this.delegate.getTokenData());
   }

   public boolean hasExpired() {
      return !this.delegate.getValidityRange().isInInclusiveRange(Instant.now());
   }

   public Date getValidTo() {
      return this.delegate.getValidityRange().getToDate();
   }

   public Date getValidFrom() {
      return this.delegate.getValidityRange().getFromDate();
   }

   public Date getActivationDate() {
      return this.delegate.getActivationDate();
   }

   public Date getGenerationDate() {
      return this.delegate.getGenerationDate();
   }

   public int getTotalUsages() {
      return this.delegate.getTotalUsages();
   }

   public boolean isEnabled() {
      return this.delegate.isActive();
   }

   public void setLabel(String label) {
      this.delegate.setGenericDataElement1(label);
   }

   public String getLabel() {
      return this.delegate.getGenericDataElement1();
   }

   public void setSerial(String serial) {
      this.delegate.setSerialId(serial);
   }

   public String getSerial() {
      return this.delegate.getSerialId();
   }

   public String getId() {
      return this.delegate.getTokenId();
   }

   public DeviceTokenId getTokenId() {
      return new DeviceTokenId(this.getId());
   }

   public Date getLatestUsageDate() {
      return this.delegate.getLatestUsageDate();
   }

   public DeviceToken updateSuccess() {
      Date now = new Date();
      if (this.delegate.getFirstUsageDate() == null) {
         this.delegate.setFirstUsageDate(now);
      }

      this.delegate.setLatestUsageDate(now);
      this.delegate.setTotalUsages(this.delegate.getTotalUsages() + 1);
      return this;
   }

   private ECJsonWebKey getJwkFromJsonBase64(String tokenData) {
      String base64Decoded = new String(Base64Util.decode(tokenData), StandardCharsets.UTF_8);
      return ECJsonWebKey.fromJSON(base64Decoded);
   }
}
