/*
 * Arrebol Consultancy copyright.
 * 
 * This code belongs to Arrebol Consultancy
 * its use, redistribution or modification are prohibited 
 * without written authorization from Arrebol Consultancy.
 */
package com.arrebol.taxiservicios.controller.admin;

import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.admin.FeeByDriver;
import com.arrebol.taxiservicios.model.admin.Sanction;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.FeeType;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
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 Carlos Janitzio Zavala Lopez <janitzio.zavala@arrebol.com.mx>
 */
@RequestScoped
public class FeeByDriverServiceImpl implements FeeByDriverService {

    @Override
    public boolean updateAllFeesSelected(List<String> selectedFees, FeeType status, User user, String comments, Sanction sanction) {
        logger.info("updateAllFeesSelected");

        boolean success = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaUpdate<FeeByDriver> updateQuery = builder.createCriteriaUpdate(FeeByDriver.class);
            Root<FeeByDriver> root = updateQuery.from(FeeByDriver.class);

            updateQuery.set(root.get("status"), status);
            updateQuery.set(root.get("comment"), comments);
            updateQuery.set(root.get("lastUpdatedBy"), user);
            updateQuery.set(root.get("lastUpdatedOn"), new Date());

            updateQuery.where(root.get("id").in(selectedFees));

            int total = session.createQuery(updateQuery).executeUpdate();

            if (null != sanction && FeeType.PAID.equals(status)) {
                sanction.setActive(false);
                session.save(sanction);
                logger.info("Sanction saved " + sanction);
            }

            transaction.commit();
            logger.info("Total of fees updated " + total);

            success = true;
        } catch (HibernateException e) {
            logger.error("Update all fees selected", e);
            if (null != transaction) {
                transaction.rollback();
            }
        } catch (Exception e) {
            logger.error("Method updateAllFeesSelected()", e);
            if (null != transaction) {
                transaction.rollback();
            }
        }
        return success;
    }

    final Logger logger = LogManager.getLogger(getClass());

    @Override
    public List<FeeByDriver> findAllFeesByDriverAndStatus(Person driver, FeeType status) {
        logger.info("findAllFeesByDriverAndStatus");

        List<FeeByDriver> results = new ArrayList<>();
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<FeeByDriver> query = builder.createQuery(FeeByDriver.class);
            Root<FeeByDriver> root = query.from(FeeByDriver.class);

            Path<String> id = root.get("id");
            Path<Person> person = root.get("driver");
            Path<Date> feeDate = root.get("feeDate");
            Path<Double> amount = root.get("amount");
            Path<String> comment = root.get("comment");

            Predicate equalsToDriver = builder.equal(root.get("driver"), driver);
            Predicate equalsToStatus = builder.equal(root.get("status"), status);

            query.select(
                    builder.construct(FeeByDriver.class,
                            id, person, feeDate, amount, comment
                    ));
            query.where(equalsToDriver, equalsToStatus);
            query.orderBy(builder.asc(root.get("feeDate")));

            results = session.createQuery(query).getResultList();

            transaction.commit();

            logger.info("Total of fees loaded " + results.size());
        } catch (HibernateException e) {
            logger.error("Fees by driver list could not be found", e);
            if (null != transaction) {
                transaction.rollback();
            }
        } catch (Exception e) {
            logger.error("Method findAllFeesByDriverAndStatus()", e);
            if (null != transaction) {
                transaction.rollback();
            }
        }

        return results;
    }
}
