/*
 * 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.crov.prase.controller.prase;

import com.arrebol.taxiservicios.controller.connection.ConnectionManager;
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.crov.prase.model.prase.Incidence;
import com.crov.prase.model.prase.IncidenceDamage;
import com.crov.prase.model.prase.IncidenceEvidencia;
import com.crov.prase.model.prase.IncidenceOwnDriver;
import com.crov.prase.model.prase.IncidenceStory;
import com.crov.prase.model.prase.IncidenceThirdPartyVehicle;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
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 Crov
 */
public class IncidenceController extends ConnectionManager implements Serializable {

    private static final long serialVersionUID = -8772793021819350069L;
    final Logger logger = LogManager.getLogger(getClass());

    public boolean addIncidence(Incidence incidence, User user, boolean save) {
        logger.info("addIncidence");
        boolean success = false;
        Transaction transaction = null;

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

            if (save) {
                incidence.setId(UUID.randomUUID().toString());
                incidence.setCreatedBy(user);
                incidence.setCreatedOn(new Date());
                session.save(incidence);
                transaction.commit();
                logger.info("Incidence saved " + incidence.getId());
            } else {
                incidence.setLastUpdatedOn(new Date());
                incidence.setLastUpdatedBy(user);
                session.update(incidence);
                transaction.commit();
                logger.info("Incidence updated " + incidence.getId());
            }

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

    public Incidence findIncidence(String idIncidence) {
        logger.info("findIncidence");

        Incidence result = null;
        Transaction transaction = null;

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

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

            Predicate criterio = (builder.equal(root.get("id"), idIncidence));
            criteria.where(builder.and(criterio));
            criteria.orderBy(builder.desc(root.get("createdOn")));

            result = session.createQuery(criteria).setMaxResults(1).getSingleResult();
            transaction.commit();
        } catch (NoResultException e) {
            transaction.rollback();
            logger.error("No se encontro la Incidence: " + idIncidence);
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Error al encontrar la Incidence: ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Método findIncidence: ", e);
        }

        return result;
    }

    public List<Incidence> fillIncidenceByLocation(Location location) {
        logger.info("fillIncidenceByLocation");
        List<Incidence> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching Incidence for lote..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

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

            Predicate criterio1 = builder.equal(root.get("location"), location);
            Predicate criterio2 = builder.equal(root.get("active"), true);
            criteria.where(builder.and(criterio1, criterio2));
            criteria.orderBy(builder.desc(root.get("createdOn")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of incidence found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Incidence cannot be loade ");
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillIncidenceByLocation ", e);
            rollback(transaction);
        }
        return resultList;
    }

    public boolean addIncidenceStory(IncidenceStory story, User user, boolean save) {
        logger.info("addIncidenceStory");
        boolean success = false;
        Transaction transaction = null;

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

            if (save) {
                story.setId(UUID.randomUUID().toString());
                story.setCreatedBy(user);
                story.setCreatedOn(new Date());
                session.save(story);
                transaction.commit();
                logger.info("IncidenceStory saved " + story.getId());
            } else {
                story.setLastUpdatedOn(new Date());
                story.setLastUpdatedBy(user);
                session.update(story);
                transaction.commit();
                logger.info("IncidenceStory updated " + story.getId());
            }

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

    public IncidenceStory findIncidenceStoryByIncidence(Incidence incidence) {
        logger.info("findIncidenceStoryByIncidence");

        IncidenceStory result = null;
        Transaction transaction = null;

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

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

            Predicate criterio = (builder.equal(root.get("incidence"), incidence));
            criteria.where(builder.and(criterio));
            criteria.orderBy(builder.desc(root.get("createdOn")));

            result = session.createQuery(criteria).setMaxResults(1).getSingleResult();
            transaction.commit();
        } catch (NoResultException e) {
            transaction.rollback();
            logger.error("No se encontro la IncidenceStory para la incidence: " + incidence);
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Error al encontrar la IncidenceStory: ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Método findIncidenceStoryByIncidence: ", e);
        }

        return result;
    }

    public boolean addIncidenceThirdPartyVehicle(IncidenceThirdPartyVehicle thirdPartyVehicle, User user, boolean save) {
        logger.info("addIncidenceThirdPartyVehicle");
        boolean success = false;
        Transaction transaction = null;

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

            if (save) {
                thirdPartyVehicle.setId(UUID.randomUUID().toString());
                thirdPartyVehicle.setCreatedBy(user);
                thirdPartyVehicle.setCreatedOn(new Date());
                session.save(thirdPartyVehicle);
                transaction.commit();
                logger.info("IncidenceThirdPartyVehicle saved " + thirdPartyVehicle.getId());
            } else {
                thirdPartyVehicle.setLastUpdatedOn(new Date());
                thirdPartyVehicle.setLastUpdatedBy(user);
                session.update(thirdPartyVehicle);
                transaction.commit();
                logger.info("IncidenceThirdPartyVehicle updated " + thirdPartyVehicle.getId());
            }

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

    public IncidenceThirdPartyVehicle findIncidenceThirdPartyVehicleByIncidence(Incidence incidence) {
        logger.info("findIncidenceThirdPartyVehicleByIncidence");

        IncidenceThirdPartyVehicle result = null;
        Transaction transaction = null;

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

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

            Predicate criterio = (builder.equal(root.get("incidence"), incidence));
            criteria.where(builder.and(criterio));
            criteria.orderBy(builder.desc(root.get("createdOn")));

            result = session.createQuery(criteria).setMaxResults(1).getSingleResult();
            transaction.commit();
        } catch (NoResultException e) {
            transaction.rollback();
            logger.error("No se encontro la IncidenceThirdPartyVehicle para la incidence: " + incidence);
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Error al encontrar la IncidenceThirdPartyVehicle: ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Método findIncidenceThirdPartyVehicleByIncidence: ", e);
        }

        return result;
    }
    
    public List<IncidenceThirdPartyVehicle> findListIncidenceThirdPartyVehicleByIncidence(Incidence incidence) {
        logger.info("findIncidenceThirdPartyVehicleByIncidence");

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

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

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

            Predicate criterio = (builder.equal(root.get("incidence"), incidence));
            criteria.where(builder.and(criterio));
            criteria.orderBy(builder.desc(root.get("createdOn")));

            result = session.createQuery(criteria).getResultList();
            transaction.commit();
        } catch (NoResultException e) {
            transaction.rollback();
            logger.error("No se encontro la IncidenceThirdPartyVehicle para la incidence: " + incidence);
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Error al encontrar la IncidenceThirdPartyVehicle: ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Método findIncidenceThirdPartyVehicleByIncidence: ", e);
        }

        return result;
    }

    public boolean addIncidenceOwnDriver(IncidenceOwnDriver ownDriver, User user, boolean save) {
        logger.info("addIncidenceOwnDriver");
        boolean success = false;
        Transaction transaction = null;

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

            if (save) {
                ownDriver.setId(UUID.randomUUID().toString());
                ownDriver.setCreatedBy(user);
                ownDriver.setCreatedOn(new Date());
                session.save(ownDriver);
                transaction.commit();
                logger.info("IncidenceOwnDriver saved " + ownDriver.getId());
            } else {
                ownDriver.setLastUpdatedOn(new Date());
                ownDriver.setLastUpdatedBy(user);
                session.update(ownDriver);
                transaction.commit();
                logger.info("IncidenceOwnDriver updated " + ownDriver.getId());
            }

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

    public List<IncidenceOwnDriver> findAllIncidenceOwnDriverByIncidence(Incidence incidence) {
        logger.info("findAllIncidenceOwnDriverByIncidence");

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

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

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

            Predicate criterio = (builder.equal(root.get("incidence"), incidence));
            criteria.where(builder.and(criterio));
            criteria.orderBy(builder.desc(root.get("createdOn")));

            result = session.createQuery(criteria).getResultList();
            transaction.commit();
        } catch (NoResultException e) {
            transaction.rollback();
            logger.error("No se encontro las IncidenceOwnDriver para la incidence: " + incidence);
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Error al encontrar las IncidenceOwnDriver: ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Método findAllIncidenceOwnDriverByIncidence: ", e);
        }

        return result;
    }

    public boolean addIncidenceDamage(IncidenceDamage damage, User user, boolean save) {
        logger.info("addIncidenceDamage");
        boolean success = false;
        Transaction transaction = null;

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

            if (save) {
                damage.setId(UUID.randomUUID().toString());
                damage.setCreatedBy(user);
                damage.setCreatedOn(new Date());
                session.save(damage);
                transaction.commit();
                logger.info("IncidenceDamage saved " + damage.getId());
            } else {
                damage.setLastUpdatedOn(new Date());
                damage.setLastUpdatedBy(user);
                session.update(damage);
                transaction.commit();
                logger.info("IncidenceDamage updated " + damage.getId());
            }

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

    public List<IncidenceDamage> findAllIncidenceDamageByIncidence(Incidence incidence) {
        logger.info("findAllIncidenceDamageByIncidence");

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

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

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

            Predicate criterio = (builder.equal(root.get("incidence"), incidence));
            criteria.where(builder.and(criterio));
            criteria.orderBy(builder.desc(root.get("createdOn")));

            result = session.createQuery(criteria).getResultList();
            transaction.commit();
        } catch (NoResultException e) {
            transaction.rollback();
            logger.error("No se encontro las IncidenceDamage para la incidence: " + incidence);
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Error al encontrar las IncidenceDamage: ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Método findAllIncidenceDamageByIncidence: ", e);
        }

        return result;
    }

    public Incidence fillFoliosByPagos(String abreviacionFolio) {
        Incidence result = null;
        Transaction transaction = null;
        try {
            logger.info("Search last generated folio..");

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

            String query = "SELECT tap FROM Incidence tap "
                    + "WHERE tap.folio LIKE '" + abreviacionFolio + "%' "
                    + "ORDER BY "
                    + "SUBSTRING_INDEX(tap.folio, '-', 1) DESC, "
                    + "SUBSTRING_INDEX(SUBSTRING_INDEX(tap.folio, '-', -2), '-', -6) DESC ";

            result = (Incidence) session.createQuery(query)
                    .setMaxResults(1)
                    .uniqueResult();

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Search for the last generated folio " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillFoliosByPagos() " + e);
            rollback(transaction);
        }
        return result;
    }

    public boolean addIncidenceEvidencia(IncidenceEvidencia evidencia, User user, boolean save) {
        logger.info("addIncidenceEvidencia");
        boolean success = false;
        Transaction transaction = null;

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

            if (save) {
                evidencia.setId(UUID.randomUUID().toString());
                evidencia.setCreatedBy(user);
                evidencia.setCreatedOn(new Date());
                session.save(evidencia);
                transaction.commit();
                logger.info("Incidence evidencia saved " + evidencia.getId());
            } else {
                evidencia.setLastUpdatedOn(new Date());
                evidencia.setLastUpdatedBy(user);
                session.update(evidencia);
                transaction.commit();
                logger.info("Incidence evidencia updated " + evidencia.getId());
            }

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

    public List<IncidenceEvidencia> findAllIncidenceEvidenciaByIncidence(Incidence incidence) {
        logger.info("findAllIncidenceEvidenciaByIncidence");

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

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

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

            Predicate criterio = (builder.equal(root.get("incidence"), incidence));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            criteria.where(builder.and(criterio, criterio2));
            criteria.orderBy(builder.desc(root.get("createdOn")));

            result = session.createQuery(criteria).getResultList();
            transaction.commit();
        } catch (NoResultException e) {
            transaction.rollback();
            logger.error("No se encontro las IncidenceEvidencia para la incidence: " + incidence);
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Error al encontrar las IncidenceEvidencia: ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Método findAllIncidenceEvidenciaByIncidence: ", e);
        }

        return result;
    }

}
