package dev.lions.unionflow.server.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * Association polymorphique entre un document et
 * une entité métier quelconque.
 *
 * <p>
 * Remplace les 6 FK nullables mutuellement
 * exclusives (membre, organisation, cotisation,
 * adhesion, demandeAide, transactionWave) par un
 * couple {@code (type_entite_rattachee,
 * entite_rattachee_id)}.
 *
 * <p>
 * Les types autorisés sont définis dans le
 * domaine {@code ENTITE_RATTACHEE} de la table
 * {@code types_reference} (ex: MEMBRE,
 * ORGANISATION, COTISATION, ADHESION, AIDE,
 * TRANSACTION_WAVE).
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2026-02-21
 */
@Entity
@Table(name = "pieces_jointes", indexes = {
    @Index(name = "idx_pj_document", columnList = "document_id"),
    @Index(name = "idx_pj_entite", columnList = "type_entite_rattachee,"
        + " entite_rattachee_id"),
    @Index(name = "idx_pj_type_entite", columnList = "type_entite_rattachee")
})
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class PieceJointe extends BaseEntity {

  /** Ordre d'affichage. */
  @NotNull
  @Min(value = 1, message = "L'ordre doit être positif")
  @Column(name = "ordre", nullable = false)
  private Integer ordre;

  /** Libellé de la pièce jointe. */
  @Size(max = 200)
  @Column(name = "libelle", length = 200)
  private String libelle;

  /** Commentaire. */
  @Size(max = 500)
  @Column(name = "commentaire", length = 500)
  private String commentaire;

  /** Document associé (obligatoire). */
  @NotNull
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "document_id", nullable = false)
  private Document document;

  /**
   * Type de l'entité rattachée (code du domaine
   * {@code ENTITE_RATTACHEE} dans
   * {@code types_reference}).
   *
   * <p>
   * Valeurs attendues : {@code MEMBRE},
   * {@code ORGANISATION}, {@code COTISATION},
   * {@code ADHESION}, {@code AIDE},
   * {@code TRANSACTION_WAVE}.
   */
  @NotBlank
  @Size(max = 50)
  @Column(name = "type_entite_rattachee", nullable = false, length = 50)
  private String typeEntiteRattachee;

  /**
   * UUID de l'entité rattachée (membre,
   * organisation, cotisation, etc.).
   */
  @NotNull
  @Column(name = "entite_rattachee_id", nullable = false)
  private UUID entiteRattacheeId;

  /**
   * Callback JPA avant la persistance.
   *
   * <p>
   * Initialise {@code ordre} à 1 si non
   * renseigné. Normalise le type en majuscules.
   */
  @Override
  @PrePersist
  protected void onCreate() {
    super.onCreate();
    if (ordre == null) {
      ordre = 1;
    }
    if (typeEntiteRattachee != null) {
      typeEntiteRattachee = typeEntiteRattachee.toUpperCase();
    }
  }
}
