package dev.lions.unionflow.server.api.dto.base;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;

/**
 * Classe de base pour tous les DTOs UnionFlow Fournit les propriétés communes
 * d'audit et de gestion
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-10
 */
@Getter
@Setter
public abstract class BaseDTO implements Serializable {

  @Serial
  private static final long serialVersionUID = 1L;

  /** Identifiant unique UUID */
  private UUID id;

  /** Date de création de l'enregistrement */
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  public LocalDateTime dateCreation;

  /** Date de dernière modification */
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  public LocalDateTime dateModification;

  /** Utilisateur qui a créé l'enregistrement */
  private String creePar;

  /** Utilisateur qui a modifié l'enregistrement en dernier */
  private String modifiePar;

  /** Version pour gestion de la concurrence optimiste */
  private Long version;

  /** Indicateur si l'enregistrement est actif */
  private Boolean actif;

  // Constructeur par défaut
  public BaseDTO() {
    this.dateCreation = LocalDateTime.now();
    this.actif = true;
    this.version = 0L;
  }

  // Getters et Setters générés automatiquement par Lombok @Getter/@Setter

  // Méthodes utilitaires

  /**
   * Marque l'entité comme nouvellement créée
   *
   * @param utilisateur L'utilisateur qui crée l'entité
   */
  public void marquerCommeNouveau(String utilisateur) {
    LocalDateTime maintenant = LocalDateTime.now();
    this.dateCreation = maintenant;
    this.dateModification = maintenant;
    this.creePar = utilisateur;
    this.modifiePar = utilisateur;
    this.version = 0L;
    this.actif = true;
  }

  /**
   * Marque l'entité comme modifiée
   *
   * @param utilisateur L'utilisateur qui modifie l'entité
   */
  public void marquerCommeModifie(String utilisateur) {
    this.dateModification = LocalDateTime.now();
    this.modifiePar = utilisateur;
    if (this.version != null) {
      this.version++;
    }
  }

  /**
   * Désactive l'entité (soft delete)
   *
   * @param utilisateur L'utilisateur qui désactive l'entité
   */
  public void desactiver(String utilisateur) {
    this.actif = false;
    marquerCommeModifie(utilisateur);
  }

  /**
   * Réactive l'entité
   *
   * @param utilisateur L'utilisateur qui réactive l'entité
   */
  public void reactiver(String utilisateur) {
    this.actif = true;
    marquerCommeModifie(utilisateur);
  }

  /**
   * Vérifie si l'entité est nouvelle (pas encore persistée)
   *
   * @return true si l'entité est nouvelle
   */
  public boolean isNouveau() {
    return id == null;
  }

  /**
   * Vérifie si l'entité est active
   *
   * @return true si l'entité est active
   */
  public boolean isActif() {
    return Boolean.TRUE.equals(actif);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null || getClass() != obj.getClass())
      return false;

    BaseDTO baseDTO = (BaseDTO) obj;
    return id != null && id.equals(baseDTO.id);
  }

  @Override
  public int hashCode() {
    return id != null ? id.hashCode() : 0;
  }

  @Override
  public String toString() {
    return getClass().getSimpleName()
        + "{"
        + "id="
        + id
        + ", dateCreation="
        + dateCreation
        + ", dateModification="
        + dateModification
        + ", creePar='"
        + creePar
        + '\''
        + ", modifiePar='"
        + modifiePar
        + '\''
        + ", version="
        + version
        + ", actif="
        + actif
        + '}';
  }
}
