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

import com.airlock.iam.base.api.domain.model.mapification.MapifiedValues;
import com.airlock.iam.base.domain.model.mapification.MapifiedValuesBuilder;
import com.airlock.iam.core.misc.impl.cronto.CrontoChallengeResult;
import com.airlock.iam.flow.api.domain.model.step.StepResultData;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.List;
import java.util.Optional;
import lombok.NonNull;

public final class CrontoAuthChallenge implements StepResultData {
   private static final String CRYPTOGRAM_KEY = "cryptogram";
   private static final String CHALLENGE_KEY = "challenge";
   private static final String ONLINE_KEY = "online";
   private static final String PUSH_KEY = "push";
   private static final String LOGIN_ID_KEY = "loginId";
   private static final String DEVICES_KEY = "devices";
   private final String base64Cryptogram;
   private final Optional<String> secureChannelChallenge;
   private final boolean onlineValidation;
   private final boolean pushed;
   private final Optional<String> pushLoginId;
   @NonNull
   private final List<CrontoPushDevice> pushDevices;

   public CrontoAuthChallenge withUpdatedMethod(CrontoChallengeResult.CrontoMethod method) {
      return builder()
         .base64Cryptogram(this.base64Cryptogram)
         .secureChannelChallenge(this.secureChannelChallenge)
         .onlineValidation(method.isOnlineValidation())
         .pushed(method.isPush())
         .pushLoginId(this.pushLoginId)
         .pushDevices(this.pushDevices)
         .build();
   }

   @Override
   public MapifiedValues mapify() {
      return MapifiedValuesBuilder.mapifiedValues()
         .put("cryptogram", this.base64Cryptogram)
         .putIfPresent("challenge", this.secureChannelChallenge)
         .put("online", this.onlineValidation)
         .put("push", this.pushed)
         .putIfPresent("loginId", this.pushLoginId)
         .putIfNotEmpty("devices", this.pushDevices.stream().map(CrontoPushDevice::mapify).toList())
         .build();
   }

   public static CrontoAuthChallenge demapify(MapifiedValues values) {
      return builder()
         .base64Cryptogram(values.get("cryptogram"))
         .secureChannelChallenge(values.getOptional("challenge"))
         .onlineValidation(values.<Boolean>get("online"))
         .pushed(values.<Boolean>get("push"))
         .pushLoginId(values.getOptional("loginId"))
         .pushDevices(values.demapifyList("devices", CrontoPushDevice::demapify))
         .build();
   }

   @SuppressFBWarnings(justification = "generated code")
   CrontoAuthChallenge(
      String base64Cryptogram,
      Optional<String> secureChannelChallenge,
      boolean onlineValidation,
      boolean pushed,
      Optional<String> pushLoginId,
      @NonNull List<CrontoPushDevice> pushDevices
   ) {
      if (pushDevices == null) {
         throw new NullPointerException("pushDevices is marked non-null but is null");
      }

      this.base64Cryptogram = base64Cryptogram;
      this.secureChannelChallenge = secureChannelChallenge;
      this.onlineValidation = onlineValidation;
      this.pushed = pushed;
      this.pushLoginId = pushLoginId;
      this.pushDevices = pushDevices;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static CrontoAuthChallenge.CrontoAuthChallengeBuilder builder() {
      return new CrontoAuthChallenge.CrontoAuthChallengeBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public String getBase64Cryptogram() {
      return this.base64Cryptogram;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public boolean isOnlineValidation() {
      return this.onlineValidation;
   }

   @SuppressFBWarnings(justification = "generated code")
   public boolean isPushed() {
      return this.pushed;
   }

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

   @NonNull
   @SuppressFBWarnings(justification = "generated code")
   public List<CrontoPushDevice> getPushDevices() {
      return this.pushDevices;
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public boolean equals(Object o) {
      if (o == this) {
         return true;
      } else if (!(o instanceof CrontoAuthChallenge other)) {
         return false;
      } else {
         if (this.onlineValidation != other.onlineValidation) {
            return false;
         }

         if (this.pushed != other.pushed) {
            return false;
         }

         Object this$base64Cryptogram = this.base64Cryptogram;
         Object other$base64Cryptogram = other.base64Cryptogram;
         if (this$base64Cryptogram == null ? other$base64Cryptogram == null : this$base64Cryptogram.equals(other$base64Cryptogram)) {
            Object this$secureChannelChallenge = this.secureChannelChallenge;
            Object other$secureChannelChallenge = other.secureChannelChallenge;
            if (this$secureChannelChallenge == null ? other$secureChannelChallenge == null : this$secureChannelChallenge.equals(other$secureChannelChallenge)) {
               Object this$pushLoginId = this.pushLoginId;
               Object other$pushLoginId = other.pushLoginId;
               if (this$pushLoginId == null ? other$pushLoginId == null : this$pushLoginId.equals(other$pushLoginId)) {
                  Object this$pushDevices = this.pushDevices;
                  Object other$pushDevices = other.pushDevices;
                  return this$pushDevices == null ? other$pushDevices == null : this$pushDevices.equals(other$pushDevices);
               } else {
                  return false;
               }
            } else {
               return false;
            }
         } else {
            return false;
         }
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public int hashCode() {
      int PRIME = 59;
      int result = 1;
      result = result * 59 + (this.onlineValidation ? 79 : 97);
      result = result * 59 + (this.pushed ? 79 : 97);
      Object $base64Cryptogram = this.base64Cryptogram;
      result = result * 59 + ($base64Cryptogram == null ? 43 : $base64Cryptogram.hashCode());
      Object $secureChannelChallenge = this.secureChannelChallenge;
      result = result * 59 + ($secureChannelChallenge == null ? 43 : $secureChannelChallenge.hashCode());
      Object $pushLoginId = this.pushLoginId;
      result = result * 59 + ($pushLoginId == null ? 43 : $pushLoginId.hashCode());
      Object $pushDevices = this.pushDevices;
      return result * 59 + ($pushDevices == null ? 43 : $pushDevices.hashCode());
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public String toString() {
      return "CrontoAuthChallenge(base64Cryptogram="
         + this.getBase64Cryptogram()
         + ", secureChannelChallenge="
         + this.getSecureChannelChallenge()
         + ", onlineValidation="
         + this.isOnlineValidation()
         + ", pushed="
         + this.isPushed()
         + ", pushLoginId="
         + this.getPushLoginId()
         + ", pushDevices="
         + this.getPushDevices()
         + ")";
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class CrontoAuthChallengeBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String base64Cryptogram;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<String> secureChannelChallenge;
      @SuppressFBWarnings(justification = "generated code")
      private boolean onlineValidation;
      @SuppressFBWarnings(justification = "generated code")
      private boolean pushed;
      @SuppressFBWarnings(justification = "generated code")
      private Optional<String> pushLoginId;
      @SuppressFBWarnings(justification = "generated code")
      private List<CrontoPushDevice> pushDevices;

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

      @SuppressFBWarnings(justification = "generated code")
      public CrontoAuthChallenge.CrontoAuthChallengeBuilder base64Cryptogram(String base64Cryptogram) {
         this.base64Cryptogram = base64Cryptogram;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public CrontoAuthChallenge.CrontoAuthChallengeBuilder secureChannelChallenge(Optional<String> secureChannelChallenge) {
         this.secureChannelChallenge = secureChannelChallenge;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public CrontoAuthChallenge.CrontoAuthChallengeBuilder onlineValidation(boolean onlineValidation) {
         this.onlineValidation = onlineValidation;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public CrontoAuthChallenge.CrontoAuthChallengeBuilder pushed(boolean pushed) {
         this.pushed = pushed;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public CrontoAuthChallenge.CrontoAuthChallengeBuilder pushLoginId(Optional<String> pushLoginId) {
         this.pushLoginId = pushLoginId;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public CrontoAuthChallenge.CrontoAuthChallengeBuilder pushDevices(@NonNull List<CrontoPushDevice> pushDevices) {
         if (pushDevices == null) {
            throw new NullPointerException("pushDevices is marked non-null but is null");
         }

         this.pushDevices = pushDevices;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public CrontoAuthChallenge build() {
         return new CrontoAuthChallenge(
            this.base64Cryptogram, this.secureChannelChallenge, this.onlineValidation, this.pushed, this.pushLoginId, this.pushDevices
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "CrontoAuthChallenge.CrontoAuthChallengeBuilder(base64Cryptogram="
            + this.base64Cryptogram
            + ", secureChannelChallenge="
            + this.secureChannelChallenge
            + ", onlineValidation="
            + this.onlineValidation
            + ", pushed="
            + this.pushed
            + ", pushLoginId="
            + this.pushLoginId
            + ", pushDevices="
            + this.pushDevices
            + ")";
      }
   }
}
