package dev.lions.unionflow.server.entity;

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.0
 * @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 */
  @Enumerated(EnumType.STRING)
  @Column(name = "type_role", nullable = false, length = 50)
  private TypeRole typeRole;

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

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

  /** Énumération des types de rôle */
  public enum TypeRole {
    SYSTEME("Rôle Système"),
    ORGANISATION("Rôle Organisation"),
    PERSONNALISE("Rôle Personnalisé");

    private final String libelle;

    TypeRole(String libelle) {
      this.libelle = libelle;
    }

    public String getLibelle() {
      return libelle;
    }
  }

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

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

