package ru.ibs.socrates.confexporter.dao.entity;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import java.time.OffsetDateTime;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.Hibernate;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.annotations.UuidGenerator;

@Getter
@Setter
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "message")
public class MessageEntity {

  @Id
  @UuidGenerator
  private UUID id;

  /**
   * ID из RabbitMQ сообщения
   */
  @Column(name = "external_message_id", nullable = false, length = 36)
  private UUID externalMessagelId;

  /**
   * Проект
   */
  @OneToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.PERSIST)
  @JoinColumn(name = "project_id", nullable = false)
  private ProjectEntity project;

  /**
   * Тип контента в сообщении
   */
  @Column(name = "content_type", nullable = false)
  private String contentType;

  /**
   * Содержимое сообщения
   */
  @OneToMany(mappedBy = "message", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  @ToString.Exclude
  @EqualsAndHashCode.Exclude
  private Set<TextContentEntity> content;

  /**
   * Размер содержимого
   */
  @Column(name = "content_size", nullable = false)
  private Long contentSize;

  @CreationTimestamp
  @Column(name = "created", updatable = false, nullable = false)
  private OffsetDateTime created;

  @UpdateTimestamp
  @Column(name = "updated", nullable = false)
  private OffsetDateTime updated;
  
  @PrePersist
  @PreUpdate
  private void onUpdate() {
    this.setContentSize(Optional.ofNullable(getText())
        .map(String::length)
        .map(Integer::longValue)
        .orElse(0L));
  }

  @Transient
  public TextContentEntity getContentEntity() {
    return getContent().iterator().next();
  }

  @Transient
  public String getText() {
    return getContent().iterator().next().getText();
  }

  @Transient
  public String getLink() {
    return getContent().iterator().next().getLink();
  }
  
  public void addContent(TextContentEntity content) {
    if (this.content == null) {
      this.content = new HashSet<>();
    }
    this.content.add(content);
    content.setMessage(this);
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) {
      return false;
    }
    MessageEntity that = (MessageEntity) o;
    return id != null && Objects.equals(id, that.getId());
  }

  @Override
  public int hashCode() {
    return getClass().hashCode();
  }

}
