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

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.GenericValidationController;
import com.arrebol.taxiservicios.controller.admin.TaxiController;
import com.arrebol.taxiservicios.controller.catalog.BankCardController;
import com.arrebol.taxiservicios.controller.catalog.LocationController;
import com.arrebol.taxiservicios.controller.sp.report.ReportCustomerPayController;
import com.arrebol.taxiservicios.model.admin.Expense;
import com.arrebol.taxiservicios.model.admin.FinancingCustomer;
import com.arrebol.taxiservicios.model.admin.ReleaseResource;
import com.arrebol.taxiservicios.model.admin.Sale;
import com.arrebol.taxiservicios.model.admin.Taxi;
import com.arrebol.taxiservicios.model.catalog.BankCard;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.ActionStatus;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.arrebol.taxiservicios.model.enums.ExpenseStatusType;
import com.arrebol.taxiservicios.model.sp.report.ReportCustomerPay;
import com.arrebol.taxiservicios.model.stocktaking.Invoice;
import com.arrebol.taxiservicios.model.stocktaking.InvoiceHasProduct;
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.model.stocktaking.view.KardexOutStocktakingView;
import com.arrebol.taxiservicios.model.view.report.PaymentClient;
import java.io.File;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import static java.util.Calendar.HOUR_OF_DAY;
import static java.util.Calendar.MILLISECOND;
import static java.util.Calendar.MINUTE;
import static java.util.Calendar.SECOND;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.view.JasperViewer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.hql.internal.ast.DetailedSemanticException;
import org.primefaces.PrimeFaces;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;

/**
 *
 * @author Janitzio Zavala López.
 */
@Named
@ViewScoped
public class ReportCustomerPayBean extends TaxiGenericBean implements Serializable {

    public void calculateTotal() {
        try {
            setSeguroVentasDinero(getSeguroVentas() * getPagoDiario());
            getPaymentClient().setTotalPayment((getPaymentClient().getAmountToPay()
                    + getPaymentClient().getIncrease()
                    + getSeguroVentasDinero())
                    - getPaymentClient().getDiscount()
                    - getFinancingCustomer().getPayment() - getTotalContrato() - getTotalCobro()
                    - getIncrementoPagos() + getDescuentoPagos());
        } catch (Exception e) {
            LOG.error("calculateTotal", e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Pago al cliente", "Error calculando el total");
        }
    }
    

    public void calculateTotalFinancing() {
        if(selectedDetailProductOrderList.size()>0 && selectedDetailProductOrderFinanceList.size()>0){
            
            selectedDetailProductOrderFinanceList.stream().filter(kardex -> (selectedDetailProductOrderList.contains(kardex))).forEachOrdered(kardex -> {
                selectedDetailProductOrderList.remove(kardex);
            });
        
        }
       
        
        try {
            getFinancingCustomer().setActuallyDebit(
                    getCalculateExpensePrice()
                    + getFinanciamiento()
                    + getCalculatePrice()
                    + getFinancingCustomer().getIncrease()
                    - getFinancingCustomer().getDiscount()
                    - getFinancingCustomer().getPayment()
            );
            
            setTotalCobro(getCalculatePriceCobrar());
            calculateTotal();
            if(getPaymentClient().getTotalPayment()==null){
                getPaymentClient().setTotalPayment(0D);
            }
            
            getPaymentClient().setTotalPayment(getPaymentClient().getTotalPayment());

            PrimeFaces.current().ajax().update("tabMain:PaymentClientAddForm:totalDifferenceFinancing");
            
        } catch (Exception e) {
            LOG.error("calculateTotalFinancing", e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Pago al cliente", "Error calculando el total financiado");
        }
    }
    
    public void calculateTotalFinancingGastos() {
        if(selectedExpensesToPay.size()>0 && selectedExpensesToFinance.size()>0){
            
            selectedExpensesToFinance.stream().filter(kardex -> (selectedExpensesToPay.contains(kardex))).forEachOrdered(kardex -> {
                selectedExpensesToPay.remove(kardex);
            });
        
        }
       
        
        try {
            getFinancingCustomer().setActuallyDebit(
                    getCalculateExpensePrice()
                    + getFinanciamiento()
                    + getCalculatePrice()
                    + getFinancingCustomer().getIncrease()
                    - getFinancingCustomer().getDiscount()
                    - getFinancingCustomer().getPayment()
            );
            
            setTotalCobro(getCalculatePriceCobrar());
            calculateTotal();
            if(getPaymentClient().getTotalPayment()==null){
                getPaymentClient().setTotalPayment(0D);
            }
            getPaymentClient().setTotalPayment(getPaymentClient().getTotalPayment());

            PrimeFaces.current().ajax().update("tabMain:PaymentClientAddForm:totalDifferenceFinancing");
            
        } catch (Exception e) {
            LOG.error("calculateTotalFinancing", e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Pago al cliente", "Error calculando el total financiado");
        }
    }
    
    public void calculateTotalFinancingCobro() {
        if(selectedDetailProductOrderList.size()>0 && selectedDetailProductOrderFinanceList.size()>0){
            
            selectedDetailProductOrderList.stream().filter(kardex -> (selectedDetailProductOrderFinanceList.contains(kardex))).forEachOrdered(kardex -> {
                selectedDetailProductOrderFinanceList.remove(kardex);
            });
        
        }
       
        
        try {
            getFinancingCustomer().setActuallyDebit(
                    getCalculateExpensePrice()
                    + getFinanciamiento()
                    + getCalculatePrice()
                    + getFinancingCustomer().getIncrease()
                    - getFinancingCustomer().getDiscount()
                    - getFinancingCustomer().getPayment()
            );
            
            setTotalCobro(getCalculatePriceCobrar());
            calculateTotal();
            getPaymentClient().setTotalPayment(getPaymentClient().getTotalPayment());

            PrimeFaces.current().ajax().update("tabMain:PaymentClientAddForm:totalDifferenceFinancing");
            
        } catch (Exception e) {
            LOG.error("calculateTotalFinancing", e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Pago al cliente", "Error calculando el total cobrado");
        }
    }
    
    public void calculateTotalFinancingCobroGastos() {
        if(selectedExpensesToPay.size()>0 && selectedExpensesToFinance.size()>0){
            
            selectedExpensesToPay.stream().filter(kardex -> (selectedExpensesToFinance.contains(kardex))).forEachOrdered(kardex -> {
                selectedExpensesToFinance.remove(kardex);
            });
        
        }
       
        
        try {
            getFinancingCustomer().setActuallyDebit(
                    getCalculateExpensePrice()
                    + getFinanciamiento()
                    + getCalculatePrice()
                    + getFinancingCustomer().getIncrease()
                    - getFinancingCustomer().getDiscount()
                    - getFinancingCustomer().getPayment()
            );
            
            setTotalCobro(getCalculatePriceCobrar());
            calculateTotal();
            getPaymentClient().setTotalPayment(getPaymentClient().getTotalPayment());

            PrimeFaces.current().ajax().update("tabMain:PaymentClientAddForm:totalDifferenceFinancing");
            
        } catch (Exception e) {
            LOG.error("calculateTotalFinancing", e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Pago al cliente", "Error calculando el total cobrado");
        }
    }

    public void calculateTotalContrato() {
        try {
            setTotalContrato((getContrato()
                    + getIncreaseContrato())
                    - getDiscountContrato());
        } catch (Exception e) {
            LOG.error("calculateTotalContrato", e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Pago al cliente", "Error calculando el total del contrato");
        }
    }

    public void addRow() {
        try {
            if (idTaxi == null || idTaxi.isEmpty()) {
                showMessage(FacesMessage.SEVERITY_ERROR,
                        "Advertencia",
                        "Debes seleccionar un vehículo");
                return;
            }
            if (getGenericController().existClosingDayByCreatedOn(new Date(), getLoggedUser())) {
                showMessage(FacesMessage.SEVERITY_WARN,
                        "Error",
                        "No se puede hacer ninguna acción si existe un corte del día");
                return;
            }
            if (getGenericController().existStableGeneralBoxByCurdate(getLoggedUser())) {
                showMessage(FacesMessage.SEVERITY_WARN,
                        "Dia cerrado",
                        "No se pueden eliminar más registros porque ya existe un cuadre de caja chica del día");
                return;
            }
            getPaymentClient().setId(UUID.randomUUID().toString());
            
            getPaymentClient().setActiveStatus(BasicType.ENEBLED);
            getPaymentClient().setCreatedBy(getLoggedUser());
            getPaymentClient().setCreatedOn(new Date());
            getPaymentClient().setTaxi(new Taxi(idTaxi));
            getPaymentClient().setDiasSeguroVentas(seguroVentas);
            getPaymentClient().setPagoSeguroVentas(seguroVentasDinero);
            getPaymentClient().setTotalContrato(getContrato());
            getPaymentClient().setIncrementoContrato(getIncreaseContrato());
            getPaymentClient().setDescuentoContrato(getDiscountContrato());
            getPaymentClient().setAbonoAdeudo(getFinancingCustomer().getPayment());
            getPaymentClient().setLocationSend(new Location(locationId));
            getPaymentClient().setAmountToCharge(totalCobro);
            getPaymentClient().setLocation(getLoggedUser().getLocation());
            if(locationId.equalsIgnoreCase(getLoggedUser().getLocation().getId())){
                    getPaymentClient().setPaid(BasicType.ENEBLED);
                    getPaymentClient().setActionStatus(ActionStatus.APPROVED);
                }
                else
                {
                    getPaymentClient().setPaid(BasicType.DISABLED);
                    getPaymentClient().setActionStatus(ActionStatus.PENDING);
                }
            getPaymentClient().setDescuentoPago(descuentoPagos);
            getPaymentClient().setIncrementoPago(incrementoPagos);
            getPaymentClient().setIncrementoPagoComentario(comentariosIncrementoPago);
            getPaymentClient().setDescuentoPagoComentario(comentariosDescuentoPago);
            
            if(isDeposit()){
                getPaymentClient().setDepositStatus(ExpenseStatusType.PENDING);
                getPaymentClient().setBankCard(new BankCard(getBankCardId()));
            
            }else{
                getPaymentClient().setDepositStatus(ExpenseStatusType.AUTHORIZED);
            }

            Calendar start = Calendar.getInstance();
            Calendar end = Calendar.getInstance();

            start.setTime(getStartDate());
            start.set(Calendar.HOUR_OF_DAY, 7);
            start.set(Calendar.MINUTE, 30);
            start.set(Calendar.SECOND, 0);

            end.setTime(null == getEndDate() ? getToday() : getEndDate());
            end.set(Calendar.HOUR_OF_DAY, 23);
            end.set(Calendar.MINUTE, 59);
            end.set(Calendar.SECOND, 59);

            getPaymentClient().setInitDate(start.getTime());
            getPaymentClient().setEndDate(end.getTime());

            if (getController().savePaymentClient(getPaymentClient())) {
                showMessage(FacesMessage.SEVERITY_INFO,
                        "Pago al cliente",
                        "Se agregó correctamente");
            }

            //if (getFinancingCustomer().getPayment() > 0D) {
            getFinancingCustomer().setId(UUID.randomUUID().toString());
            getFinancingCustomer().setActive(Boolean.TRUE);
            getFinancingCustomer().setActiveStatus(BasicType.ENEBLED);
            getFinancingCustomer().setCreatedBy(getLoggedUser());
            getFinancingCustomer().setCreatedOn(new Date());
            getFinancingCustomer().setLastDebit(financiamiento);
            getFinancingCustomer().setMonthDebit(getCalculateExpensePrice() + getCalculatePrice());
            getFinancingCustomer().setTaxi(new Taxi(idTaxi));
            getFinancingCustomer().setPaymentClient(getPaymentClient());
            

            if (getController().saveFinancingClient(getFinancingCustomer())) {
                showMessage(FacesMessage.SEVERITY_INFO,
                        "Abono al adeudo",
                        "Se agregó correctamente");

                Taxi taxiTemp = getController().getTaxiById(idTaxi);
                taxiTemp.setAdeudo((float) getFinancingCustomer().getActuallyDebit());
                getController().updateTaxiById(taxiTemp);
            }
            //}

            financingCustomer = new FinancingCustomer();
            getFinancingCustomer().setActuallyDebit(0D);
            getFinancingCustomer().setDiscount(0D);
            getFinancingCustomer().setIncrease(0D);
            getFinancingCustomer().setLastDebit(0D);
            getFinancingCustomer().setMonthDebit(0D);
            getFinancingCustomer().setPayment(0D);
            setFinanciamiento(0F);
            setAdeudoMes(0F);

            setContrato(0F);
            setTotalContrato(0F);
            setDiscountContrato(0F);
            setIncreaseContrato(0F);
            
            

            //Cobrado
            getSelectedDetailProductOrderList().stream().map(kardexOut -> {
                String prod = kardexOut.getProductId();
                String serv = kardexOut.getServiceId();
                ServiceOrderHasProductId id = new ServiceOrderHasProductId(serv, prod,getPaymentClient(),new Date(),getLoggedUser(),new Date(),getLoggedUser());
                return id;
            }).forEachOrdered(id -> {
                getController().editServicesHasProduct(id);//TODO pregutnar si deberí pasarcomo ENEBLED el status de cobrado
            });
            
            //Financiado
            getSelectedDetailProductOrderFinanceList().stream().map(kardexOut -> {
                String prod = kardexOut.getProductId();
                String serv = kardexOut.getServiceId();
                ServiceOrderHasProductId id = new ServiceOrderHasProductId(serv, prod,getPaymentClient(),new Date(),getLoggedUser(),new Date(),getLoggedUser());
                return id;
            }).forEachOrdered(id -> {
                getController().editServicesHasProductFinance(id);//TODO pregutnar si deberí pasarcomo ENEBLED el status de cobrado
            });
            
            //Pago de gastos
            getSelectedExpensesToPay().forEach(expenseToPayEdit ->{
                expenseToPayEdit.setPaymentClient(getPaymentClient());
                expenseToPayEdit.setPaymentDate(getPaymentClient().getCreatedOn());
                getController().editExpenseToPay(expenseToPayEdit);
                
            });
          
            //Financiamento de gastos
            getSelectedExpensesToFinance().forEach(expenseToFinanceEdit ->{
                expenseToFinanceEdit.setPaymentClientFinance(getPaymentClient());
                expenseToFinanceEdit.setFinanceDate(getPaymentClient().getCreatedOn());
                getController().editExpenseToFinance(expenseToFinanceEdit);
                
            });
           
            paymentClient = new PaymentClient();
            getPaymentClient().setAmountToPay(0D);
            getPaymentClient().setIncrease(0D);
            getPaymentClient().setDiscount(0D);
            
            setDetailProductOrder(getController().fillProductsDetailByOrderServices(idTaxi, start.getTime(), end.getTime()));
            setDetailProductOrderFinancing(getController().fillProductsDetailByOrderServicesFinancing(idTaxi, start.getTime(), end.getTime()));
            setExpenseToPay(getController().fillExpenseDatatableLeftJoinToPay(idTaxi, start.getTime(), end.getTime()));
            setExpenseToFinance(getController().fillExpenseDatatableLeftJoinToFinance(idTaxi, start.getTime(), end.getTime()));
            
            getSelectedDetailProductOrderList().clear();
            getSelectedDetailProductOrderFinanceList().clear();
            getSelectedExpensesToPay().clear();
            getSelectedExpensesToFinance().clear();

            
            /*
            if (getCopySelectedProducts() != null && !getCopySelectedProducts().isEmpty()) {
                getSelectedDetailProductOrderList().stream().map(kardexOut -> {
                    String prod = kardexOut.getProductId();
                    String serv = kardexOut.getServiceId();
                    ServiceOrderHasProductId id = new ServiceOrderHasProductId(serv, prod);
                    return id;
                }).forEachOrdered(id -> {
                    getController().editServicesHasProduct(id);
                });
            }
             */
        } catch (Exception e) {
            LOG.error("addRow", e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Pago al cliente", "Error, por favor verifica los datos y reportalo al equipo de soporte");
        }
    }
    
    
     public void createPDF() {
        try {
            if (idTaxi == null || idTaxi.isEmpty()) {
                showMessage(FacesMessage.SEVERITY_ERROR,
                        "Advertencia",
                        "Debes seleccionar un vehículo");
                return;
            }
            if (getGenericController().existClosingDayByCreatedOn(new Date(), getLoggedUser())) {
                showMessage(FacesMessage.SEVERITY_WARN,
                        "Error",
                        "No se puede hacer ninguna acción si existe un corte del día");
                return;
            }
           if (getGenericController().existStableGeneralBoxByCurdate(getLoggedUser())) {
                showMessage(FacesMessage.SEVERITY_WARN,
                        "Dia cerrado",
                        "No se pueden eliminar más registros porque ya existe un cuadre de caja chica del día");
                return;
            }
            //getPaymentClient().setId(UUID.randomUUID().toString());
            
            getPaymentClient().setActiveStatus(BasicType.ENEBLED);
            getPaymentClient().setCreatedBy(getLoggedUser());
            getPaymentClient().setCreatedOn(new Date());
            getPaymentClient().setTaxi(new Taxi(idTaxi));
            getPaymentClient().setDiasSeguroVentas(seguroVentas);
            getPaymentClient().setPagoSeguroVentas(seguroVentasDinero);
            getPaymentClient().setTotalContrato(getContrato());
            getPaymentClient().setIncrementoContrato(getIncreaseContrato());
            getPaymentClient().setDescuentoContrato(getDiscountContrato());
            getPaymentClient().setAbonoAdeudo(getFinancingCustomer().getPayment());
            getPaymentClient().setLocationSend(new Location(locationId));
            getPaymentClient().setAmountToCharge(totalCobro);
            getPaymentClient().setLocation(getLoggedUser().getLocation());
            if(locationId.equalsIgnoreCase(getLoggedUser().getLocation().getId())){
                    getPaymentClient().setPaid(BasicType.ENEBLED);
                    getPaymentClient().setActionStatus(ActionStatus.APPROVED);
                }
                else
                {
                    getPaymentClient().setPaid(BasicType.DISABLED);
                    getPaymentClient().setActionStatus(ActionStatus.PENDING);
                }

            Calendar start = Calendar.getInstance();
            Calendar end = Calendar.getInstance();

            start.setTime(getStartDate());
            start.set(Calendar.HOUR_OF_DAY, 7);
            start.set(Calendar.MINUTE, 30);
            start.set(Calendar.SECOND, 0);

            end.setTime(null == getEndDate() ? getToday() : getEndDate());
            end.set(Calendar.HOUR_OF_DAY, 23);
            end.set(Calendar.MINUTE, 59);
            end.set(Calendar.SECOND, 59);

            getPaymentClient().setInitDate(start.getTime());
            getPaymentClient().setEndDate(end.getTime());

            String filePath= FacesContext.getCurrentInstance().getExternalContext().getRealPath("/resources/jasper-reports/reportPaymentClient.jrxml");
            File file = new File(filePath);
            
            Map<String,Object> parameters = new HashMap<String, Object>();
            
            SimpleDateFormat dateFormat = new SimpleDateFormat("d 'de' MMMM 'del' yyyy", new Locale("es", "MX"));
            
            String fechas = "Del "+" "+ dateFormat.format(start.getTime()) +" al " + dateFormat.format(end.getTime()) ;
            
            parameters.put("fecha",new Date());
            
            String direccion = getLoggedUser().getLocation().getCompleteAddress();
            parameters.put("direccion",direccion);
            
            String gerente = getLoggedUser().getLocation().getGerente();
            parameters.put("gerente",gerente);
            
            Taxi taxiReport = getTaxiController().getTaxiByIdReport(getPaymentClient().getTaxi().getId());
            
            String cliente = taxiReport.getCustomer().getFirstName()+" "+(taxiReport.getCustomer().getSecondName() == null ? "":taxiReport.getCustomer().getSecondName() + " " ) +taxiReport.getCustomer().getLastName()+ " " + taxiReport.getCustomer().getMiddleName() ;
            
            parameters.put("cliente",cliente);
            
           
            String ventasDiariasLS = formatearDecimales(taxiReport.getPaymentCar()/6);
            String diasPorSemana = getReportCustomerPays().get(0).getWorkedDays().toString();
            
            String km= taxiReport.getKm().toString();
            
            String totalFormateado = formatearDecimales(getPaymentClient().getTotalPayment());
            String totalLetra = Convertir(totalFormateado, true);
            
            float adeudoActual = getCalculatePrice() +  getCalculateExpensePrice() + (float) getFinancingCustomer().getIncrease() - (float) getFinancingCustomer().getDiscount()
                     ;
      
            Double saldoActual = getFinancingCustomer().getActuallyDebit();
            
            float subtotal = getFinanciamiento() + adeudoActual;

            JRBeanCollectionDataSource financiamientoServicios = new JRBeanCollectionDataSource(getSelectedDetailProductOrderFinanceList());
            JRBeanCollectionDataSource cobrosServicios = new JRBeanCollectionDataSource(getSelectedDetailProductOrderList());
            JRBeanCollectionDataSource financiamientoGastos = new JRBeanCollectionDataSource(getSelectedExpensesToFinance());
            JRBeanCollectionDataSource cobroGastos = new JRBeanCollectionDataSource(getSelectedExpensesToPay());
            parameters.put("placas",taxiReport.getPlaca());
            parameters.put("kilometraje",km);
            parameters.put("marca",taxiReport.getVehicle().getBrand().getName());
            parameters.put("modelo",taxiReport.getVehicle().getName());
            parameters.put("ano",taxiReport.getYear());
            parameters.put("color",taxiReport.getColor().getName());
            parameters.put("paquete",getReportCustomerPays().get(0).getContractService());
            parameters.put("ventasSemanales",formatearDecimales(getReportCustomerPays().get(0).getCompromisoTotal()));
            parameters.put("ventaDiariaLS",ventasDiariasLS);
            parameters.put("informacion",fechas);
            parameters.put("diasPorSemana",diasPorSemana);
            parameters.put("rentaDiaria",ventasDiariasLS);
            parameters.put("subTotal",formatearDecimales(taxiReport.getPaymentCar()));
            parameters.put("financiamiento",financiamientoServicios);
            parameters.put("cobrosServicios",cobrosServicios);
            parameters.put("financiamientoGastos",financiamientoGastos);
            parameters.put("cobroGastos",cobroGastos);
            parameters.put("totalLetra",totalLetra);
            parameters.put("ingresos",formatearDecimales(getReportCustomerPays().get(0).getCompromisoTotal() + getPaymentClient().getIncrease() - getPaymentClient().getDiscount()));
            parameters.put("pagoPaquete",formatearDecimales(getTotalContrato()));
            parameters.put("totalEgresos",formatearDecimales(getTotalCobro()+financingCustomer.getPayment()+getIncrementoPagos()-getDescuentoPagos()));
            parameters.put("total",formatearDecimales(getPaymentClient().getTotalPayment()));
            parameters.put("adeudoAnterior",formatearDecimales(getFinanciamiento()));
            parameters.put("adeudoActual",formatearDecimales(adeudoActual));
            parameters.put("abonoDelMes",formatearDecimales(financingCustomer.getPayment()));
            parameters.put("subtotal", formatearDecimales(subtotal));
            parameters.put("saldoActual", formatearDecimales(saldoActual));

            
            JasperDesign jasperDesign = JRXmlLoader.load(file);
            
            JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
            JasperPrint print = JasperFillManager.fillReport(jasperReport,parameters,new JREmptyDataSource());
            
            HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
            response.addHeader("content-disposition", "attachment;filename = reporte.pdf");
            ServletOutputStream stream = response.getOutputStream();
            JasperExportManager.exportReportToPdfStream(print, stream);
            FacesContext.getCurrentInstance().responseComplete();

        } catch (Exception e) {
            LOG.error("addRow", e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Pago al cliente", "Error, por favor verifica los datos y reportalo al equipo de soporte");
        }
    }

    public void updateReport() {
        LOG.info("updateReport");
        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();

        start.setTime(getStartDate());
        start.set(Calendar.HOUR_OF_DAY, 7);
        start.set(Calendar.MINUTE, 30);
        start.set(Calendar.SECOND, 0);

        end.setTime(null == getEndDate() ? getToday() : getEndDate());
        end.set(Calendar.HOUR_OF_DAY, 23);
        end.set(Calendar.MINUTE, 59);
        end.set(Calendar.SECOND, 59);
        try {
            setReportCustomerPays(
                    getController().callReportCustomerPayToMySQLQuery(
                            DATE_FORMAT.format(start.getTime()),
                            DATE_FORMAT.format(end.getTime()),
                            idTaxi
                    )
            );

            setSales(getController().getSalesbyTaxiTuple(idTaxi, getStartDate(), getEndDate()));
            setExpense(getController().fillExpenseDatatableLeftJoin(idTaxi, start.getTime(), end.getTime()));
            setExpenseToPay(getController().fillExpenseDatatableLeftJoinToPay(idTaxi, start.getTime(), end.getTime()));
            setExpenseToFinance(getController().fillExpenseDatatableLeftJoinToFinance(idTaxi, start.getTime(), end.getTime()));
            setServiceOrders(getController().getAllServiceOrderActiveAndStatusInTuple(idTaxi, start.getTime(), end.getTime()));
            setInvoice(getController().fillInvoiceDatatableLeftJoin(idTaxi, start.getTime(), end.getTime()));
            setPaymentClientList(getController().fillPaymentClientDatatable(idTaxi));
            setRelease(getController().fillReleaseDatatable(idTaxi));
            setDetailProductOrder(getController().fillProductsDetailByOrderServices(idTaxi, start.getTime(), end.getTime()));
            setDetailProductOrderFinancing(getController().fillProductsDetailByOrderServicesFinancing(idTaxi, start.getTime(), end.getTime()));
            
            Taxi taxiTemp = getController().getTaxiById(idTaxi);
            float sumFaltante = 0F;
            float sumContrato = 0F;
            setPorcentajeEfectivo(0F);
            //float financiamientoTemp = 0F;
            setFinanciamiento(taxiTemp.getAdeudo());
            
            if (getReportCustomerPays() != null || !getReportCustomerPays().isEmpty()) {
                for (ReportCustomerPay value : getReportCustomerPays()) {
                    if (value.getEconomicNumber().equalsIgnoreCase(taxiTemp.getEconomicNumber())) {
                        //sumFaltante = value.getTotalWorkedToPayDays();
                        //sumFaltante = value.getClientCompromise();
                        sumContrato = value.getTotalContractService();
                        setNameContrato(value.getContractService());
                        setPorcentajeEfectivo(value.getPorcentajeEfectividad());
                        //financiamientoTemp = value.getTotalServiceOrder() + value.getTotalElectricExpense() // TODO preguntar si es correcto comentarla
                        //financiamientoTemp = value.getTotalElectricExpense()
                          //      + value.getTotalEsteticoExpense() + value.getTotalGruaExpense() + value.getTotalSoldaduraExpense()
                            //    + value.getTotalTornoExpense();
                        setPagoDiario(value.getPagoDiario());
                    }
                }
            }
            
            if (getSales()!= null || !getSales().isEmpty()) {
                for (Sale value : getSales()) {
                    GregorianCalendar fechaCalendario = new GregorianCalendar();
                    fechaCalendario.setTime(value.getPayDate());
                    int diaSemana = fechaCalendario.get(Calendar.DAY_OF_WEEK);
                    if (diaSemana == 1) {
                        value.getProductividad(100);
                    }
                    else
                    {
                        sumFaltante = (float) (sumFaltante + value.getProductividad(getPorcentajeEfectivo()));
                    }
                }
            }
            
            if (getReportCustomerPays() != null || !getReportCustomerPays().isEmpty()) {
                for (ReportCustomerPay value : getReportCustomerPays()) {
                    if (value.getEconomicNumber().equalsIgnoreCase(taxiTemp.getEconomicNumber())) {
                        value.setCompromisoTotal(sumFaltante);
                    }
                }
            }
             
            getPaymentClient().setAmountToPay(Double.valueOf(sumFaltante + ""));
            setAdeudoMes(0f);
            setContrato(sumContrato);

            getPaymentClient().setIncrease(0D);
            getPaymentClient().setDiscount(0D);

            getFinancingCustomer().setActuallyDebit(0D);
            getFinancingCustomer().setDiscount(0D);
            getFinancingCustomer().setIncrease(0D);
            getFinancingCustomer().setLastDebit(0D);
            getFinancingCustomer().setMonthDebit(0D);
            getFinancingCustomer().setPayment(0D);

            setIncreaseContrato(0F);
            setDiscountContrato(0F);
            setTotalContrato(0F);

            calculateTotalFinancing();
            calculateTotalContrato();
            calculateTotal();

        } catch (Exception e) {
            LOG.error("updateReport", e);
        }
    }

    public List<ServiceOrderHasProduct> getDetails(String id) {
        LOG.info("getDetails");
        try {
            setDetails(getController().findAllProductByOrderId(id));

            LOG.info("details loaded size " + details.size());
        } catch (Exception e) {
            LOG.error("getDetails", e);
        }
        return null == details ? new ArrayList<>() : details;
    }

    public List<InvoiceHasProduct> getDetailsInvoice(String id) {
        LOG.info("getDetailsInvoice");
        try {
            setDetailsinvoice(getController().findAllProductByInvoiceId(id));

            LOG.info("detailsInvoice loaded size " + detailsinvoice.size());
        } catch (Exception e) {
            LOG.error("getDetailsInvoice", e);
        }
        return null == detailsinvoice ? new ArrayList<>() : detailsinvoice;
    }

    @PostConstruct
    public void init() {
        LOG.info("init");
        try {
            sales = new ArrayList();
            expense = new ArrayList();
            serviceOrders = new ArrayList();
            invoice = new ArrayList();
            reportCustomerPays = new ArrayList();
            paymentClientList = new ArrayList();
            detailProductOrder = new ArrayList();
            release = new ArrayList();
            loadBundlePropertyFile();
            setController(new ReportCustomerPayController());
            setGenericController(new GenericValidationController());
            setTaxis(getController().fillTaxisComboBox());
            setLocationController(new LocationController());
            setLocations(getLocationController().fillLocationDatatable());
            setTaxiController(new TaxiController());
            paymentClient = new PaymentClient();
            financingCustomer = new FinancingCustomer();
            getPaymentClient().setAmountToPay(0D);
            getPaymentClient().setIncrease(0D);
            getPaymentClient().setDiscount(0D);
            setBankCardController(new BankCardController());
            setBankCards(getBankCardController().findAllBankCardsByLocation(getLoggedUser().getLocation().getId()));
            setDeposit(false);
         

            getFinancingCustomer().setActuallyDebit(0D);
            getFinancingCustomer().setDiscount(0D);
            getFinancingCustomer().setIncrease(0D);
            getFinancingCustomer().setLastDebit(0D);
            getFinancingCustomer().setMonthDebit(0D);
            getFinancingCustomer().setPayment(0D);
            setFinanciamiento(0F);
            setAdeudoMes(0F);
            setContrato(0F);
            setDiscountContrato(0F);
            setIncreaseContrato(0F);
            setTotalContrato(0F);
            setSeguroVentas(0);
            setPagoDiario(0F);
            setSeguroVentasDinero(0F);

        } catch (Exception e) {
            LOG.error("init", e);
        }
    }

    private static final long serialVersionUID = 6394938203433032821L;
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    final Logger LOG = LogManager.getLogger(ReportCustomerPayBean.class);
    private LocationController locationController;
    private TaxiController taxiController;
    private List<Location> locations;
    private String locationId;

    private ReportCustomerPayController controller;
    private GenericValidationController genericController;
    private List<ReportCustomerPay> reportCustomerPays;
    private List<Sale> sales;
    private List<Expense> expense;
    private List<Expense> expenseToPay;
    private List<Expense> expenseToFinance;
    private List<Expense> selectedExpensesToPay;
    private List<Expense> selectedExpensesToFinance;
    private List<ServiceOrder> serviceOrders;
    private List<ServiceOrderHasProduct> details;
    private List<KardexOutStocktakingView> detailProductOrder;
    private List<KardexOutStocktakingView> detailProductOrderFinancing;
    private List<KardexOutStocktakingView> selectedDetailProductOrderList;
    private List<KardexOutStocktakingView> selectedDetailProductOrderFinanceList;
    private HashMap<String, List<KardexOutStocktakingView>> copySelectedProducts;
    private List<InvoiceHasProduct> detailsinvoice;
    private List<PaymentClient> paymentClientList;
    private List<ReleaseResource> release;
    private List<Invoice> invoice;
    private Date startDate;
    private Date endDate;
    private List<Taxi> taxis;
    private String idTaxi;
    private ServiceOrder selectedServiceOrder;
    private PaymentClient paymentClient;
    private float totalCobro;
    private float financiamiento;
    private float adeudoMes;
    private float contrato;
    private float discountContrato;
    private float increaseContrato;
    private float totalContrato;
    private float incrementoPagos;
    private float descuentoPagos;
    private FinancingCustomer financingCustomer;
    private String nameContrato;
    private int seguroVentas;
    private float pagoDiario;
    private float seguroVentasDinero;
    private float porcentajeEfectivo;
    private String comentariosIncrementoPago;
    private String comentariosDescuentoPago;
    private boolean deposit;
    private String bankCardId;
    private BankCardController bankCardController;
    private List<BankCard> bankCards;

    public LocationController getLocationController() {
        return locationController;
    }

    public void setLocationController(LocationController locationController) {
        this.locationController = locationController;
    }

    public List<Location> getLocations() {
        return locations;
    }

    public void setLocations(List<Location> locations) {
        this.locations = locations;
    }

    public String getLocationId() {
        return locationId;
    }

    public void setLocationId(String locationId) {
        this.locationId = locationId;
    }

    public float getPorcentajeEfectivo() {
        return porcentajeEfectivo;
    }

    public void setPorcentajeEfectivo(float porcentajeEfectivo) {
        this.porcentajeEfectivo = porcentajeEfectivo;
    }
    
    

    public GenericValidationController getGenericController() {
        return genericController;
    }

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

    public float getSeguroVentasDinero() {
        return seguroVentasDinero;
    }

    public void setSeguroVentasDinero(float seguroVentasDinero) {
        this.seguroVentasDinero = seguroVentasDinero;
    }

    public float getPagoDiario() {
        return pagoDiario;
    }

    public void setPagoDiario(float pagoDiario) {
        this.pagoDiario = pagoDiario;
    }

    public int getSeguroVentas() {
        return seguroVentas;
    }

    public void setSeguroVentas(int seguroVentas) {
        this.seguroVentas = seguroVentas;
    }

    public HashMap<String, List<KardexOutStocktakingView>> getCopySelectedProducts() {
        if (null == copySelectedProducts) {
            copySelectedProducts = new HashMap<>();
        }
        return copySelectedProducts;
    }

    public void setCopySelectedProducts(HashMap<String, List<KardexOutStocktakingView>> copySelectedProducts) {
        this.copySelectedProducts = copySelectedProducts;
    }

    public TaxiController getTaxiController() {
        return taxiController;
    }

    public void setTaxiController(TaxiController taxiController) {
        this.taxiController = taxiController;
    }

    public List<Expense> getSelectedExpensesToFinance() {
       if (null == selectedExpensesToFinance) {
            selectedExpensesToFinance = new ArrayList<>();
        }
        return selectedExpensesToFinance;
    }

    public void setSelectedExpensesToFinance(List<Expense> selectedExpensesToFinance) {
        this.selectedExpensesToFinance = selectedExpensesToFinance;
    }

    public List<Expense> getExpenseToFinance() {
        return expenseToFinance;
    }

    public void setExpenseToFinance(List<Expense> expensetoFinance) {
        this.expenseToFinance = expensetoFinance;
    }
    
    
    
    public void onRowSelect(SelectEvent event) {
        LOG.info("onRowSelect");
        try {
            getCopySelectedProducts().put(((KardexOutStocktakingView) event.getObject()).getId(), getSelectedDetailProductOrderList());
        } catch (Exception e) {
            LOG.error("onRowSelect", e);
        }
    }

    public void onRowUnselect(UnselectEvent event) {
        LOG.info("onRowUnselect");
        try {
            if (!getSelectedDetailProductOrderList().isEmpty()) {
                getCopySelectedProducts().put(((KardexOutStocktakingView) event.getObject()).getId(), getSelectedDetailProductOrderList());
            }
        } catch (Exception e) {
            LOG.error("onRowUnselect", e);
        }
    }

    public List<KardexOutStocktakingView> getSelectedDetailProductOrderList() {
        if (null == selectedDetailProductOrderList) {
            selectedDetailProductOrderList = new ArrayList<>();
        }
        return selectedDetailProductOrderList;
    }

    public void setSelectedDetailProductOrderList(List<KardexOutStocktakingView> selectedDetailProductOrderList) {
        this.selectedDetailProductOrderList = selectedDetailProductOrderList;
    }

    public List<KardexOutStocktakingView> getSelectedDetailProductOrderFinanceList() {
        
        if (null == selectedDetailProductOrderFinanceList) {
            selectedDetailProductOrderFinanceList = new ArrayList<>();
        }
        
        return selectedDetailProductOrderFinanceList;
    }

    public void setSelectedDetailProductOrderFinanceList(List<KardexOutStocktakingView> selectedDetailProductOrderFinanceList) {
        this.selectedDetailProductOrderFinanceList = selectedDetailProductOrderFinanceList;
    }

    public float getTotalCobro() {
        return totalCobro;
    }

    public void setTotalCobro(float totalCobro) {
        this.totalCobro = totalCobro;
    }

    public List<KardexOutStocktakingView> getDetailProductOrderFinancing() {
        return detailProductOrderFinancing;
    }

    public void setDetailProductOrderFinancing(List<KardexOutStocktakingView> detailProductOrderFinancing) {
        this.detailProductOrderFinancing = detailProductOrderFinancing;
    }

    public float getIncrementoPagos() {
        return incrementoPagos;
    }

    public void setIncrementoPagos(float incrementoPagos) {
        this.incrementoPagos = incrementoPagos;
    }

    public float getDescuentoPagos() {
        return descuentoPagos;
    }

    public void setDescuentoPagos(float descuentoPagos) {
        this.descuentoPagos = descuentoPagos;
    }

    public String getComentariosIncrementoPago() {
        return comentariosIncrementoPago;
    }

    public void setComentariosIncrementoPago(String comentariosIncrementoPago) {
        this.comentariosIncrementoPago = comentariosIncrementoPago;
    }

    public String getComentariosDescuentoPago() {
        return comentariosDescuentoPago;
    }

    public void setComentariosDescuentoPago(String comentariosDescuentoPago) {
        this.comentariosDescuentoPago = comentariosDescuentoPago;
    }
    
    
    

    public List<KardexOutStocktakingView> getDetailProductOrder() {
        return detailProductOrder;
    }

    public void setDetailProductOrder(List<KardexOutStocktakingView> detailProductOrder) {
        this.detailProductOrder = detailProductOrder;
    }

    public float getTotalContrato() {
        return totalContrato;
    }

    public void setTotalContrato(float totalContrato) {
        this.totalContrato = totalContrato;
    }

    public String getNameContrato() {
        return nameContrato;
    }

    public void setNameContrato(String nameContrato) {
        this.nameContrato = nameContrato;
    }

    public float getContrato() {
        return contrato;
    }

    public void setContrato(float contrato) {
        this.contrato = contrato;
    }

    public float getDiscountContrato() {
        return discountContrato;
    }

    public void setDiscountContrato(float discountContrato) {
        this.discountContrato = discountContrato;
    }

    public float getIncreaseContrato() {
        return increaseContrato;
    }

    public void setIncreaseContrato(float increaseContrato) {
        this.increaseContrato = increaseContrato;
    }

    public List<ReleaseResource> getRelease() {
        return release;
    }

    public void setRelease(List<ReleaseResource> release) {
        this.release = release;
    }

    public ReportCustomerPayBean() {
    }

    public FinancingCustomer getFinancingCustomer() {
        return financingCustomer;
    }

    public void setFinancingCustomer(FinancingCustomer financingCustomer) {
        this.financingCustomer = financingCustomer;
    }

    public float getAdeudoMes() {
        return adeudoMes;
    }

    public void setAdeudoMes(float adeudoMes) {
        this.adeudoMes = adeudoMes;
    }

    public float getFinanciamiento() {
        return financiamiento;
    }

    public void setFinanciamiento(float financiamiento) {
        this.financiamiento = financiamiento;
    }

    public List<PaymentClient> getPaymentClientList() {
        return paymentClientList;
    }

    public void setPaymentClientList(List<PaymentClient> paymentClientList) {
        this.paymentClientList = paymentClientList;
    }

    public PaymentClient getPaymentClient() {
        return paymentClient;
    }

    public void setPaymentClient(PaymentClient paymentClient) {
        this.paymentClient = paymentClient;
    }

    public List<InvoiceHasProduct> getDetailsinvoice() {
        return detailsinvoice;
    }

    public void setDetailsinvoice(List<InvoiceHasProduct> detailsinvoice) {
        this.detailsinvoice = detailsinvoice;
    }

    public List<Invoice> getInvoice() {
        return invoice;
    }

    public void setInvoice(List<Invoice> invoice) {
        this.invoice = invoice;
    }

    public List<ServiceOrderHasProduct> getDetails() {
        return details;
    }

    public void setDetails(List<ServiceOrderHasProduct> details) {
        this.details = details;
    }

    public ServiceOrder getSelectedServiceOrder() {
        return selectedServiceOrder;
    }

    public void setSelectedServiceOrder(ServiceOrder selectedServiceOrder) {
        this.selectedServiceOrder = selectedServiceOrder;
    }

    public List<ServiceOrder> getServiceOrders() {
        return serviceOrders;
    }

    public void setServiceOrders(List<ServiceOrder> serviceOrders) {
        this.serviceOrders = serviceOrders;
    }

    public List<Expense> getExpense() {
        return expense;
    }

    public void setExpense(List<Expense> expense) {
        this.expense = expense;
    }

    public List<Expense> getExpenseToPay() {
        return expenseToPay;
    }

    public void setExpenseToPay(List<Expense> expenseToPay) {
        this.expenseToPay = expenseToPay;
    }

    public List<Sale> getSales() {
        return sales;
    }

    public void setSales(List<Sale> sales) {
        this.sales = sales;
    }

    public List<Taxi> getTaxis() {
        return taxis;
    }

    public void setTaxis(List<Taxi> taxis) {
        this.taxis = taxis;
    }

    public String getIdTaxi() {
        return idTaxi;
    }

    public void setIdTaxi(String idTaxi) {
        this.idTaxi = idTaxi;
    }

    public ReportCustomerPayController getController() {
        return controller;
    }

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

    public List<ReportCustomerPay> getReportCustomerPays() {
        return reportCustomerPays;
    }

    public void setReportCustomerPays(List<ReportCustomerPay> reportCustomerPays) {
        this.reportCustomerPays = reportCustomerPays;
    }

    public List<Expense> getSelectedExpensesToPay() {
        if (null == selectedExpensesToPay) {
            selectedExpensesToPay = new ArrayList<>();
        }
        return selectedExpensesToPay;
    }

    public void setSelectedExpensesToPay(List<Expense> selectedExpensesToPay) {
        this.selectedExpensesToPay = selectedExpensesToPay;
    }

    public boolean isDeposit() {
        return deposit;
    }

    public void setDeposit(boolean deposit) {
        this.deposit = deposit;
    }

    public String getBankCardId() {
        return bankCardId;
    }

    public void setBankCardId(String bankCardId) {
        this.bankCardId = bankCardId;
    }

    public BankCardController getBankCardController() {
        return bankCardController;
    }

    public void setBankCardController(BankCardController bankCardController) {
        this.bankCardController = bankCardController;
    }

    public List<BankCard> getBankCards() {
        return bankCards;
    }

    public void setBankCards(List<BankCard> bankCards) {
        this.bankCards = bankCards;
    }
    
    

    public Date getStartDate() {
        if (null == startDate) {
            Calendar calendar = Calendar.getInstance();

            calendar.add(Calendar.MONTH, -1);

            calendar.set(HOUR_OF_DAY, 0);
            calendar.set(MINUTE, 0);
            calendar.set(SECOND, 0);
            calendar.set(MILLISECOND, 0);

            startDate = calendar.getTime();
        }

        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Date getEndDate() {
        if (null == endDate) {
            endDate = new Date();
        }
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public float getCalculatePrice() {
        float zero = 0f;
        if (!getSelectedDetailProductOrderFinanceList().isEmpty()) {
            zero = getSelectedDetailProductOrderFinanceList()
                    .stream()
                    .map(row -> row.getPriceToPay().floatValue())
                    .reduce(zero, (accumulator, _item) -> accumulator + _item);
        }
        return zero;
    }
    
    public float getCalculatePriceCobrar() {
        float zero = 0f;
        if (!getSelectedDetailProductOrderList().isEmpty()) {
            zero = getSelectedDetailProductOrderList()
                    .stream()
                    .map(row -> row.getPriceToPay().floatValue())
                    .reduce(zero, (accumulator, _item) -> accumulator + _item);
        }
        if (!getSelectedExpensesToPay().isEmpty()) {
            zero = getSelectedExpensesToPay()
                    .stream()
                    .map(row -> row.getAmountMenudeo().floatValue())
                    .reduce(zero, (accumulator, _item) -> accumulator + _item);
        }
        return zero;
    }


    public float getCalculateExpensePrice() {
        float zero = 0f;
        if (!getSelectedExpensesToFinance().isEmpty()) {
            zero = getSelectedExpensesToFinance()
                    .stream()
                    .map(row -> row.getAmountMenudeo().floatValue())
                    .reduce(zero, (accumulator, _item) -> accumulator + _item);
        }
        return zero;
    }
}
