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

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.GenericValidationController;
import com.arrebol.taxiservicios.controller.catalog.ProductBrandController;
import com.arrebol.taxiservicios.controller.catalog.ProductController;
import com.arrebol.taxiservicios.controller.stocktaking.ServiceOrderController;
import com.arrebol.taxiservicios.controller.stocktaking.ServiceOrderSingletonController;
import com.arrebol.taxiservicios.controller.util.DateWrapper;
import com.arrebol.taxiservicios.model.admin.Taxi;
import com.arrebol.taxiservicios.model.catalog.Brand;
import com.arrebol.taxiservicios.model.catalog.Product;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.arrebol.taxiservicios.model.enums.ServiceOrderType;
import com.arrebol.taxiservicios.model.stocktaking.ServiceOrder;
import com.arrebol.taxiservicios.model.stocktaking.ServiceOrderHasProduct;
import com.arrebol.taxiservicios.model.stocktaking.ServiceOrderHasProductId;
import com.arrebol.taxiservicios.services.catalog.ProductService;
import com.arrebol.taxiservicios.wrapper.PersonWrapper;
import com.arrebol.taxiservicios.wrapper.ProductWrapper;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedProperty;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.primefaces.event.RowEditEvent;

/**
 *
 * @author oscarvargas
 */
@Named
@ViewScoped
public class GarageEditBean extends TaxiGenericBean implements Serializable {

    /**
     *
     */
    public void createNewProduct() {
        try {
            if(getGenericController().existCheckStocktakingPending(getLoggedUser().getLocation().getId()))
        {
            showMessage(FacesMessage.SEVERITY_WARN,
                        "Inventario cerrado",
                        "No puedes hacer ningun movimiento al inventario hasta que se termine de cotejar");
            return;
        }
            getNewProduct().setAmount(0d);
            getNewProduct().setQuantity(0);
            getNewProduct().setUtility(0d);
            getNewProduct().setAmount2(0d);
            getNewProduct().setQuantity2(0);
            getNewProduct().setUtility2(0d);
            getNewProduct().setService(BasicType.DISABLED);
            getNewProduct().setHerramienta(BasicType.DISABLED);
            getNewProduct().setActiveStatus(BasicType.ENEBLED);

            if (productCtrl.saveProduct(getNewProduct(), getLoggedUser().getId() ,getBrandId())) {
                LOG.info("createNewProduct");
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("garage.title"),
                        getBundlePropertyFile().getString("invoice.add.new.product.success.desc"));

                setComboProducts(getController().getAllProducts());
            } else {
                LOG.info("Error createNewProduct");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("garage.title"),
                        getBundlePropertyFile().getString("invoice.add.new.product.fail.desc"));
            }
        } catch (Exception e) {
            LOG.error("createNewProduct: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("garage.title"),
                    getBundlePropertyFile().getString("invoice.add.new.product.exception.desc"));
        }

        setNewProduct(null);
        setBrandId("N/A");
    }

    /**
     * Update product list.
     */
    public void updateServiceOrderProducts() {
        LOG.info("updateServiceOrder");
        try {
        if(getGenericController().existCheckStocktakingPending(getLoggedUser().getLocation().getId()))
        {
            showMessage(FacesMessage.SEVERITY_WARN,
                        "Inventario cerrado",
                        "No puedes hacer ningun movimiento al inventario hasta que se termine de cotejar");
            return;
        }
            User user = new User(getLoggedUser().getId(), "");
            getServiceOrderHasProducts().clear();

            getDtTblProducts().stream().map((wrapper) -> {
                ServiceOrderHasProduct sohp = new ServiceOrderHasProduct(
                        new ServiceOrderHasProductId(
                                getServiceOrder().getId(),
                                wrapper.getProductId()
                        )
                );

                if (null == wrapper.getQuantity() || wrapper.getQuantity() <= 0) {
                    throw new NumberFormatException("Quantity is wrong value " + wrapper.getQuantity());
                }
                if (null == wrapper.getName()) {
                    throw new NullPointerException("Description of the project es null");
                }

                sohp.setCreatedBy(user);
                sohp.setCreatedOn(DateWrapper.getTodayMXTime());
                sohp.setQuantity(wrapper.getQuantity());
                sohp.setPrice(wrapper.getPrice().floatValue());
                sohp.setTotal(wrapper.getTotal().floatValue());//Total within IVA
                sohp.setMayoreo(Float.valueOf(wrapper.getUtility()+""));
                sohp.setCobrado(BasicType.DISABLED);
                sohp.setFinanciado(BasicType.DISABLED);
                sohp.setCommercialInvoiceStatus(BasicType.DISABLED);

                return sohp;
            }).forEachOrdered((sohp) -> {
                getServiceOrderHasProducts().add(sohp);
            });

            Double ivaSO = 0d;
            Double subtotalSO = 0d;
            Double totalSO = 0d;

            for (ServiceOrderHasProduct sohp : getServiceOrderHasProducts()) {
                subtotalSO = sohp.getTotal() + subtotalSO;
                ivaSO = (sohp.getTotal() * iva) + ivaSO;
            }

            totalSO = subtotalSO + ivaSO;
            ServiceOrder so = new ServiceOrder(getServiceOrder().getId());

            so.setPendingDate(DateWrapper.getTodayMXTime());
            so.setLastUpdatedBy(user);
            so.setDescription(getServiceOrder().getDescription());
            so.setLastUpdatedOn(DateWrapper.getTodayMXTime());
            so.setSubtotal(subtotalSO.floatValue());
            so.setIva(ivaSO.floatValue());
            so.setTotal(totalSO.floatValue());

            if (getSingletonController().workWithServiceOrder(1, getServiceOrder().getId(), getServiceOrderHasProducts(), so, null, null, null, null, getLoggedUser().getLocation())) {
                //if (getController().updateServiceOrderProducts(orderHasProducts, so)) {
                LOG.info("saveServiceOrder");
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("garage.title"),
                        getBundlePropertyFile().getString("garage.update.order.desc"));
            } else {
                LOG.error("saveServiceOrder");

                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("garage.title"),
                        getBundlePropertyFile().getString("garage.update.order.exception.desc"));
            }
        } catch (NumberFormatException e) {
            LOG.error("saveServiceOrder NumberFormatException: " + e);

            String msg = getBundlePropertyFile().getString("garage.km.exception");

            if (null != e.getMessage() && e.getMessage().contains("Quantity is wrong value")) {
                msg = getBundlePropertyFile().getString("garage.search.null.pointer.exception");
            }

            showMessage(FacesMessage.SEVERITY_ERROR,
                    getBundlePropertyFile().getString("garage.title"), msg);
        } catch (NullPointerException e) {
            LOG.error("saveServiceOrder NullPointerException : " + e);
            showMessage(FacesMessage.SEVERITY_ERROR,
                    getBundlePropertyFile().getString("garage.title"), "Valor no valido");
        } catch (Exception e) {
            LOG.error("saveServiceOrder: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("garage.title"),
                    getBundlePropertyFile().getString("fatal.access.details"));
        }
    }

    /**
     *
     */
    public void deleteSelectedProduct() {
        LOG.info("deleteSelectedProduct");
        try {
            getDtTblProducts().remove(getSelectedProduct());
        } catch (Exception e) {
            LOG.error("deleteSelectedProduct", e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("garage.title"),
                    getBundlePropertyFile().getString("fatal.access.details"));
        }
    }

    /**
     *
     * @param event
     */
    public void onRowEdit(RowEditEvent event) {
        LOG.info("onRowEdit");
        try {
            ProductWrapper product = (ProductWrapper) event.getObject();

            if (null == product.getQuantity() || product.getQuantity() <= 0) {
                throw new NumberFormatException("Quantity is wrong value " + product.getQuantity());
            }
            if (null == product.getProductId()) {
                throw new NullPointerException("Description of the project es null");
            }

            getComboProducts().forEach((Product comboPrdct) -> {
                if (product.getProductId().equals(comboPrdct.getId())) {
                    if(getLoggedUser().getLocation().getId().equalsIgnoreCase("4d0859be-e31a-4acb-a690-2a5c2cb027a7"))
                    {
                       product.wrapper(comboPrdct, comboPrdct.getCode(), comboPrdct.getBrand().getName());
                    }
                    else
                    {
                        product.wrapper(comboPrdct, comboPrdct.getCode(), comboPrdct.getBrand().getName(), true);
                    }
                }
            });
        } catch (NumberFormatException e) {
            LOG.error("onRowEdit ", e);
            showMessage(FacesMessage.SEVERITY_ERROR,
                    getBundlePropertyFile().getString("garage.title"),
                    getBundlePropertyFile().getString("garage.search.number.format.exception"));
        } catch (NullPointerException e) {
            LOG.error("onRowEdit ", e);
            showMessage(FacesMessage.SEVERITY_ERROR,
                    getBundlePropertyFile().getString("garage.title"),
                    getBundlePropertyFile().getString("garage.search.null.pointer.exception"));
        } catch (Exception e) {
            LOG.error("onRowEdit", e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("garage.title"),
                    getBundlePropertyFile().getString("garage.search.exception.desc"));
        }
    }

    public void onRowCancel(RowEditEvent event) {

    }

    /**
     *
     */
    public void onAddNew() {
        getDtTblProducts().add(new ProductWrapper(UUID.randomUUID().toString()));

        LOG.info(getDtTblProducts());
    }

    private static final long serialVersionUID = 6449604006171989418L;

    final Logger LOG = LogManager.getLogger(GarageEditBean.class);

    private ServiceOrderController controller;
    private ServiceOrderSingletonController singletonController;
    private GenericValidationController genericController;
    private ServiceOrder serviceOrder;
    private PersonWrapper client;
    private PersonWrapper driver;
    private List<Product> comboProducts;
    private List<ProductWrapper> dtTblProducts;
    private ProductWrapper selectedProduct;
    private boolean hasProduct;
    private List<ServiceOrderHasProduct> serviceOrderHasProducts;
    private boolean aproved;
    private Product newProduct;
    private String brandId;
    private boolean paseTaller;
    private boolean tallerExterno;

    private ProductController productCtrl;
    private ProductBrandController brandCtrl;

    @PostConstruct
    public void init() {
        LOG.info("init");
        try {
            String id = externalContext().getRequestParameterMap().get("id");

            loadBundlePropertyFile();
            productCtrl = new ProductController();
            brandCtrl = new ProductBrandController();
            setController(new ServiceOrderController());
            setGenericController(new GenericValidationController());
            setSingletonController(ServiceOrderSingletonController.getInstance());
            setServiceOrder(getController().loadServiceOrderById(id));

            if (null != getServiceOrder()) {
                setClient(wraperPerson(getServiceOrder().getTaxi().getCustomer()));

                if (null != getServiceOrder().getTaxi().getDriver()) {
                    setDriver(wraperPerson(getServiceOrder().getTaxi().getDriver()));
                } else {
                    setDriver(new PersonWrapper());
                }

                if (ServiceOrderType.PENDING.equals(getServiceOrder().getServiceOrderType())) {
                    setComboProducts(getController().getAllProducts());

                    List<ServiceOrderHasProduct> hasProducts = getController().findAllProductByOrderId(id);

                    hasProducts.forEach(orderHasProduct -> getDtTblProducts().add(new ProductWrapper(orderHasProduct)));
                } else {
                    setAproved(true);
                    showMessage(FacesMessage.SEVERITY_INFO,
                            getBundlePropertyFile().getString("garage.title"),
                            getBundlePropertyFile().getString("garage.already.approved.desc"));
                }
                
                if(ServiceOrderType.PASE_TALLER.equals(getServiceOrder().getServiceOrderType()))
                {
                    setPaseTaller(true);
                }
                else
                {
                    setPaseTaller(false);
                }
                
                if(getServiceOrder().getTallerExterno().equals(BasicType.ENEBLED))
                {
                    setTallerExterno(true);
                }
                else
                {
                    setTallerExterno(false);
                }
            } else {
                setServiceOrder(new ServiceOrder(new Taxi()));
                setClient(new PersonWrapper());
                setDriver(new PersonWrapper());

                setAproved(true);

                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("garage.title"),
                        getBundlePropertyFile().getString("garage.not.exist.desc"));
            }
        } catch (Exception e) {
            LOG.error("GarageEditBean init", e);
        }
    }

    public ProductController getProductCtrl() {
        return productCtrl;
    }

    public void setProductCtrl(ProductController productCtrl) {
        this.productCtrl = productCtrl;
    }

    public ProductBrandController getBrandCtrl() {
        return brandCtrl;
    }

    public void setBrandCtrl(ProductBrandController brandCtrl) {
        this.brandCtrl = brandCtrl;
    }

    public GenericValidationController getGenericController() {
        return genericController;
    }

    public void setGenericController(GenericValidationController genericController) {
        this.genericController = genericController;
    }

    public boolean isPaseTaller() {
        return paseTaller;
    }

    public void setPaseTaller(boolean paseTaller) {
        this.paseTaller = paseTaller;
    }

    public boolean isTallerExterno() {
        return tallerExterno;
    }

    public void setTallerExterno(boolean tallerExterno) {
        this.tallerExterno = tallerExterno;
    }

    public ServiceOrderController getController() {
        return controller;
    }

    public void setController(ServiceOrderController controller) {
        this.controller = controller;
    }

    public ServiceOrderSingletonController getSingletonController() {
        return singletonController;
    }

    public void setSingletonController(ServiceOrderSingletonController singletonController) {
        this.singletonController = singletonController;
    }

    public ServiceOrder getServiceOrder() {
        return serviceOrder;
    }

    public void setServiceOrder(ServiceOrder serviceOrder) {
        this.serviceOrder = serviceOrder;
    }

    public PersonWrapper getClient() {
        if (null == client) {
            client = new PersonWrapper();
        }
        return client;
    }

    public void setClient(PersonWrapper client) {
        this.client = client;
    }

    public PersonWrapper getDriver() {
        if (null == driver) {
            driver = new PersonWrapper();
        }
        return driver;
    }

    public void setDriver(PersonWrapper driver) {
        this.driver = driver;
    }

    public List<Product> getComboProducts() {
        if (null == comboProducts) {
            comboProducts = new ArrayList<Product>();
        }
        return comboProducts;
    }

    public void setComboProducts(List<Product> comboProducts) {
        this.comboProducts = comboProducts;
    }

    public List<ProductWrapper> getDtTblProducts() {
        if (null == dtTblProducts) {
            dtTblProducts = new ArrayList<ProductWrapper>();
        }
        return dtTblProducts;
    }

    public void setDtTblProducts(List<ProductWrapper> dtTblProducts) {
        this.dtTblProducts = dtTblProducts;
    }

    public ProductWrapper getSelectedProduct() {
        return selectedProduct;
    }

    public void setSelectedProduct(ProductWrapper selectedProduct) {
        this.selectedProduct = selectedProduct;
    }

    public boolean isHasProduct() {
        return hasProduct;
    }

    public void setHasProduct(boolean hasProduct) {
        this.hasProduct = hasProduct;
    }

    public List<ServiceOrderHasProduct> getServiceOrderHasProducts() {
        if (null == serviceOrderHasProducts) {
            serviceOrderHasProducts = new ArrayList<ServiceOrderHasProduct>();
        }
        return serviceOrderHasProducts;
    }

    public void setServiceOrderHasProducts(List<ServiceOrderHasProduct> serviceOrderHasProducts) {
        this.serviceOrderHasProducts = serviceOrderHasProducts;
    }

    public boolean isAproved() {
        return aproved;
    }

    public void setAproved(boolean aproved) {
        this.aproved = aproved;
    }

    public Product getNewProduct() {
        if (null == newProduct) {
            newProduct = new Product();
        }

        return newProduct;
    }

    public void setNewProduct(Product newProduct) {
        this.newProduct = newProduct;
    }

    public List<Brand> getBrandes() {
        return brandCtrl.fillProductBrandComboBox();
    }

    public String getBrandId() {
        return brandId;
    }

    public void setBrandId(String brandId) {
        this.brandId = brandId;
    }
}
