/*
 * Arrebol Consultancy copyright.
 * 
 * This code belongs to Arrebol Consultancy
 * its use, redistribution or modification are prohibited 
 * without written authorization from Arrebol Consultancy.
 */
package com.arrebol.taxiservicios.beans.admin.client;

import com.arrebol.taxiservicios.beans.GenericPersonBean;
import com.arrebol.taxiservicios.controller.admin.CustomerController;
import com.arrebol.taxiservicios.controller.admin.DriverController;
import com.arrebol.taxiservicios.controller.admin.ExpenseController;
import com.arrebol.taxiservicios.controller.admin.GenericValidationController;
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.Taxi;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.arrebol.taxiservicios.model.enums.ExpenseStatusType;
import com.arrebol.taxiservicios.model.enums.ExpenseType;
import com.arrebol.taxiservicios.model.stocktaking.ServiceOrderHasProductId;
import com.arrebol.taxiservicios.model.stocktaking.view.KardexOutStocktakingView;
import com.arrebol.taxiservicios.model.view.PersonListCustomerFinancingView;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 *
 * @author Carlos Janitzio Zavala Lopez <janitzio.zavala@arrebol.com.mx>
 */
@Named("customerFinantialBean")
@ViewScoped
public class CustomerFinantialBean extends GenericPersonBean implements Serializable {

    /**
     *
     * @param outcome
     * @return
     */
    public String editCustomer(String outcome) {
        return outcome;
    }

    public void addFinantialCustomer() {
        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().existStableSmallBoxByCurdate(getLoggedUser())) {
            showMessage(FacesMessage.SEVERITY_WARN,
                    "Dia cerrado",
                    "No se pueden agregar más registros porque ya existe un cuadre de caja chica del día");
            return;
        }
        if (getGenericController().existStableGeneralBoxByCurdate(getLoggedUser())) {
            showMessage(FacesMessage.SEVERITY_WARN,
                    "Dia cerrado",
                    "No se pueden agregar más registros porque ya existe un cuadre de caja general del día");
            return;
        }
        if (getSelectedDetailProductOrderList().isEmpty() && getSelectedExpensesToPay().isEmpty()) {
            showMessage(FacesMessage.SEVERITY_WARN,
                    "Financiamiento en 0",
                    "Debe seleccionar los productos o gastos a financiar");
            return;

        }

        if (taxiId != null && !taxiId.isEmpty()) {
            Taxi taxiTemp = getCustomerController().getTaxiById(taxiId);
            getFinancing().setActiveStatus(BasicType.ENEBLED);
      
            getFinancing().setActuallyDebit(taxiTemp.getAdeudo() - getFinancing().getPayment());
            getFinancing().setCreatedBy(getLoggedUser());
            getFinancing().setCreatedOn(new Date());
            getFinancing().setDiscount(0D);
            getFinancing().setLastDebit(taxiTemp.getAdeudo());
            getFinancing().setMonthDebit(taxiTemp.getAdeudo());
            getFinancing().setTaxi(taxiTemp);
            getFinancing().setIncrease(0D);
            getFinancing().setId(UUID.randomUUID().toString());
            getFinancing().setActive(Boolean.TRUE);

            if (getReportController().saveFinancingClient(getFinancing())) {
                Expense expense = new Expense();
                expense.setId(UUID.randomUUID().toString());
                expense.setAmountMenudeo(getFinancing().getPayment());
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.HOUR, -6);
                expense.setCreatedOn(calendar.getTime());
                expense.setDescription("Abono de financiamiento");
                expense.setFolio("");
                expense.setPayment(getFinancing().getPayment());
                expense.setPaymentDate(calendar.getTime());
                expense.setStatus(ExpenseStatusType.AUTHORIZED);
                expense.setType(ExpenseType.ABONO_FINANCIAMIENTO);
                expense.setLocation(getLoggedUser().getLocation());
                expense.setLocationSend(new Location(getLoggedUser().getId()));
                expense.setPaid(BasicType.ENEBLED);
                expense.setFinance(BasicType.DISABLED);
                expense.setCommercialInvoiceStatus(BasicType.DISABLED);
                expense.setDepositStatus(ExpenseStatusType.AUTHORIZED);

                boolean success = getExpenseController().addExpense(
                        expense,
                        getLoggedUser().getId(),
                        (null != taxiId && !"".equals(taxiId.trim())) ? taxiId : null);

                if (success) {
                    showMessage(FacesMessage.SEVERITY_INFO,
                            "Abono al adeudo",
                            "Se agregó correctamente");
                }

                getSelectedDetailProductOrderList().stream().map(kardexOut -> {
                    String prod = kardexOut.getProductId();
                    String serv = kardexOut.getServiceId();
                    ServiceOrderHasProductId id = new ServiceOrderHasProductId(serv, prod, new Date(), getLoggedUser(), expense);
                    return id;
                }).forEachOrdered(id -> {
                    getCustomerController().editServicesHasProduct(id);//TODO pregutnar si deberí pasarcomo ENEBLED el status de cobrado
                });
                
                getSelectedExpensesToPay().forEach(expenseToPayEdit -> {
                    
                    expenseToPayEdit.setPaymentDate(getFinancing().getCreatedOn());
                    getCustomerController().editExpenseToPay(expenseToPayEdit);

                });

                taxiTemp.setAdeudo((float) getFinancing().getActuallyDebit());
                getReportController().updateTaxiById(taxiTemp);
            }

            setFinancing(new FinancingCustomer());
            setDetailProductOrder(getCustomerController().fillProductsDetailByOrderServicesFinancing(taxiId));
            setExpenseToPay(getCustomerController().fillExpenseDatatableLeftJoinToFinance(taxiId));
            getSelectedDetailProductOrderList().clear();
            getSelectedExpensesToPay().clear();
            calculateTotalFinancing();
            calculateTotalFinancingGastos();
            setTotalAdeudos(customerController.getTotalAdeudosByLocation(getLoggedUser().getLocation()));
            setAdeudoVehiculo(getCustomerController().getTaxiById(taxiId).getAdeudo());
        }
    }
    
    public void addDirectFinantialCustomer() {
        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().existStableSmallBoxByCurdate(getLoggedUser())) {
            showMessage(FacesMessage.SEVERITY_WARN,
                    "Dia cerrado",
                    "No se pueden agregar más registros porque ya existe un cuadre de caja chica del día");
            return;
        }
        if (getGenericController().existStableGeneralBoxByCurdate(getLoggedUser())) {
            showMessage(FacesMessage.SEVERITY_WARN,
                    "Dia cerrado",
                    "No se pueden agregar más registros porque ya existe un cuadre de caja general del día");
            return;
        }
        

        if (taxiId != null && !taxiId.isEmpty()) {
            Taxi taxiTemp = getCustomerController().getTaxiById(taxiId);
            getFinancing().setActiveStatus(BasicType.ENEBLED);
            getFinancing().setPayment(getAbonoDirecto());
            getFinancing().setActuallyDebit(taxiTemp.getAdeudo() - getAbonoDirecto());
            getFinancing().setCreatedBy(getLoggedUser());
            getFinancing().setCreatedOn(new Date());
            getFinancing().setDiscount(0D);
            getFinancing().setLastDebit(taxiTemp.getAdeudo());
            getFinancing().setMonthDebit(taxiTemp.getAdeudo());
            getFinancing().setTaxi(taxiTemp);
            getFinancing().setIncrease(0D);
            getFinancing().setId(UUID.randomUUID().toString());
            getFinancing().setActive(Boolean.TRUE);

            if (getReportController().saveFinancingClient(getFinancing())) {
                Expense expense = new Expense();
                expense.setId(UUID.randomUUID().toString());
                expense.setAmountMenudeo(getFinancing().getPayment());
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.HOUR, -6);
                expense.setCreatedOn(calendar.getTime());
                expense.setDescription("Abono de financiamiento");
                expense.setFolio("");
                expense.setPayment(getFinancing().getPayment());
                expense.setPaymentDate(calendar.getTime());
                expense.setStatus(ExpenseStatusType.AUTHORIZED);
                expense.setType(ExpenseType.ABONO_FINANCIAMIENTO);
                expense.setLocation(getLoggedUser().getLocation());
                expense.setLocationSend(new Location(getLoggedUser().getId()));
                expense.setPaid(BasicType.ENEBLED);
                expense.setFinance(BasicType.DISABLED);
                expense.setCommercialInvoiceStatus(BasicType.DISABLED);
                expense.setDepositStatus(ExpenseStatusType.AUTHORIZED);

                boolean success = getExpenseController().addExpense(
                        expense,
                        getLoggedUser().getId(),
                        (null != taxiId && !"".equals(taxiId.trim())) ? taxiId : null);

                if (success) {
                    showMessage(FacesMessage.SEVERITY_INFO,
                            "Abono al adeudo",
                            "Se agregó correctamente");
                }

                
                
                

                taxiTemp.setAdeudo((float) getFinancing().getActuallyDebit());
                getReportController().updateTaxiById(taxiTemp);
            }

            setFinancing(new FinancingCustomer());
            setAbonoDirecto(0.0);
            setTotalAdeudos(customerController.getTotalAdeudosByLocation(getLoggedUser().getLocation()));
            setAdeudoVehiculo(getCustomerController().getTaxiById(taxiId).getAdeudo());
            
        }
    }
    

    public String seeDetails(String outcome) {
        return outcome;
    }

    public List<Taxi> getDetails(String id) {
        logger.info("getDetails");
        try {
            setTaxis(getCustomerController().getTaxiByIdCustomer(id, getLoggedUser().getLocation().getId()));

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

    public void calculateTotalFinancing() {

        setTotalFinancing(getCalculatePrice());
        getFinancing().setPayment(getTotalFinancing()+getTotalFinancingGastos());

    }
    
    public void calculateTotalFinancingGastos() {

        setTotalFinancingGastos(getCalculatePriceGastos());
        getFinancing().setPayment(getTotalFinancing()+getTotalFinancingGastos());

    }
    

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

        return zero;
    }

    public void updateReport() {
        logger.info("updateReport");

        try {

            setDetailProductOrder(getCustomerController().fillProductsDetailByOrderServicesFinancing(taxiId));
            setExpenseToPay(getCustomerController().fillExpenseDatatableLeftJoinToFinance(taxiId));
            setAdeudoVehiculo(getCustomerController().getTaxiById(taxiId).getAdeudo());

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

    @PostConstruct
    public void init() {
        try {
            loadBundlePropertyFile();

            setFinancing(new FinancingCustomer());

            setController(new DriverController());
            setCustomerController(new CustomerController());
            setReportController(new ReportCustomerPayController());
            setExpenseController(new ExpenseController());
            setGenericController(new GenericValidationController());
            setCustomers(getController().callReportCustomerFinancingQueryMySQL(getLoggedUser().getLocation().getId()));
            setTaxis(getCustomerController().fillTaxisComboBoxFinance());
            totalFinancing = 0F;
            totalFinancingGastos = 0F;
            abonoDirecto = 0.0;
            adeudoVehiculo= 0F;
            setTotalAdeudos(customerController.getTotalAdeudosByLocation(getLoggedUser().getLocation()));
           

        } catch (Exception e) {
            logger.error("Finantial customer init", e);
        }
    }

    private static final long serialVersionUID = -7284027390656669184L;

    final Logger logger = LogManager.getLogger(CustomerListBean.class);

    private CustomerController customerController;
    private ReportCustomerPayController reportController;
    private ExpenseController expenseController;
    private GenericValidationController genericController;

    private List<PersonListCustomerFinancingView> customers;
    private List<Taxi> taxis;
    private PersonListCustomerFinancingView selectedCustomer;
    private FinancingCustomer financing;
    private String taxiId;
    private float totalFinancing;
    private float totalFinancingGastos;
    private Double totalAdeudos;
    private Double abonoDirecto;
    private float adeudoVehiculo;
    private String comentario;
    private List<KardexOutStocktakingView> detailProductOrder;
    private List<KardexOutStocktakingView> selectedDetailProductOrderList;

    private List<Expense> expenseToPay;
    private List<Expense> selectedExpensesToPay;

    public Double getTotalAdeudos() {
        return totalAdeudos;
    }

    public void setTotalAdeudos(Double totalAdeudos) {
        this.totalAdeudos = totalAdeudos;
    }

    public GenericValidationController getGenericController() {
        return genericController;
    }

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

    public float getTotalFinancing() {
        return totalFinancing;
    }

    public void setTotalFinancing(float totalFinancing) {
        this.totalFinancing = totalFinancing;
    }

    public ExpenseController getExpenseController() {
        return expenseController;
    }

    public void setExpenseController(ExpenseController expenseController) {
        this.expenseController = expenseController;
    }

    public ReportCustomerPayController getReportController() {
        return reportController;
    }

    public void setReportController(ReportCustomerPayController reportController) {
        this.reportController = reportController;
    }

    public List<Taxi> getTaxisCombo() {
        return getCustomerController().fillTaxisComboBox();
    }

    public String getTaxiId() {
        return taxiId;
    }

    public void setTaxiId(String taxiId) {
        this.taxiId = taxiId;
    }

    public FinancingCustomer getFinancing() {
        return financing;
    }

    public void setFinancing(FinancingCustomer financing) {
        this.financing = financing;
    }

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

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

    public CustomerController getCustomerController() {
        return customerController;
    }

    public void setCustomerController(CustomerController customerController) {
        this.customerController = customerController;
    }

    public List<PersonListCustomerFinancingView> getCustomers() {
        if (null == customers) {
            customers = new ArrayList<>();
        }
        return customers;
    }

    public void setCustomers(List<PersonListCustomerFinancingView> customers) {
        this.customers = customers;
    }

    public PersonListCustomerFinancingView getSelectedCustomer() {
        return selectedCustomer;
    }

    public void setSelectedCustomer(PersonListCustomerFinancingView selectedCustomer) {
        this.selectedCustomer = selectedCustomer;
    }

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

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

    public List<KardexOutStocktakingView> getSelectedDetailProductOrderList() {
        return selectedDetailProductOrderList;
    }

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

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

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

    public List<Expense> getSelectedExpensesToPay() {
        return selectedExpensesToPay;
    }

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

    public float getTotalFinancingGastos() {
        return totalFinancingGastos;
    }

    public void setTotalFinancingGastos(float totalFinancingGastos) {
        this.totalFinancingGastos = totalFinancingGastos;
    }

    public Double getAbonoDirecto() {
        return abonoDirecto;
    }

    public void setAbonoDirecto(Double abonoDirecto) {
        this.abonoDirecto = abonoDirecto;
    }

    public String getComentario() {
        return comentario;
    }

    public void setComentario(String comentario) {
        this.comentario = comentario;
    }

    public float getAdeudoVehiculo() {
        return adeudoVehiculo;
    }

    public void setAdeudoVehiculo(float adeudoVehiculo) {
        this.adeudoVehiculo = adeudoVehiculo;
    }

   
    
    

}
