package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.membre.TypePieceIdentite;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * Bénéficiaire effectif (UBO — Ultimate Beneficial Owner) lié à un dossier KYC.
 *
 * <p>Implémente l'obligation introduite par l'<strong>Instruction BCEAO 003-03-2025 du 18 mars
 * 2025</strong> : identification, vérification et connaissance du client par les institutions
 * financières — vérification systématique des bénéficiaires effectifs obligatoire (approche par
 * les risques).
 *
 * <p>Un bénéficiaire effectif est, selon la directive UEMOA et le GAFI/FATF, toute personne
 * physique qui :
 *
 * <ul>
 *   <li>détient au moins <strong>25 %</strong> du capital ou des droits de vote d'une personne
 *       morale ;
 *   <li>OU exerce un contrôle effectif (de fait ou de droit) sur la gestion de l'entité ;
 *   <li>OU est bénéficiaire ultime d'une opération suspecte structurée.
 * </ul>
 *
 * <p>Ces enregistrements doivent être conservés <strong>10 ans</strong> après la clôture de la
 * relation d'affaires (directive 02/2015/CM/UEMOA).
 *
 * @since 2026-04-25 — Instruction BCEAO 003-03-2025 (KYC + UBO)
 */
@Entity
@Table(
    name = "beneficiaires_effectifs",
    indexes = {
      @Index(name = "idx_ubo_kyc_dossier", columnList = "kyc_dossier_id"),
      @Index(name = "idx_ubo_organisation_cible", columnList = "organisation_cible_id"),
      @Index(name = "idx_ubo_pays", columnList = "pays_residence")
    })
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class BeneficiaireEffectif extends BaseEntity {

  /** Dossier KYC auquel ce bénéficiaire effectif est rattaché. */
  @NotNull
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "kyc_dossier_id", nullable = false)
  private KycDossier kycDossier;

  /**
   * Organisation cible dont cette personne est bénéficiaire effectif (utile en cas de KYC client
   * personne morale — la chaîne de contrôle UBO peut traverser plusieurs entités).
   */
  @Column(name = "organisation_cible_id")
  private UUID organisationCibleId;

  /** Lien vers le membre UnionFlow correspondant si applicable (UBO interne au système). */
  @Column(name = "membre_id")
  private UUID membreId;

  // Identité

  @NotBlank
  @Column(name = "nom", nullable = false, length = 100)
  private String nom;

  @NotBlank
  @Column(name = "prenoms", nullable = false, length = 200)
  private String prenoms;

  @NotNull
  @Column(name = "date_naissance", nullable = false)
  private LocalDate dateNaissance;

  @Column(name = "lieu_naissance", length = 200)
  private String lieuNaissance;

  @NotBlank
  @Column(name = "nationalite", nullable = false, length = 3)
  private String nationalite; // ISO 3166-1 alpha-3

  @Column(name = "pays_residence", length = 3)
  private String paysResidence;

  // Pièce d'identité

  @Enumerated(EnumType.STRING)
  @Column(name = "type_piece_identite", length = 30)
  private TypePieceIdentite typePieceIdentite;

  @Column(name = "numero_piece_identite", length = 50)
  private String numeroPieceIdentite;

  @Column(name = "date_expiration_piece")
  private LocalDate dateExpirationPiece;

  // Contrôle

  /**
   * Pourcentage de détention en capital (0-100). Si {@code >= 25} → UBO direct selon GAFI.
   * Peut être null si le contrôle est exercé autrement (mandat, accord d'actionnaires).
   */
  @DecimalMin("0.00")
  @DecimalMax("100.00")
  @Column(name = "pourcentage_capital", precision = 5, scale = 2)
  private BigDecimal pourcentageCapital;

  /** Pourcentage des droits de vote (0-100). */
  @DecimalMin("0.00")
  @DecimalMax("100.00")
  @Column(name = "pourcentage_droits_vote", precision = 5, scale = 2)
  private BigDecimal pourcentageDroitsVote;

  /**
   * Nature du contrôle exercé : DETENTION_CAPITAL, DROITS_VOTE, CONTROLE_DE_FAIT,
   * BENEFICIAIRE_ULTIME, MANDAT_REPRESENTATION.
   */
  @NotBlank
  @Column(name = "nature_controle", nullable = false, length = 50)
  private String natureControle;

  // Politique d'exposition (PEP)

  @Column(name = "est_pep", nullable = false)
  @Builder.Default
  private boolean estPep = false;

  @Column(name = "pep_categorie", length = 100)
  private String pepCategorie;

  @Column(name = "pep_pays", length = 3)
  private String pepPays;

  @Column(name = "pep_fonction", length = 200)
  private String pepFonction;

  // Sanctions / vigilance

  @Column(name = "presence_listes_sanctions", nullable = false)
  @Builder.Default
  private boolean presenceListesSanctions = false;

  @Column(name = "details_listes_sanctions", length = 1000)
  private String detailsListesSanctions;

  // Vérification

  @Column(name = "verifie_par_id")
  private UUID verifieParId;

  @Column(name = "date_verification")
  private java.time.LocalDateTime dateVerification;

  @Column(name = "source_verification", length = 200)
  private String sourceVerification;

  @Column(name = "notes", length = 2000)
  private String notes;
}
