/*
 * 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.stocktaking;

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.catalog.Product;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.stocktaking.Invoice;
import com.arrebol.taxiservicios.model.stocktaking.InvoiceHasProduct;
import com.arrebol.taxiservicios.model.stocktaking.InvoiceHasProductId;
import com.arrebol.taxiservicios.model.stocktaking.ReturnInvoice;
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.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 Oscar
 */
public class ReturnInvoiceController extends ConnectionManager implements Serializable {
    
    public List<InvoiceHasProduct> findAllProductByInvoiceId(String id) {
        logger.info("findAllProductByInvoiceId");

        List<InvoiceHasProduct> list = null;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<InvoiceHasProduct> query = builder.createQuery(InvoiceHasProduct.class);

            Root<InvoiceHasProduct> root = query.from(InvoiceHasProduct.class);

            Path<InvoiceHasProductId> sohpId = root.get("id");
            Path<Product> product = root.get("product");
            Path<Integer> quantity = root.get("quantity");
            Path<Float> price = root.get("priceMenudeo");
            Path<User> usuario = root.get("createdBy");

            query.select(builder.construct(InvoiceHasProduct.class,
                    sohpId, product, price, quantity, usuario));

            query.where(builder.equal(root.get("invoice"), new Invoice(id)));

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

            transaction.commit();
            logger.info("Load all products by Invoice");
        } catch (HibernateException e) {
            logger.error("HibernateException findAllProductByInvoiceId()", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method findAllProductByInvoiceId() ", e);
            rollback(transaction);
        }
        return list;
    }
    
    public List<ReturnInvoice> fillDataTableBetweenDates(Date starDate, Date endDate, Location location) {
        logger.info("fillDataTableBetweenDates");

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

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

            results = session.createQuery("FROM ReturnInvoice WHERE (DATE(createdOn) BETWEEN DATE(:starDate) AND DATE(:endDate)) AND "
                    + "location.id = :location ORDER BY createdOn DESC")
                    .setParameter("starDate", starDate)
                    .setParameter("endDate", endDate)
                    .setParameter("location", location.getId())
                    .getResultList();

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

        return results;
    }
    
    public List<Invoice> fillInvoiceByLocation(Location location) {
        logger.info("fillInvoiceByLocation");

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

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

            results = session.createQuery("FROM Invoice WHERE location.id = :location ORDER BY createdOn DESC")
                    .setParameter("location", location.getId())
                    .getResultList();

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

        return results;
    }
    
    public List<InvoiceHasProduct> getProductsByInvoice(Invoice invoice) {
        logger.info("getProductsByInvoice");

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

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

            results = session.createQuery("FROM InvoiceHasProduct WHERE invoice.id = :invoice")
                    .setParameter("invoice", invoice.getId())
                    .getResultList();

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

        return results;
    }
    
    public Invoice findInvoiceById(String id) {
        Invoice result = null;
        Transaction transaction = null;

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

            result = session.find(Invoice.class, id);

            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not found invoice by id", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method findInvoiceById", e);
        }

        return result;
    }

    public boolean saveReturnInvoice(ReturnInvoice returnInvoice, List<InvoiceHasProduct> invoiceHasProduct) {
        logger.info("saveReturnInvoice");

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

            session.save(returnInvoice);
            
            //Update product details from invoice.
            invoiceHasProduct.forEach((prdct) -> {
                Product productFromDB = session.get(Product.class, prdct.getProduct().getId());
                int totalQuantity = 0;
                if(returnInvoice.getLocation().getId().equalsIgnoreCase("4d0859be-e31a-4acb-a690-2a5c2cb027a7"))
                {
                   totalQuantity =productFromDB.getQuantity() -  prdct.getQuantity();
                   productFromDB.setQuantity(totalQuantity);
                }
                else
                {
                    totalQuantity = productFromDB.getQuantity2() - prdct.getQuantity();
                    productFromDB.setQuantity2(totalQuantity);
                }
                
                productFromDB.setLastUpdatedBy(prdct.getLastUpdatedBy());
                productFromDB.setLastUpdatedOn(new Date());

                session.save(productFromDB);
            });
            transaction.commit();

            success = true;
        } catch (HibernateException e) {
            logger.error("Invoice can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method saveInvoice() ", e);
            rollback(transaction);
        }
        return success;
    }
    final Logger logger = LogManager.getLogger(ReturnInvoiceController.class);
    private final float iva = .16f;

    public ReturnInvoiceController() {
    }
    
}
