package org.jpos.tcpay.db.repository;

import org.jpos.tcpay.ApplicationProperties;
import org.jpos.util.AppLogger;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.function.Function;

/**
 * Base JPA repository providing EntityManager management and transaction handling
 */
public abstract class BaseJpaRepository {
    
    protected final AppLogger logger = new AppLogger();
    private static EntityManagerFactory entityManagerFactory;
    
    static {
        try {
            entityManagerFactory = Persistence.createEntityManagerFactory(
                    "jpos-tcpay-local", 
                    new ApplicationProperties().getPersistenceProperties()
            );
        } catch (Exception e) {
            new AppLogger().exceptionLog(e);
        }
    }
    
    protected EntityManager createEntityManager() {
        return entityManagerFactory.createEntityManager();
    }
    
    protected <T> T executeInTransaction(Function<EntityManager, T> operation) {
        EntityManager em = createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        
        try {
            transaction.begin();
            T result = operation.apply(em);
            transaction.commit();
            return result;
        } catch (Exception e) {
            if (transaction.isActive()) {
                transaction.rollback();
            }
            logger.exceptionLog(e);
            throw new RuntimeException("Transaction failed", e);
        } finally {
            em.close();
        }
    }
    
    protected <T> T executeWithEntityManager(Function<EntityManager, T> operation) {
        EntityManager em = createEntityManager();
        try {
            return operation.apply(em);
        } catch (Exception e) {
            logger.exceptionLog(e);
            throw new RuntimeException("Operation failed", e);
        } finally {
            em.close();
        }
    }
    
    public static void closeEntityManagerFactory() {
        if (entityManagerFactory != null && entityManagerFactory.isOpen()) {
            entityManagerFactory.close();
        }
    }
}