package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.document.TypeDocument;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * Entité Document pour la gestion documentaire sécurisée
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Entity
@Table(
    name = "documents",
    indexes = {
      @Index(name = "idx_document_nom_fichier", columnList = "nom_fichier"),
      @Index(name = "idx_document_type", columnList = "type_document"),
      @Index(name = "idx_document_hash_md5", columnList = "hash_md5"),
      @Index(name = "idx_document_hash_sha256", columnList = "hash_sha256")
    })
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class Document extends BaseEntity {

  /** Nom du fichier original */
  @NotBlank
  @Column(name = "nom_fichier", nullable = false, length = 255)
  private String nomFichier;

  /** Nom original du fichier (tel que téléchargé) */
  @Column(name = "nom_original", length = 255)
  private String nomOriginal;

  /** Chemin de stockage */
  @NotBlank
  @Column(name = "chemin_stockage", nullable = false, length = 1000)
  private String cheminStockage;

  /** Type MIME */
  @Column(name = "type_mime", length = 100)
  private String typeMime;

  /** Taille du fichier en octets */
  @NotNull
  @Min(value = 0, message = "La taille doit être positive")
  @Column(name = "taille_octets", nullable = false)
  private Long tailleOctets;

  /** Type de document */
  @Enumerated(EnumType.STRING)
  @Column(name = "type_document", length = 50)
  private TypeDocument typeDocument;

  /** Hash MD5 pour vérification d'intégrité */
  @Column(name = "hash_md5", length = 32)
  private String hashMd5;

  /** Hash SHA256 pour vérification d'intégrité */
  @Column(name = "hash_sha256", length = 64)
  private String hashSha256;

  /** Description du document */
  @Column(name = "description", length = 1000)
  private String description;

  /** Nombre de téléchargements */
  @Builder.Default
  @Column(name = "nombre_telechargements", nullable = false)
  private Integer nombreTelechargements = 0;

  /** Date de dernier téléchargement */
  @Column(name = "date_dernier_telechargement")
  private java.time.LocalDateTime dateDernierTelechargement;

  /** Pièces jointes associées */
  @JsonIgnore
  @OneToMany(mappedBy = "document", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  @Builder.Default
  private List<PieceJointe> piecesJointes = new ArrayList<>();

  /** Méthode métier pour vérifier l'intégrité avec MD5 */
  public boolean verifierIntegriteMd5(String hashAttendu) {
    return hashMd5 != null && hashMd5.equalsIgnoreCase(hashAttendu);
  }

  /** Méthode métier pour vérifier l'intégrité avec SHA256 */
  public boolean verifierIntegriteSha256(String hashAttendu) {
    return hashSha256 != null && hashSha256.equalsIgnoreCase(hashAttendu);
  }

  /** Méthode métier pour obtenir la taille formatée */
  public String getTailleFormatee() {
    if (tailleOctets == null) {
      return "0 B";
    }
    if (tailleOctets < 1024) {
      return tailleOctets + " B";
    } else if (tailleOctets < 1024 * 1024) {
      return String.format("%.2f KB", tailleOctets / 1024.0);
    } else {
      return String.format("%.2f MB", tailleOctets / (1024.0 * 1024.0));
    }
  }

  /** Callback JPA avant la persistance */
  @PrePersist
  protected void onCreate() {
    super.onCreate();
    if (nombreTelechargements == null) {
      nombreTelechargements = 0;
    }
    if (typeDocument == null) {
      typeDocument = TypeDocument.AUTRE;
    }
  }
}

