/*
 * 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.apc.web.beans.admin;

import com.arrebol.apc.controller.BitacoraController;
import com.arrebol.apc.controller.GenericController;
import com.arrebol.apc.controller.GenericValidationController;
import com.arrebol.apc.controller.admin.LoanEmployeeController;
import com.arrebol.apc.model.admin.LoanEmployee;
import com.arrebol.apc.model.admin.LoanEmployeeDetails;
import com.arrebol.apc.model.core.HumanResource;
import com.arrebol.apc.model.core.Office;
import com.arrebol.apc.model.enums.ActiveStatus;
import com.arrebol.apc.model.system.logs.Bitacora;
import com.arrebol.apc.model.views.LoanEmployeeDetailAllDataView;
import com.arrebol.apc.model.views.LoanEmployeeView;
import com.arrebol.apc.web.beans.Datatable;
import com.arrebol.apc.web.beans.GenericBean;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.primefaces.event.ReorderEvent;
import org.primefaces.event.RowEditEvent;

/**
 *
 * @author Administrador
 */
@Named("loanEmployeeListBean")
@ViewScoped
public class LoanEmployeeListBean extends GenericBean implements Serializable, Datatable {

   public List<LoanEmployeeDetailAllDataView> getDetails(String idLoan) {
      try {
         setLoanEmployeeDetails(getController().getLoanEmployeeDetailByIdLoan(idLoan));
         setTotalAmountLoan(fillTotalAmountLoan());
      } catch (Exception e) {
      }
      return null == loanEmployeeDetails ? new ArrayList<>() : loanEmployeeDetails;
   }

   public void searchHistoricalAction() {
      try {
         if (getStarDate().after(getEndDate())) {
            showMessage(FacesMessage.SEVERITY_ERROR, getBundlePropertyFile().getString("generic.start.date"), getBundlePropertyFile().getString("generic.end.date.error"));
         } else {
            setLoanEmployee(getController().fillLoanEmployeeDataTable(getStarDate(), getEndDate()));
         }
      } catch (Exception e) {
      }
   }

   public BigDecimal searchTotalAmountLoan() {
      try {
         if (getStarDate().after(getEndDate())) {
            showMessage(FacesMessage.SEVERITY_ERROR, getBundlePropertyFile().getString("generic.start.date"), getBundlePropertyFile().getString("generic.end.date.error"));
         } else {
            setTotalAmountLoan(fillTotalAmountLoan());
         }
      } catch (Exception e) {
      }
      return getTotalAmountLoan();
   }

   public BigDecimal fillTotalAmountLoan() {
      return getController().fillTotalAmountLoan(getStarDate(), getEndDate());
   }

   @Override
   public void editRow(RowEditEvent event) {
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   }

   @Override
   public void onRowCancel(RowEditEvent event) {
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   }

   @Override
   public void onRowReorder(ReorderEvent event) {
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   }

   @Override
   public void addRow() {
      Date date = new Date();
      if (genericCtrl.existStableGeneralBoxByCreatedOn(date)) {
         showMessage(FacesMessage.SEVERITY_WARN, "Día cerrado", "No se pueden agregar más compras de producto a empleados porque ya se existe un cuadre de caja general de hoy.");
         return;
      }

      if (amountLoan.compareTo(BigDecimal.ZERO) == 0 || amountToPay.compareTo(BigDecimal.ZERO) == 0) {

         showMessage(FacesMessage.SEVERITY_WARN, "Compra de producto incorrecto", "No se pueden agregar la compra de producto a empleados con monto o monto de abonos de 0");
         return;

      }

      if (amountLoan.compareTo(amountToPay) <= 0) {

         showMessage(FacesMessage.SEVERITY_WARN, "Compra de producto incorrecto", "No se pueden agregar la compra de producto a empleados con valor a pagar menor a sus abonos");
         return;

      }

      LoanEmployee loan = new LoanEmployee();
      loan.setIdEmployee(userId);
      loan.setCreatedOn(new Date());
      loan.setCreatedBy(getLoggedUser().getUser().getId());
      loan.setAmountLoan(amountLoan);
      loan.setAmountToPay(amountToPay);
      loan.setLoanEmployeeStatus(ActiveStatus.ENEBLED);

      // Calcula numero de semanas
      Double interes = 0.05;
      Double interesReal = 0.0;
      Double semanasD = amountLoan.doubleValue() / amountToPay.doubleValue();
      int numSemanas = semanasD.intValue();
      double residuo = semanasD - numSemanas;
      if (residuo != 0.0) {
         numSemanas += 1;
      }

      // Calcula número de meses
      int numMeses = numSemanas / 4;
      if (numSemanas % 4 > 0) {
         numMeses += 1;
      }

      // Calcula el interes real 0.05 por el número de meses
      interesReal = interes * numMeses;
      Double saldoTotal = (amountLoan.doubleValue() * interesReal) + amountLoan.doubleValue();
      loan.setTotalAmountToPay(new BigDecimal(saldoTotal));
      loan.setBalance(new BigDecimal(saldoTotal));

      HumanResource hr = users.stream().filter(p -> p.getId().equals(userId)).findFirst().get();
      hr.setBalance(hr.getBalance().add(new BigDecimal(saldoTotal)));

      getController().saveLoanEmployee(loan, hr);

      userId = "";
      amountLoan = BigDecimal.ZERO;
      amountToPay = BigDecimal.ZERO;

      setLoanEmployee(getController().fillLoanEmployeeDataTable(getStarDate(), getEndDate()));
   }

   public void addRowLoanDetail() {

      if (loanDetailAmount.compareTo(BigDecimal.ZERO) == 0) {

         showMessage(FacesMessage.SEVERITY_WARN, "Abono Incorrecto", "No se pueden agregar un abono de 0");
         return;

      }

      if (loanDetailAmount.compareTo(BigDecimal.ZERO) < 0) {

         showMessage(FacesMessage.SEVERITY_WARN, "Abono Incorrecto", "No se pueden agregar un abono negativo");
         return;

      }

      if (genericCtrl.existStableGeneralBoxByCreatedOn(new Date())) {
         showMessage(FacesMessage.SEVERITY_WARN, "Día cerrado", "No se pueden hacer mas abonos a compra de productos porque ya se existe un cuadre de caja general de hoy.");
         return;
      }

      if (loanDetailAmount.compareTo(selectedLoan.getBalance()) <= 0) {
         if (selectedLoan.getLoanEmployeeStatus() == ActiveStatus.ENEBLED) {
            LoanEmployeeDetails loanDetail = new LoanEmployeeDetails();
            loanDetail.setIdLoan(selectedLoan.getId());
            loanDetail.setIdUser(selectedLoan.getIdUser());
            loanDetail.setPaymentAmount(loanDetailAmount);
            loanDetail.setReferenceNumber(selectedLoan.getReferenceNumber() + 1);
            loanDetail.setCreatedOn(new Date());
            loanDetail.setCreatedBy(getLoggedUser().getUser().getId());
            loanDetail.setLoanEmployeeDetailStatus(ActiveStatus.ENEBLED);
            loanDetail.setPayroll(ActiveStatus.DISABLED);

            HumanResource hr = users.stream().filter(p -> p.getId().equals(selectedLoan.getIdUser())).findFirst().get();
            hr.setBalance(hr.getBalance().subtract(loanDetailAmount));

            LoanEmployee loan = getController().getLoanEmployeeById(selectedLoan.getId());
            loan.setBalance(loan.getBalance().subtract(loanDetailAmount));

            getController().saveLoanEmployeeDetail(loanDetail, hr, loan);
            loanDetailAmount = BigDecimal.ZERO;

            setLoanEmployee(getController().fillLoanEmployeeDataTable(getStarDate(), getEndDate()));
            showMessage(FacesMessage.SEVERITY_INFO, "Abono correcto", "Abono creado correctamente.");
         } else {
            showMessage(FacesMessage.SEVERITY_WARN, "Compra de producto deshabilitado", "No se puede abonar a una compra deshabilitado");
         }
      } else {
         showMessage(FacesMessage.SEVERITY_WARN, "Cantidad incorrecta", "La cantidad a abonar es mayor a la deuda faltante de la compra de producto");
      }

   }

   @Override
   public void deleteRow() {

      if (genericCtrl.existStableGeneralBoxByCreatedOn(selectedLoan.getCreatedOn())) {
         showMessage(FacesMessage.SEVERITY_WARN, "Compra de producto a empleado", "No se puede borrar porque ya se realizó el cuadre de caja general del día.");
      } else {
         if (selectedLoan.getTotalAmountToPay().compareTo(selectedLoan.getBalance()) == 0) {
            boolean delete = true;
            delete = selectedLoan.getLoanEmployeeStatus() == ActiveStatus.ENEBLED ? true : false;

            if (delete) {
               getController().updateLoanEmployeeByStatus(ActiveStatus.DISABLED, selectedLoan.getId(), getLoggedUser().getUser().getId());
               setLoanEmployee(getController().fillLoanEmployeeDataTable(getStarDate(), getEndDate()));

               Bitacora bitacora = new Bitacora();
               LoanEmployee loan = getController().getLoanEmployeeById(selectedLoan.getId());
               bitacora.setAction("Eliminar gasto administrativo");
               bitacora.setCommentsUser(commentsBitacora);
               bitacora.setCreatedBy(getLoggedUser().getUser().getId());
               bitacora.setCreatedOn(new Date());
               bitacora.setNameUser(getLoggedUser().getUser().getUserName());
               bitacora.setOffice(new Office(getLoggedUser().getOffice().getId()));
               bitacora.setDescription("Se eliminó la compra de producto con monto $"
                       + loan.getAmountLoan() + " y fecha " + loan.getCreatedOn());

               /*
                List<LoanEmployeeDetailAllDataView> details = getDetails(selectedLoan.getId());
                if (details != null) {
                    for (LoanEmployeeDetailAllDataView detail : details) {
                        getController().updateLoanEmployeeDetailByStatus(ActiveStatus.DISABLED, detail.getId(), getLoggedUser().getUser().getId());
                    }
                }*/
               bitacoraCtrl.saveBitacora(bitacora);
               commentsBitacora = "";
               selectedLoan = null;
               showMessage(FacesMessage.SEVERITY_INFO, "Compra de producto a empleado eliminado", "Se eliminó correctamente.");
            }
         } else {
            showMessage(FacesMessage.SEVERITY_INFO, "La compra de producto tiene abonos agregados", "No se puede borrar una compra de producto con abonos.");
         }

      }
   }

   private LoanEmployeeController controller;
   private GenericController genericCtrl;
   private List<LoanEmployeeView> loanEmployeeView;
   private List<LoanEmployeeDetailAllDataView> loanEmployeeDetails;
   private LoanEmployeeView selectedLoan;
   private List<HumanResource> users;
   private String userId;
   private BigDecimal amountLoan;
   private BigDecimal amountToPay;
   private BigDecimal loanDetailAmount;
   private BigDecimal totalAmountLoan;

   private BitacoraController bitacoraCtrl;
   private GenericValidationController genericValidateController;
   private Date lastStableGeneralBox;
   private String commentsBitacora;

   public BigDecimal getTotalAmountLoan() {
      return totalAmountLoan;
   }

   public void setTotalAmountLoan(BigDecimal totalAmountLoan) {
      this.totalAmountLoan = totalAmountLoan;
   }

   public BigDecimal getAmountLoan() {
      return amountLoan;
   }

   public void setAmountLoan(BigDecimal amountLoan) {
      this.amountLoan = amountLoan;
   }

   public BigDecimal getLoanDetailAmount() {
      return loanDetailAmount;
   }

   public void setLoanDetailAmount(BigDecimal loanDetailAmount) {
      this.loanDetailAmount = loanDetailAmount;
   }

   public BigDecimal getAmountToPay() {
      return amountToPay;
   }

   public void setAmountToPay(BigDecimal amountToPay) {
      this.amountToPay = amountToPay;
   }

   public String getUserId() {
      return userId;
   }

   public void setUserId(String userId) {
      this.userId = userId;
   }

   public GenericController getGenericCtrl() {
      return genericCtrl;
   }

   public void setGenericCtrl(GenericController genericCtrl) {
      this.genericCtrl = genericCtrl;
   }

   public List<HumanResource> getUsers() {
      return users;
   }

   public void setUsers(List<HumanResource> users) {
      this.users = users;
   }

   public List<LoanEmployeeView> getLoanEmployeeView() {
      return loanEmployeeView;
   }

   public void setLoanEmployeeView(List<LoanEmployeeView> loanEmployeeView) {
      this.loanEmployeeView = loanEmployeeView;
   }

   public LoanEmployeeView getSelectedLoan() {
      return selectedLoan;
   }

   public void setSelectedLoan(LoanEmployeeView selectedLoan) {
      this.selectedLoan = selectedLoan;
   }

   public LoanEmployeeController getController() {
      return controller;
   }

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

   public List<LoanEmployeeView> getLoanEmployee() {
      return loanEmployeeView;
   }

   public void setLoanEmployee(List<LoanEmployeeView> loanEmployee) {
      this.loanEmployeeView = loanEmployee;
   }

   public List<LoanEmployeeDetailAllDataView> getLoanEmployeeDetails() {
      return loanEmployeeDetails;
   }

   public void setLoanEmployeeDetails(List<LoanEmployeeDetailAllDataView> loanEmployeeDetails) {
      this.loanEmployeeDetails = loanEmployeeDetails;
   }

   public String getCommentsBitacora() {
      return commentsBitacora;
   }

   public void setCommentsBitacora(String commentsBitacora) {
      this.commentsBitacora = commentsBitacora;
   }

   public GenericValidationController getGenericValidateController() {
      return genericValidateController;
   }

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

   public Date getLastStableGeneralBox() {
      return lastStableGeneralBox;
   }

   public void setLastStableGeneralBox(Date lastStableGeneralBox) {
      this.lastStableGeneralBox = lastStableGeneralBox;
   }

   @PostConstruct
   public void init() {
      try {
         loadBundlePropertyFile();
         genericCtrl = new GenericController();
         setController(new LoanEmployeeController());
         bitacoraCtrl = new BitacoraController();
         setGenericValidateController(new GenericValidationController());
         setLastStableGeneralBox(getGenericValidateController().lastStableGeneralBoxByDate(getLoggedUser().getUser()));
         setLoanEmployee(getController().fillLoanEmployeeDataTable(getStarDate(), getEndDate()));
         // users = genericCtrl.getAllUsersByOffice(getLoggedUser().getOffice().getId());
         users = genericCtrl.getAllHRByOffice(getLoggedUser().getOffice().getId());
         totalAmountLoan = fillTotalAmountLoan();
      } catch (Exception e) {
      }
   }
}
