package dev.lions.unionflow.server.entity;

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

/**
 * Entité Permission pour la gestion des permissions granulaires
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Entity
@Table(
    name = "permissions",
    indexes = {
      @Index(name = "idx_permission_code", columnList = "code", unique = true),
      @Index(name = "idx_permission_module", columnList = "module"),
      @Index(name = "idx_permission_ressource", columnList = "ressource")
    })
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class Permission extends BaseEntity {

  /** Code unique de la permission (format: MODULE > RESSOURCE > ACTION) */
  @NotBlank
  @Column(name = "code", unique = true, nullable = false, length = 100)
  private String code;

  /** Module (ex: ORGANISATION, MEMBRE, COTISATION) */
  @NotBlank
  @Column(name = "module", nullable = false, length = 50)
  private String module;

  /** Ressource (ex: MEMBRE, COTISATION, ADHESION) */
  @NotBlank
  @Column(name = "ressource", nullable = false, length = 50)
  private String ressource;

  /** Action (ex: CREATE, READ, UPDATE, DELETE, VALIDATE) */
  @NotBlank
  @Column(name = "action", nullable = false, length = 50)
  private String action;

  /** Libellé de la permission */
  @Column(name = "libelle", length = 200)
  private String libelle;

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

  /** Rôles associés */
  @JsonIgnore
  @OneToMany(mappedBy = "permission", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  @Builder.Default
  private List<RolePermission> roles = new ArrayList<>();

  /** Méthode métier pour générer le code à partir des composants */
  public static String genererCode(String module, String ressource, String action) {
    return String.format("%s > %s > %s", module.toUpperCase(), ressource.toUpperCase(), action.toUpperCase());
  }

  /** Méthode métier pour vérifier si le code est valide */
  public boolean isCodeValide() {
    return code != null && code.contains(" > ") && code.split(" > ").length == 3;
  }

  /** Callback JPA avant la persistance */
  @PrePersist
  protected void onCreate() {
    super.onCreate();
    // Générer le code si non fourni
    if (code == null || code.isEmpty()) {
      if (module != null && ressource != null && action != null) {
        code = genererCode(module, ressource, action);
      }
    }
  }
}

