package dev.lions.unionflow.server.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * Entité Role pour la gestion des rôles dans le système
 *
 * @author UnionFlow Team
 * @version 3.1
 * @since 2025-01-29
 */
@Entity
@Table(name = "roles", indexes = {
    @Index(name = "idx_role_code", columnList = "code", unique = true),
    @Index(name = "idx_role_actif", columnList = "actif"),
    @Index(name = "idx_role_niveau", columnList = "niveau_hierarchique")
})
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class Role extends BaseEntity {

  /** Code unique du rôle */
  @NotBlank
  @Column(name = "code", unique = true, nullable = false, length = 50)
  private String code;

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

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

  /** Niveau hiérarchique (plus bas = plus prioritaire) */
  @NotNull
  @Builder.Default
  @Column(name = "niveau_hierarchique", nullable = false)
  private Integer niveauHierarchique = 100;

  /** Type de rôle (SYSTEME, ORGANISATION, PERSONNALISE) */
  @Column(name = "type_role", nullable = false, length = 50)
  private String typeRole;

  /** Catégorie du rôle (PLATEFORME, FONCTIONNEL, METIER) */
  @Column(name = "categorie", length = 30)
  @Builder.Default
  private String categorie = "FONCTIONNEL";

  /** Organisation propriétaire (null pour rôles système) */
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "organisation_id")
  private Organisation organisation;

  /** Permissions associées */
  @JsonIgnore
  @OneToMany(mappedBy = "role", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  @Builder.Default
  private List<RolePermission> permissions = new ArrayList<>();

  /** Énumération des constantes de types de rôle */
  public enum TypeRole {
    SYSTEME,
    ORGANISATION,
    PERSONNALISE;
  }

  /** Méthode métier pour vérifier si c'est un rôle système */
  public boolean isRoleSysteme() {
    return TypeRole.SYSTEME.name().equals(typeRole);
  }

  /** Callback JPA avant la persistance */
  @PrePersist
  protected void onCreate() {
    super.onCreate();
    if (typeRole == null) {
      typeRole = TypeRole.PERSONNALISE.name();
    }
    if (niveauHierarchique == null) {
      niveauHierarchique = 100;
    }
  }
}
