package dev.lions.unionflow.server.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * Entité LigneEcriture pour les lignes d'une écriture comptable
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Entity
@Table(
    name = "lignes_ecriture",
    indexes = {
      @Index(name = "idx_ligne_ecriture_ecriture", columnList = "ecriture_id"),
      @Index(name = "idx_ligne_ecriture_compte", columnList = "compte_comptable_id")
    })
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class LigneEcriture extends BaseEntity {

  /** Numéro de ligne */
  @NotNull
  @Min(value = 1, message = "Le numéro de ligne doit être positif")
  @Column(name = "numero_ligne", nullable = false)
  private Integer numeroLigne;

  /** Montant débit */
  @DecimalMin(value = "0.0", message = "Le montant débit doit être positif ou nul")
  @Digits(integer = 12, fraction = 2)
  @Column(name = "montant_debit", precision = 14, scale = 2)
  private BigDecimal montantDebit;

  /** Montant crédit */
  @DecimalMin(value = "0.0", message = "Le montant crédit doit être positif ou nul")
  @Digits(integer = 12, fraction = 2)
  @Column(name = "montant_credit", precision = 14, scale = 2)
  private BigDecimal montantCredit;

  /** Libellé de la ligne */
  @Column(name = "libelle", length = 500)
  private String libelle;

  /** Référence */
  @Column(name = "reference", length = 100)
  private String reference;

  // Relations
  @NotNull
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "ecriture_id", nullable = false)
  private EcritureComptable ecriture;

  @NotNull
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "compte_comptable_id", nullable = false)
  private CompteComptable compteComptable;

  /** Méthode métier pour vérifier que la ligne a soit un débit soit un crédit (pas les deux) */
  public boolean isValide() {
    boolean aDebit = montantDebit != null && montantDebit.compareTo(BigDecimal.ZERO) > 0;
    boolean aCredit = montantCredit != null && montantCredit.compareTo(BigDecimal.ZERO) > 0;
    return aDebit != aCredit; // XOR : soit débit, soit crédit, pas les deux
  }

  /** Méthode métier pour obtenir le montant (débit ou crédit) */
  public BigDecimal getMontant() {
    if (montantDebit != null && montantDebit.compareTo(BigDecimal.ZERO) > 0) {
      return montantDebit;
    }
    if (montantCredit != null && montantCredit.compareTo(BigDecimal.ZERO) > 0) {
      return montantCredit;
    }
    return BigDecimal.ZERO;
  }

  /** Callback JPA avant la persistance */
  @PrePersist
  protected void onCreate() {
    super.onCreate();
    if (montantDebit == null) {
      montantDebit = BigDecimal.ZERO;
    }
    if (montantCredit == null) {
      montantCredit = BigDecimal.ZERO;
    }
  }
}

