package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * Entité JournalComptable pour la gestion des journaux
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Entity
@Table(
    name = "journaux_comptables",
    uniqueConstraints = {
      @UniqueConstraint(name = "uk_journaux_org_code", columnNames = {"organisation_id", "code"})
    },
    indexes = {
      @Index(name = "idx_journal_code", columnList = "code"),
      @Index(name = "idx_journal_type", columnList = "type_journal"),
      @Index(name = "idx_journal_periode", columnList = "date_debut, date_fin")
    })
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class JournalComptable extends BaseEntity {

  /** Code du journal (unique par organisation). */
  @NotBlank
  @Column(name = "code", nullable = false, length = 10)
  private String code;

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

  /** Type de journal */
  @NotNull
  @Enumerated(EnumType.STRING)
  @Column(name = "type_journal", nullable = false, length = 30)
  private TypeJournalComptable typeJournal;

  /** Date de début de la période */
  @Column(name = "date_debut")
  private LocalDate dateDebut;

  /** Date de fin de la période */
  @Column(name = "date_fin")
  private LocalDate dateFin;

  /** Statut du journal (OUVERT, FERME, ARCHIVE) */
  @Builder.Default
  @Column(name = "statut", length = 20)
  private String statut = "OUVERT";

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

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

  /** Écritures comptables associées */
  @JsonIgnore
  @OneToMany(mappedBy = "journal", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  @Builder.Default
  private List<EcritureComptable> ecritures = new ArrayList<>();

  /** Méthode métier pour vérifier si le journal est ouvert */
  public boolean isOuvert() {
    return "OUVERT".equals(statut);
  }

  /** Méthode métier pour vérifier si une date est dans la période */
  public boolean estDansPeriode(LocalDate date) {
    if (dateDebut == null || dateFin == null) {
      return true; // Période illimitée
    }
    return !date.isBefore(dateDebut) && !date.isAfter(dateFin);
  }

  /** Callback JPA avant la persistance */
  @PrePersist
  protected void onCreate() {
    super.onCreate();
    if (statut == null || statut.isEmpty()) {
      statut = "OUVERT";
    }
  }
}

