/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.arrebol.taxiservicios.controller.admin;

import com.arrebol.taxiservicios.controller.connection.ConnectionManager;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.admin.Expense;
import com.arrebol.taxiservicios.model.admin.FinancingCustomer;
import com.arrebol.taxiservicios.model.admin.Taxi;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.arrebol.taxiservicios.model.enums.ExpenseStatusType;
import com.arrebol.taxiservicios.model.stocktaking.ServiceOrderHasProduct;
import com.arrebol.taxiservicios.model.stocktaking.view.HistoryUpdateKm;
import com.arrebol.taxiservicios.model.view.report.PaymentClient;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaDelete;
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 oscarvargas
 */
public class PaymentCustomerController extends ConnectionManager implements Serializable {

    /**
     * 
     * @param starDate
     * @param endDate
     * @return 
     */
    public List<PaymentClient> fillDataTableBetweenDates(Date starDate, Date endDate) {
        logger.info("fillDataTableBetweenDates");

        List<PaymentClient> results = null;
        Transaction transaction = null;

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

            results = session.createQuery("FROM PaymentClient WHERE DATE(createdOn) BETWEEN DATE(:starDate) AND DATE(:endDate) AND activeStatus = 'ENEBLED' ORDER BY createdOn DESC")
                    .setParameter("starDate", starDate)
                    .setParameter("endDate", endDate)
                    .getResultList();

            transaction.commit();
            logger.info("Total of PaymentClient founds " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not load auto complete list of PaymentClient", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillDataTableBetweenDates", e);
        }

        return results;
    }
    
    public List<PaymentClient> fillDataTableDepositPending(String idLocation) {
        logger.info("fillDataTableDepositPending");

        List<PaymentClient> results = null;
        Transaction transaction = null;

        try {
           Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<PaymentClient> query = builder.createQuery(PaymentClient.class);
            Root<PaymentClient> root = query.from(PaymentClient.class);

           
            Predicate pending = builder.equal(root.get("depositStatus"), ExpenseStatusType.PENDING);
            Predicate bankCardNotNull = builder.isNotNull(root.get("bankCard"));

            Predicate locationPredicate = builder.equal(root.get("location"), new Location(idLocation));

            //query.select(builder.construct(Taxes.class, id, amount, description, createdOn, createdByPath, locationPath, activeStatusPath, taxesTypePath));
            query.where(builder.and(
                    pending, bankCardNotNull, locationPredicate
            ));
            query.orderBy(builder.desc(root.get("createdOn")));

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

            transaction.commit();

            logger.info("Total of paymentClient founds " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not load PaymentCllient list", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("fillDataTableDepositPending", e);
        }

        return results;
    }
    
    public boolean autorizarDeposito(String expenseId, User user) {
        logger.info("autorizar");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaUpdate<PaymentClient> update = builder.createCriteriaUpdate(PaymentClient.class);
            Root<PaymentClient> rootUpdate = update.from(PaymentClient.class);

            update.set("depositStatus", ExpenseStatusType.AUTHORIZED);
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", new Date());
            update.where(builder.equal(rootUpdate.get("id"), expenseId));

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

            if (1 == total) {
                transaction.commit();
                success = true;
                logger.info("Sale " + expenseId + " updated");
            } else {
                transaction.rollback();
                logger.error("Error Sale updated total: " + total);
            }
        } catch (HibernateException e) {
            logger.error("Sale can not be updated ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method autorizar() ", e);
            rollback(transaction);
        }
        return success;
    }
    
    public List<PaymentClient> fillDataTableBetweenDatesLocation(Date starDate, Date endDate, String idLocation) {
        logger.info("fillDataTableBetweenDates");

        List<PaymentClient> results = null;
        Transaction transaction = null;

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

            results = session.createQuery("FROM PaymentClient WHERE DATE(createdOn) BETWEEN DATE(:starDate) AND DATE(:endDate) AND "
                    + "activeStatus = 'ENEBLED' AND location.id = :location  AND actionStatus = 'APPROVED' AND paid='ENEBLED'"  
                    + "ORDER BY createdOn DESC")
                    .setParameter("starDate", starDate)
                    .setParameter("endDate", endDate)
                    .setParameter("location", idLocation)
                    .getResultList();

            transaction.commit();
            logger.info("Total of PaymentClient founds " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not load auto complete list of PaymentClient", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillDataTableBetweenDates", e);
        }

        return results;
    }
    
    public boolean deleteById(String paymentId) {
        logger.info("deleteById");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<PaymentClient> update = builder.createCriteriaUpdate(PaymentClient.class);
            Root<PaymentClient> root = update.from(PaymentClient.class);

                update.set("activeStatus",BasicType.DISABLED);
            
                update.where(builder.equal(root.get("id"), paymentId));

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

            
                transaction.commit();
                success = true;
                logger.info("PaymentCliente " + paymentId + " deleted");
            
        } catch (HibernateException e) {
            logger.error("PaymentCliente can not be deleted ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method deleteSanctionById() ", e);
            rollback(transaction);
        }
        return success;
    }
    
    public void updateAdeudoTaxi(Taxi taxi) {
        logger.info("deleteById");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Taxi> update = builder.createCriteriaUpdate(Taxi.class);
            Root<Taxi> root = update.from(Taxi.class);

                update.set("adeudo",taxi.getAdeudo());
            
                update.where(builder.equal(root.get("id"), taxi.getId()));

                session.createQuery(update).executeUpdate();

            
                transaction.commit();
              
            
                logger.info("Adeudo actualizado");
                
        } catch (HibernateException e) {
            logger.error("PaymentCliente can not be deleted ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method deleteSanctionById() ", e);
            rollback(transaction);
        }
        
    }
    
    public void updateExpensePaid(PaymentClient paymentClient) {
        logger.info("deleteById");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Expense> update = builder.createCriteriaUpdate(Expense.class);
            Root<Expense> root = update.from(Expense.class);

                update.set("paid",BasicType.DISABLED);
            
                update.where(builder.equal(root.get("paymentClient"), paymentClient));

                session.createQuery(update).executeUpdate();

            
                transaction.commit();
              
            
                logger.info("Adeudo actualizado");
                
        } catch (HibernateException e) {
            logger.error("PaymentCliente can not be deleted ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method deleteSanctionById() ", e);
            rollback(transaction);
        }
        
    }
    
    public void updateExpenseFinance(PaymentClient paymentClient) {
        logger.info("deleteById");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Expense> update = builder.createCriteriaUpdate(Expense.class);
            Root<Expense> root = update.from(Expense.class);

                update.set("finance",BasicType.DISABLED);
            
                update.where(builder.equal(root.get("paymentClientFinance"), paymentClient));

                session.createQuery(update).executeUpdate();

            
                transaction.commit();
              
            
                logger.info("Adeudo actualizado");
                
        } catch (HibernateException e) {
            logger.error("PaymentCliente can not be deleted ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method deleteSanctionById() ", e);
            rollback(transaction);
        }
        
    }
    
    public void updateServiceOrderHasProductPaid(PaymentClient paymentClient) {
        logger.info("deleteById");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<ServiceOrderHasProduct> update = builder.createCriteriaUpdate(ServiceOrderHasProduct.class);
            Root<ServiceOrderHasProduct> root = update.from(ServiceOrderHasProduct.class);

                update.set("cobrado",BasicType.DISABLED);
            
                update.where(builder.equal(root.get("paymentClient"), paymentClient));

                session.createQuery(update).executeUpdate();

            
                transaction.commit();
              
            
                logger.info("Adeudo actualizado");
                
        } catch (HibernateException e) {
            logger.error("PaymentCliente can not be deleted ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method deleteSanctionById() ", e);
            rollback(transaction);
        }
        
    }
    
    public void updateServiceOrderHasProductFinance(PaymentClient paymentClient) {
        logger.info("deleteById");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<ServiceOrderHasProduct> update = builder.createCriteriaUpdate(ServiceOrderHasProduct.class);
            Root<ServiceOrderHasProduct> root = update.from(ServiceOrderHasProduct.class);

                update.set("financiado",BasicType.DISABLED);
            
                update.where(builder.equal(root.get("paymentClientFinance"), paymentClient));

                session.createQuery(update).executeUpdate();

            
                transaction.commit();
              
            
                logger.info("Adeudo actualizado");
                
        } catch (HibernateException e) {
            logger.error("PaymentCliente can not be deleted ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method deleteSanctionById() ", e);
            rollback(transaction);
        }
        
    }
    
    public FinancingCustomer getFinancingCustomerByPaymentClient(PaymentClient paymentClient){
        

        Transaction transaction = null;
        FinancingCustomer result = null;

        try {
            logger.info("Searching taxi by id..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

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

            Path<String> idPath = root.get("id");
            Path<Double> lastDebitPath = root.get("lastDebit");
            Path<Double> monthDebitPath = root.get("monthDebit");
            Path<Double> increasePath = root.get("increase");
            Path<Double> discountPath = root.get("discount");
            Path<Double> paymentPath = root.get("payment");
            Path<Double> actuallyDebitPath = root.get("actuallyDebit");
            

            criteria.select(
                    builder.construct(FinancingCustomer.class, idPath, lastDebitPath,
                            monthDebitPath, increasePath, discountPath,paymentPath,actuallyDebitPath
                    ));

            criteria.where(builder.equal(root.get("paymentClient"), paymentClient));

            result = session.createQuery(criteria).uniqueResult();

            transaction.commit();
            logger.info("FinancingCustomer founds");
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not load financingCustomer object ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method getFinancingCustomerByPaymentClient of PaymentClient", e);
        }

        return result;
    
    }

    private static final long serialVersionUID = -793156951909596418L;

    final Logger logger = LogManager.getLogger(PaymentCustomerController.class);
    private final float iva = .16f;

    public PaymentCustomerController() {
    }
}
