package dev.lions.models;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.proxy.HibernateProxy;

/**
 * Représente un témoignage de client pour un projet.
 */
@Entity
@Table(name = "project_testimonials")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Getter
@Setter
@ToString
@Builder
@AllArgsConstructor
public class Testimonial implements Serializable {

  @Serial
  private static final long serialVersionUID = 1L;

  @Id
  @NotBlank(message = "L'identifiant du témoignage est obligatoire")
  private String id;

  @NotBlank(message = "Le nom du client est obligatoire")
  @Size(min = 3, max = 100)
  private String clientName;

  @NotBlank(message = "Le poste du client est obligatoire")
  @Size(min = 3, max = 100)
  private String clientPosition;

  @NotBlank(message = "Le contenu du témoignage est obligatoire")
  @Size(min = 10, max = 1000)
  private String content;

  @Size(max = 255)
  private String clientImage;

  @ManyToOne
  @JoinColumn(name = "project_id", nullable = false)
  private Project project;

  @Builder.Default
  private int rating = 5;

  @Builder.Default
  private boolean isFeatured = false;

  @Column(name = "completion_date")
  private LocalDateTime completionDate;

  @Column(name = "created_at", nullable = false, updatable = false)
  private LocalDateTime createdAt;

  @Column(name = "updated_at")
  private LocalDateTime updatedAt;

  /**
   * Constructeur par défaut requis pour JPA.
   */
  public Testimonial() {
    this.createdAt = LocalDateTime.now();
  }

  /**
   * Crée une nouvelle instance de témoignage.
   */
  public static Testimonial create(String clientName, String clientPosition, String content,
                                   String clientImage, Project project, int rating, boolean isFeatured) {
    Testimonial testimonial = new Testimonial();
    testimonial.setClientName(clientName);
    testimonial.setClientPosition(clientPosition);
    testimonial.setContent(content);
    testimonial.setClientImage(clientImage);
    testimonial.setProject(project);
    testimonial.setRating(rating);
    testimonial.setFeatured(isFeatured);
    testimonial.setCreatedAt(LocalDateTime.now());
    return testimonial;
  }

  /**
   * Builder personnalisé pour permettre d'ajouter un titre de projet.
   */
  public static class TestimonialBuilder {
    public TestimonialBuilder projectTitle(String title) {
      if (this.project == null) {
        this.project = new Project();
      }
      this.project.setTitle(title);
      return this;
    }

    public TestimonialBuilder date(LocalDateTime completionDate) {
      this.completionDate = completionDate;
      return this;
    }
  }

  @Override
  public final boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null) {
      return false;
    }
    Class<?> oEffectiveClass =
        o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer()
                                                          .getPersistentClass() : o.getClass();
    Class<?> thisEffectiveClass =
        this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer()
                                                                .getPersistentClass()
                                       : this.getClass();
    if (thisEffectiveClass != oEffectiveClass) {
      return false;
    }
    Testimonial that = (Testimonial) o;
    return getId() != null && Objects.equals(getId(), that.getId());
  }

  @Override
  public final int hashCode() {
    return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer()
                                                                   .getPersistentClass().hashCode()
                                          : getClass().hashCode();
  }
}
