package com.airlock.iam.common.api.domain.model.user;

import com.airlock.iam.base.api.domain.model.user.UserId;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Objects;
import java.util.Optional;
import lombok.NonNull;

public record UserIdentity(@NonNull UserId id, @NonNull ProvidedUsername providedUsername, @NonNull Optional<RepresenterId> representerId) {
   @SuppressFBWarnings(justification = "generated code")
   public UserIdentity {
      if (id == null) {
         throw new NullPointerException("id is marked non-null but is null");
      }

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

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

   public UserIdentity(@NonNull UserId id, @NonNull ProvidedUsername providedUsername) {
      this(id, providedUsername, Optional.empty());
      if (id == null) {
         throw new NullPointerException("id is marked non-null but is null");
      }

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

   public UserIdentity(@NonNull UserId id, @NonNull String providedUsername) {
      this(id, ProvidedUsername.providedUsernameOf(providedUsername), Optional.empty());
      if (id == null) {
         throw new NullPointerException("id is marked non-null but is null");
      }

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

   private UserIdentity(@NonNull UserId id, @NonNull ProvidedUsername providedUsername, RepresenterId representerId) {
      this(id, providedUsername, Optional.ofNullable(representerId));
      if (id == null) {
         throw new NullPointerException("id is marked non-null but is null");
      }

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

   public boolean hasSameId(UserIdentity other) {
      return Objects.equals(this.id, other.id);
   }

   public UserIdentity withRepresenter(@NonNull RepresenterId representer) {
      if (representer == null) {
         throw new NullPointerException("representer is marked non-null but is null");
      } else {
         return new UserIdentity(this.id, this.providedUsername, Optional.of(representer));
      }
   }

   public String toLogString() {
      return "UserIdentity[id="
         + this.id.getValue()
         + ", providedUsername="
         + this.providedUsername.getValue()
         + this.representerId.<String>map(r -> ", representerId=" + r.value() + "]").orElse("]");
   }

   @SuppressFBWarnings(justification = "generated code")
   public static UserIdentity.UserIdentityBuilder internalBuilder() {
      return new UserIdentity.UserIdentityBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class UserIdentityBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private UserId id;
      @SuppressFBWarnings(justification = "generated code")
      private ProvidedUsername providedUsername;
      @SuppressFBWarnings(justification = "generated code")
      private RepresenterId representerId;

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

      @SuppressFBWarnings(justification = "generated code")
      public UserIdentity.UserIdentityBuilder id(@NonNull UserId id) {
         if (id == null) {
            throw new NullPointerException("id is marked non-null but is null");
         }

         this.id = id;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public UserIdentity.UserIdentityBuilder providedUsername(@NonNull ProvidedUsername providedUsername) {
         if (providedUsername == null) {
            throw new NullPointerException("providedUsername is marked non-null but is null");
         }

         this.providedUsername = providedUsername;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public UserIdentity.UserIdentityBuilder representerId(RepresenterId representerId) {
         this.representerId = representerId;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public UserIdentity build() {
         return new UserIdentity(this.id, this.providedUsername, this.representerId);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "UserIdentity.UserIdentityBuilder(id="
            + this.id
            + ", providedUsername="
            + this.providedUsername
            + ", representerId="
            + this.representerId
            + ")";
      }
   }
}
