/*
 * 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.Brand;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.catalog.Product;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.arrebol.taxiservicios.model.stocktaking.TransferStocktaking;
import com.arrebol.taxiservicios.model.stocktaking.TransferStocktakingHasProduct;
import com.arrebol.taxiservicios.model.stocktaking.TransferStocktakingHasProductBk;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.UUID;
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 TransferStocktakingController extends ConnectionManager implements Serializable {
    
    public List<Product> fillProductsComboBox() {

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

        try {
            logger.info("Searching all products to select..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

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

            Path<String> idPath = root.get("id");
            Path<String> namePath = root.get("name");
            Path<String> codePath = root.get("code");
            Path<Brand> brandPath = root.get("brand");
            Path<Double> amount = root.get("amount");
            Path<Integer> quantity = root.get("quantity");

            criteria.select(
                    builder.construct(Product.class, idPath, namePath, codePath, brandPath, amount, quantity
                    ));
            criteria.where(builder.equal(root.get("activeStatus"), BasicType.ENEBLED));

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

            logger.info("Total of products found for ComboBox: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not load list of products for ComboBox ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillProductsComboBox for Invoice", e);
        }

        return result;
    }
    
    public List<Location> fillLocationComboBox() {
        logger.info("Searching all locations to select..");

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

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

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

            Path<String> idPath = root.get("id");
            Path<String> namePath = root.get("name");

            criteria.select(
                    builder.construct(Location.class, idPath, namePath
                    ));

            criteria.where(builder.equal(root.get("active"), Boolean.TRUE));

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

            logger.info("Total of locations found for ComboBox: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not load list of locations for ComboBox ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillLocationComboBox for Transfer", e);
        }

        return result;
    }
    
    public List<TransferStocktaking> fillDataTableBetweenDates(Date starDate, Date endDate, Location location) {
        logger.info("fillDataTableBetweenDates");

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

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

            results = session.createQuery("FROM TransferStocktaking 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 TransferStocktaking founds in auto complete search " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not load auto complete list of TransferStocktaking", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method fillDataTableBetweenDates", e);
        }

        return results;
    }
    
    public TransferStocktaking findById(String id) {
        TransferStocktaking result = null;
        Transaction transaction = null;

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

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

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

        return result;
    }
    
    public boolean save(TransferStocktaking transferStocktaking, List<TransferStocktakingHasProduct> products) {
        logger.info("save");

        boolean success = false;
        Transaction transaction = null;

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

            session.save(transferStocktaking);
            logger.info("transferStocktaking saved " + transferStocktaking.getId());

            products.forEach((TransferStocktakingHasProduct transferStocktakingProduct) -> {
                session.save(transferStocktakingProduct);
            });

            //Backup product details before to update stocktaking.
      /*      products.forEach((TransferStocktakingHasProduct prdct) -> {
                Product productToBackup = session.get(Product.class, prdct.getId().getProductId());

                TransferStocktakingHasProductBk backup = new TransferStocktakingHasProductBk(
                        UUID.randomUUID().toString(),
                        transferStocktaking,
                        new Product(prdct.getId().getProductId()),
                        productToBackup.getQuantity(),
                        prdct.getCreatedBy(),
                        new Date());

                session.save(backup);
            });*/

            logger.info("Backup product details: " + products.size());

            //Update product details from invoice.
            products.forEach((prdct) -> {
                Product productFromDB = session.get(Product.class, prdct.getId().getProductId());
                int totalQuantityIn = 0;
                int totalQuantityOut = 0;
                if(transferStocktaking.getLocation().getId().equalsIgnoreCase("4d0859be-e31a-4acb-a690-2a5c2cb027a7"))
                {
                   totalQuantityIn = prdct.getQuantity() + productFromDB.getQuantity2();
                   totalQuantityOut = productFromDB.getQuantity() - prdct.getQuantity();
                   productFromDB.setQuantity2(totalQuantityIn);
                   productFromDB.setQuantity(totalQuantityOut);
                   productFromDB.setAmount2((double) prdct.getPrice());
                }
                else
                {
                    totalQuantityIn = prdct.getQuantity() + productFromDB.getQuantity();
                    totalQuantityOut = prdct.getQuantity() - productFromDB.getQuantity2();
                    productFromDB.setQuantity2(totalQuantityOut);
                    productFromDB.setQuantity(totalQuantityIn);
                    productFromDB.setAmount((double) prdct.getPrice());
                }

                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(TransferStocktakingController.class);

    public TransferStocktakingController() {
    }
    
}
