package dev.lions.unionflow.server.entity;

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

/**
 * Entité CompteComptable pour le plan comptable
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Entity
@Table(
    name = "comptes_comptables",
    indexes = {
      @Index(name = "idx_compte_numero", columnList = "numero_compte", unique = true),
      @Index(name = "idx_compte_type", columnList = "type_compte"),
      @Index(name = "idx_compte_classe", columnList = "classe_comptable")
    })
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class CompteComptable extends BaseEntity {

  /** Numéro de compte unique (ex: 411000, 512000) */
  @NotBlank
  @Column(name = "numero_compte", unique = true, nullable = false, length = 10)
  private String numeroCompte;

  /** Libellé du compte */
  @NotBlank
  @Column(name = "libelle", nullable = false, length = 200)
  private String libelle;

  /** Type de compte */
  @NotNull
  @Enumerated(EnumType.STRING)
  @Column(name = "type_compte", nullable = false, length = 30)
  private TypeCompteComptable typeCompte;

  /** Classe comptable (1-7) */
  @NotNull
  @Min(value = 1, message = "La classe comptable doit être entre 1 et 9")
  @Max(value = 9, message = "La classe comptable doit être entre 1 et 9")
  @Column(name = "classe_comptable", nullable = false)
  private Integer classeComptable;

  /** Solde initial */
  @Builder.Default
  @DecimalMin(value = "0.0", message = "Le solde initial doit être positif ou nul")
  @Digits(integer = 12, fraction = 2)
  @Column(name = "solde_initial", precision = 14, scale = 2)
  private BigDecimal soldeInitial = BigDecimal.ZERO;

  /** Solde actuel (calculé) */
  @Builder.Default
  @Digits(integer = 12, fraction = 2)
  @Column(name = "solde_actuel", precision = 14, scale = 2)
  private BigDecimal soldeActuel = BigDecimal.ZERO;

  /** Compte collectif (regroupe plusieurs sous-comptes) */
  @Builder.Default
  @Column(name = "compte_collectif", nullable = false)
  private Boolean compteCollectif = false;

  /** Compte analytique */
  @Builder.Default
  @Column(name = "compte_analytique", nullable = false)
  private Boolean compteAnalytique = false;

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

  /** Organisation propriétaire (null = compte standard global) */
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "organisation_id")
  private Organisation organisation;

  /** Lignes d'écriture associées */
  @JsonIgnore
  @OneToMany(mappedBy = "compteComptable", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  @Builder.Default
  private List<LigneEcriture> lignesEcriture = new ArrayList<>();

  /** Méthode métier pour obtenir le numéro formaté */
  public String getNumeroFormate() {
    return String.format("%-10s", numeroCompte);
  }

  /** Méthode métier pour vérifier si c'est un compte de trésorerie */
  public boolean isTresorerie() {
    return TypeCompteComptable.TRESORERIE.equals(typeCompte);
  }

  /** Callback JPA avant la persistance */
  @PrePersist
  protected void onCreate() {
    super.onCreate();
    if (soldeInitial == null) {
      soldeInitial = BigDecimal.ZERO;
    }
    if (soldeActuel == null) {
      soldeActuel = soldeInitial;
    }
    if (compteCollectif == null) {
      compteCollectif = false;
    }
    if (compteAnalytique == null) {
      compteAnalytique = false;
    }
  }
}

