package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.BaseEntity;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * Repository de base pour les entités utilisant UUID comme identifiant
 * 
 * <p>Remplace PanacheRepository pour utiliser UUID au lieu de Long.
 * Fournit les fonctionnalités de base de Panache avec UUID.
 * 
 * @param <T> Le type d'entité qui étend BaseEntity
 * @author UnionFlow Team
 * @version 2.0
 * @since 2025-01-16
 */
public abstract class BaseRepository<T extends BaseEntity> {

    @PersistenceContext
    protected EntityManager entityManager;

    protected final Class<T> entityClass;

    protected BaseRepository(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    /**
     * Trouve une entité par son UUID
     * 
     * @param id L'UUID de l'entité
     * @return L'entité trouvée ou null
     */
    public T findById(UUID id) {
        return entityManager.find(entityClass, id);
    }

    /**
     * Trouve une entité par son UUID (retourne Optional)
     * 
     * @param id L'UUID de l'entité
     * @return Optional contenant l'entité si trouvée
     */
    public Optional<T> findByIdOptional(UUID id) {
        return Optional.ofNullable(findById(id));
    }

    /**
     * Persiste une entité
     * 
     * @param entity L'entité à persister
     */
    @Transactional
    public void persist(T entity) {
        entityManager.persist(entity);
    }

    /**
     * Met à jour une entité
     * 
     * @param entity L'entité à mettre à jour
     * @return L'entité mise à jour
     */
    @Transactional
    public T update(T entity) {
        return entityManager.merge(entity);
    }

    /**
     * Supprime une entité
     * 
     * @param entity L'entité à supprimer
     */
    @Transactional
    public void delete(T entity) {
        entityManager.remove(entity);
    }

    /**
     * Supprime une entité par son UUID
     * 
     * @param id L'UUID de l'entité à supprimer
     */
    @Transactional
    public boolean deleteById(UUID id) {
        T entity = findById(id);
        if (entity != null) {
            delete(entity);
            return true;
        }
        return false;
    }

    /**
     * Liste toutes les entités
     * 
     * @return La liste de toutes les entités
     */
    public List<T> listAll() {
        return entityManager.createQuery(
            "SELECT e FROM " + entityClass.getSimpleName() + " e", entityClass)
            .getResultList();
    }

    /**
     * Compte toutes les entités
     * 
     * @return Le nombre total d'entités
     */
    public long count() {
        return entityManager.createQuery(
            "SELECT COUNT(e) FROM " + entityClass.getSimpleName() + " e", Long.class)
            .getSingleResult();
    }

    /**
     * Vérifie si une entité existe par son UUID
     * 
     * @param id L'UUID de l'entité
     * @return true si l'entité existe
     */
    public boolean existsById(UUID id) {
        return findById(id) != null;
    }

    /**
     * Obtient l'EntityManager (pour les requêtes avancées)
     * 
     * @return L'EntityManager
     */
    public EntityManager getEntityManager() {
        return entityManager;
    }
}

