package org.jpos.tcpay.db.repository;

import org.jpos.tcpay.db.entity.PosTransaction;
import org.jpos.util.AppLogger;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * JPA implementation of PosTransactionRepository
 * Uses EntityManager for all database operations
 */
public class PosTransactionRepositoryImpl implements PosTransactionRepository {
    
    private final EntityManagerFactory emf;
    private final AppLogger logger = new AppLogger();
    
    public PosTransactionRepositoryImpl(EntityManagerFactory emf) {
        this.emf = emf;
    }
    
    @Override
    public PosTransaction save(PosTransaction transaction) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        
        try {
            tx.begin();
            
            if (transaction.getId() == null) {
                em.persist(transaction);
            } else {
                transaction = em.merge(transaction);
            }
            
            tx.commit();
            logger.log("Saved transaction: " + transaction.getId());
            return transaction;
            
        } catch (Exception e) {
            if (tx.isActive()) {
                tx.rollback();
            }
            logger.log("Error saving transaction: " + e.getMessage());
            throw new RuntimeException("Failed to save transaction", e);
        } finally {
            em.close();
        }
    }
    
    @Override
    public Optional<PosTransaction> findById(Long id) {
        EntityManager em = emf.createEntityManager();
        try {
            PosTransaction transaction = em.find(PosTransaction.class, id);
            return Optional.ofNullable(transaction);
        } catch (Exception e) {
            logger.log("Error finding transaction by ID: " + e.getMessage());
            return Optional.empty();
        } finally {
            em.close();
        }
    }
    
    @Override
    public List<PosTransaction> findByBankTidAndBankMid(String bTid, String bMid) {
        EntityManager em = emf.createEntityManager();
        try {
            TypedQuery<PosTransaction> query = em.createQuery(
                "SELECT t FROM PosTransaction t WHERE t.bTid = :bTid AND t.bMid = :bMid", 
                PosTransaction.class
            );
            query.setParameter("bTid", bTid);
            query.setParameter("bMid", bMid);
            
            return query.getResultList();
            
        } catch (Exception e) {
            logger.log("Error finding transactions by bank IDs: " + e.getMessage());
            return List.of();
        } finally {
            em.close();
        }
    }
    
    @Override
    public long countTransactionsSince(LocalDateTime since) {
        EntityManager em = emf.createEntityManager();
        try {
            TypedQuery<Long> query = em.createQuery(
                "SELECT COUNT(t) FROM PosTransaction t WHERE t.createdDateTime >= :since", 
                Long.class
            );
            query.setParameter("since", since);
            
            return query.getSingleResult();
            
        } catch (Exception e) {
            logger.log("Error counting transactions since: " + e.getMessage());
            return 0;
        } finally {
            em.close();
        }
    }
    
    @Override
    public List<PosTransaction> findByResponseCode(String responseCode) {
        EntityManager em = emf.createEntityManager();
        try {
            TypedQuery<PosTransaction> query = em.createQuery(
                "SELECT t FROM PosTransaction t WHERE t.responseCode = :responseCode", 
                PosTransaction.class
            );
            query.setParameter("responseCode", responseCode);
            
            return query.getResultList();
            
        } catch (Exception e) {
            logger.log("Error finding transactions by response code: " + e.getMessage());
            return List.of();
        } finally {
            em.close();
        }
    }
    
    @Override
    public long count() {
        EntityManager em = emf.createEntityManager();
        try {
            TypedQuery<Long> query = em.createQuery(
                "SELECT COUNT(t) FROM PosTransaction t", 
                Long.class
            );
            return query.getSingleResult();
            
        } catch (Exception e) {
            logger.log("Error counting transactions: " + e.getMessage());
            return 0;
        } finally {
            em.close();
        }
    }
}