package dev.lions.unionflow.server.service;

import dev.lions.unionflow.server.entity.Permission;
import dev.lions.unionflow.server.repository.PermissionRepository;
import dev.lions.unionflow.server.service.KeycloakService;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.NotFoundException;
import java.util.List;
import java.util.UUID;
import org.jboss.logging.Logger;

/**
 * Service métier pour la gestion des permissions
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@ApplicationScoped
public class PermissionService {

  private static final Logger LOG = Logger.getLogger(PermissionService.class);

  @Inject PermissionRepository permissionRepository;

  @Inject KeycloakService keycloakService;

  /**
   * Crée une nouvelle permission
   *
   * @param permission Permission à créer
   * @return Permission créée
   */
  @Transactional
  public Permission creerPermission(Permission permission) {
    LOG.infof("Création d'une nouvelle permission: %s", permission.getCode());

    // Vérifier l'unicité du code
    if (permissionRepository.findByCode(permission.getCode()).isPresent()) {
      throw new IllegalArgumentException(
          "Une permission avec ce code existe déjà: " + permission.getCode());
    }

    // Générer le code si non fourni
    if (permission.getCode() == null || permission.getCode().isEmpty()) {
      permission.setCode(
          Permission.genererCode(
              permission.getModule(), permission.getRessource(), permission.getAction()));
    }

    // Métadonnées
    permission.setCreePar(keycloakService.getCurrentUserEmail());

    permissionRepository.persist(permission);
    LOG.infof(
        "Permission créée avec succès: ID=%s, Code=%s",
        permission.getId(), permission.getCode());

    return permission;
  }

  /**
   * Met à jour une permission existante
   *
   * @param id ID de la permission
   * @param permissionModifiee Permission avec les modifications
   * @return Permission mise à jour
   */
  @Transactional
  public Permission mettreAJourPermission(UUID id, Permission permissionModifiee) {
    LOG.infof("Mise à jour de la permission ID: %s", id);

    Permission permission =
        permissionRepository
            .findPermissionById(id)
            .orElseThrow(() -> new NotFoundException("Permission non trouvée avec l'ID: " + id));

    // Mise à jour
    permission.setCode(permissionModifiee.getCode());
    permission.setModule(permissionModifiee.getModule());
    permission.setRessource(permissionModifiee.getRessource());
    permission.setAction(permissionModifiee.getAction());
    permission.setLibelle(permissionModifiee.getLibelle());
    permission.setDescription(permissionModifiee.getDescription());
    permission.setModifiePar(keycloakService.getCurrentUserEmail());

    permissionRepository.persist(permission);
    LOG.infof("Permission mise à jour avec succès: ID=%s", id);

    return permission;
  }

  /**
   * Trouve une permission par son ID
   *
   * @param id ID de la permission
   * @return Permission ou null
   */
  public Permission trouverParId(UUID id) {
    return permissionRepository.findPermissionById(id).orElse(null);
  }

  /**
   * Trouve une permission par son code
   *
   * @param code Code de la permission
   * @return Permission ou null
   */
  public Permission trouverParCode(String code) {
    return permissionRepository.findByCode(code).orElse(null);
  }

  /**
   * Liste les permissions par module
   *
   * @param module Nom du module
   * @return Liste des permissions
   */
  public List<Permission> listerParModule(String module) {
    return permissionRepository.findByModule(module);
  }

  /**
   * Liste les permissions par ressource
   *
   * @param ressource Nom de la ressource
   * @return Liste des permissions
   */
  public List<Permission> listerParRessource(String ressource) {
    return permissionRepository.findByRessource(ressource);
  }

  /**
   * Liste toutes les permissions actives
   *
   * @return Liste des permissions actives
   */
  public List<Permission> listerToutesActives() {
    return permissionRepository.findAllActives();
  }

  /**
   * Supprime (désactive) une permission
   *
   * @param id ID de la permission
   */
  @Transactional
  public void supprimerPermission(UUID id) {
    LOG.infof("Suppression de la permission ID: %s", id);

    Permission permission =
        permissionRepository
            .findPermissionById(id)
            .orElseThrow(() -> new NotFoundException("Permission non trouvée avec l'ID: " + id));

    permission.setActif(false);
    permission.setModifiePar(keycloakService.getCurrentUserEmail());

    permissionRepository.persist(permission);
    LOG.infof("Permission supprimée avec succès: ID=%s", id);
  }
}

