/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package com.arrebol.taxiservicios.controller.predio;

import com.arrebol.taxiservicios.controller.admin.GenericPersonController;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.PersonType;
import com.arrebol.taxiservicios.model.predio.CompraLoteCancelada;
import com.arrebol.taxiservicios.model.predio.Lote;
import com.arrebol.taxiservicios.model.predio.Manzana;
import com.arrebol.taxiservicios.model.predio.Predio;
import com.arrebol.taxiservicios.model.view.PersonListView;
import com.arrebol.taxiservicios.model.view.report.AbonoTotalPay;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author pc one
 */
public class PreventaController extends GenericPersonController implements Serializable {

    private static final long serialVersionUID = -6265444716269535946L;
    final Logger logger = LogManager.getLogger(PredioController.class);

    public List<Predio> fillAllPredio(Location location) {
        logger.info("Searching all predios..");

        List<Predio> result = null;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<Predio> criteria = builder.createQuery(Predio.class);
            Root<Predio> root = criteria.from(Predio.class);

            Path<String> id = root.get("id");
            Path<String> idPropetiario = root.get("propetiario");
            Path<String> nombreProyecto = root.get("nombreProyecto");
            Predicate criterioLocation = builder.equal(root.get("location"), location);
            Predicate criterioEstatus = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.select(builder.construct(Predio.class, id, idPropetiario, nombreProyecto));
            criteria.where(builder.and(criterioLocation, criterioEstatus));
            result = session.createQuery(criteria).getResultList();

            logger.info("Total of predios found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to load predios list ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillAllPredio", e);
        }

        return result;
    }

    public List<Manzana> fillAllManzanas(Predio predio) {
        logger.info("Searching all manzanas..");

        List<Manzana> result = null;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<Manzana> criteria = builder.createQuery(Manzana.class);
            Root<Manzana> root = criteria.from(Manzana.class);

            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate criteriaPredio = builder.equal(root.get("predio"), predio);
            criteria.where(builder.and(criterioActivo, criteriaPredio));

            criteria.orderBy(builder.desc(root.get("nombre")));
            result = session.createQuery(criteria).getResultList();

            logger.info("Total of manzanas found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to load manzanas list ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillAllManzanas", e);
        }

        return result;
    }

    public long countManzanasByProyecto(String idProyecto) {
        logger.info("Counting manzanas...");

        long count = 0;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<Manzana> root = criteria.from(Manzana.class);

            criteria.select(builder.count(root));
            criteria.where(
            builder.equal(root.get("predio").get("id"), idProyecto),
            builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED)
        );

            count = session.createQuery(criteria).getSingleResult();

            logger.info("Total of manzanas found: " + count);
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to count manzanas", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method countManzanasByProyecto", e);
        }

        return count;
    }
    
    public long countLotesByManzana(String idManzana) {
        logger.info("Counting manzanas...");

        long count = 0;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<Lote> root = criteria.from(Lote.class);

            criteria.select(builder.count(root));
            criteria.where(
            builder.equal(root.get("manzana").get("id"), idManzana),
            builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED)
        );

            count = session.createQuery(criteria).getSingleResult();

            logger.info("Total of manzanas found: " + count);
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to count manzanas", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method countManzanasByProyecto", e);
        }

        return count;
    }

    public List<Lote> fillAllLotes(Manzana apple) {
        logger.info("Searching all lotes..");

        List<Lote> result = null;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<Lote> criteria = builder.createQuery(Lote.class);
            Root<Lote> root = criteria.from(Lote.class);

            Predicate criterio = (builder.equal(root.get("manzana"), apple));
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.where(builder.and(criterio, criterioActivo));
            result = session.createQuery(criteria).getResultList();

            logger.info("Total of lotes found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to load lotes list ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillAllLotes", e);
        }

        return result;
    }
    
    public List<AbonoTotalPay> fillAllLotesTotalPay(Manzana apple) {
        logger.info("Searching all lotes..");

        List<AbonoTotalPay> result = null;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoTotalPay> criteria = builder.createQuery(AbonoTotalPay.class);
            Root<AbonoTotalPay> root = criteria.from(AbonoTotalPay.class);

            Predicate criterio = (builder.equal(root.get("idManzana"), apple.getId()));
            criteria.where(builder.and(criterio));
            result = session.createQuery(criteria).getResultList();

            logger.info("Total of lotes found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to load lotes list ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillAllLotes", e);
        }

        return result;
    }

    public List<PersonListView> findListOfPersonsByType(PersonType type, Location location) {
        List<PersonListView> results = null;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            String hql = "FROM PersonListView WHERE type = :type AND location = :location";

            results = session.createQuery(hql).setParameter("type", type).setParameter("location", location).getResultList();

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not list of persons", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method findListOfPersonsByType() ", e);
            rollback(transaction);
        }
        return results;
    }

    public boolean canselarCompraLote(CompraLoteCancelada ca, User user, boolean save) {

        logger.info("addLote");
        boolean success = false;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            if (save) {
                ca.setCreatedBy(user);
                ca.setCreatedOn(new Date());
                session.save(ca);
                transaction.commit();
                logger.info("Cancelar compra saved " + ca.getId());
            } else {
                ca.setLastUpdatedBy(user);
                ca.setLastUpdatedOn(new Date());
                session.update(ca);
                transaction.commit();
                logger.info("Cancelar compra updated " + ca.getId());
            }

            success = true;
        } catch (HibernateException e) {
            logger.error("Cancelar compra can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method canselarCompraLote() ", e);
            rollback(transaction);
        }
        return success;
    }

}
