/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package com.arrebol.taxiservicios.beans.cobranza;

import com.arrebol.taxiservicios.beans.Datatable;
import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.CustomerController;
import com.arrebol.taxiservicios.controller.admin.GenericPersonController;
import com.arrebol.taxiservicios.controller.admin.GenericValidationController;
import com.arrebol.taxiservicios.controller.catalog.EtapasJuridicoController;
import com.arrebol.taxiservicios.controller.cobranza.CobranzaController;
import com.arrebol.taxiservicios.controller.juridicas.DetalleLoteEtapaController;
import com.arrebol.taxiservicios.controller.predio.AbonoLoteController;
import com.arrebol.taxiservicios.controller.predio.DetalleLoteUrbanizacionController;
import com.arrebol.taxiservicios.controller.predio.PreventaController;
import com.arrebol.taxiservicios.controller.predio.UrbanizacionController;
import com.arrebol.taxiservicios.model.catalog.EtapasJuridico;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.PeriodoPago;
import com.arrebol.taxiservicios.model.enums.PersonType;
import com.arrebol.taxiservicios.model.enums.TipoAbono;
import com.arrebol.taxiservicios.model.juridicas.DetalleLoteEtapa;
import com.arrebol.taxiservicios.model.predio.AbonoLote;
import com.arrebol.taxiservicios.model.predio.AbonosView;
import com.arrebol.taxiservicios.model.predio.DetalleLoteUrbanizacion;
import com.arrebol.taxiservicios.model.predio.Lote;
import com.arrebol.taxiservicios.model.predio.Urbanizacion;
import com.arrebol.taxiservicios.model.view.PersonListView;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
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 Usuario
 */
@Named("cobranzaJuridicoBean")
@ViewScoped
public class CobranzaJuridicoBean extends TaxiGenericBean implements Serializable {

    private static final long serialVersionUID = -2400590341745672164L;
    final Logger logger = LogManager.getLogger(CobranzaJuridicoBean.class);
    private PreventaController controladorPreventa;
    private Urbanizacion selectedUrbanizacion;
    private CobranzaController cobranzaController;
    private Double pagoUrbanizacion;
    private Double totalJuridico;
    private Double pagoJuridicoDado;
    private Double pagoCuentasJuridico;
    private String etapaJuridicoComentario;
    private List<Urbanizacion> listaUrbanizacion;
    private DetalleLoteEtapa detalleLoteEtapa;
    private List<DetalleLoteEtapa> detalleLoteEtapaList;
    private String idEtapa;
    private List<String> listaIdsLotesJuridico;
    private UrbanizacionController urbanizacionController;
    private Urbanizacion selectUrbanizacion;
    private DetalleLoteUrbanizacion nuevoDetalleLoteUrbanizacion;
    private DetalleLoteUrbanizacionController detalleLoteUrbanizacionController;
    private GenericValidationController genericController;
    private Boolean comboMandados;
    private Boolean comboCobranza;
    private Double totalDado;
    private Double totalPagar;
    private DetalleLoteEtapaController detalleLoteEtapaController;
    private Double totalPagarUrbanizacion;
    private List<EtapasJuridico> listaEtapasJuridico;
    private EtapasJuridico etapaJuridicoSeleccionada;
    private EtapasJuridicoController etapaJuridicoController;

    private DetalleLoteEtapa nuevoDetalleLoteEtapa;
    private List<Lote> lotes;
    private Lote selectedLote;
    private List<PersonListView> personas;
    private String selectUser;
    private String folioLote;
    private List<AbonoLote> abonos;
    private AbonoLote selectAbono;
    private Double pagoDado;
    private Double mandadoDado;
    private Double cobranzaDada;
    private Date FechaPago;
    private CustomerController customerController;
    private List<String> idPersonasUnicos;
    private Date fechaPagoUrbanizacion;
    private String descripcionPago;
    private String descipcionJuridico;
    private List<DetalleLoteEtapa> listaDetalleLote;
    private List<Lote> listaLote;

    private AbonoLoteController abonoLoteController;
    private Double totalAbonosRestantes;
    private List<AbonoLote> abonosRestantes;
    private Double newPagoPorConvenio;
    private Double residuoReajuste;
    private Double actualizarPago;
    private List<Person> listaPersonas;
    private Boolean PagoExitoso;

    @PostConstruct
    public void init() {
        logger.info("init CobranzaBean");
        try {
            setNuevoDetalleLoteEtapa(new DetalleLoteEtapa());
            setIdPersonasUnicos(new ArrayList<>());
            setCustomerController(new CustomerController());
            setDetalleLoteEtapa(new DetalleLoteEtapa());
            setDetalleLoteEtapaController(new DetalleLoteEtapaController());
            setListaDetalleLote(getDetalleLoteEtapaController().fillDetalleLoteEtapaDatatable(getLoggedUser().getLocation()));
            setListaPersonas(new ArrayList<>());
            setListaLote(new ArrayList<>());
            for (int i = 0; i <= getListaDetalleLote().size() - 1; i++) {
                getIdPersonasUnicos().add(getListaDetalleLote().get(i).getLote().getCliente().getId());
                getListaLote().add(getListaDetalleLote().get(i).getLote());
            }
            //se filtran los valores unicos
            Set<String> conjuntoId = new HashSet<>(getIdPersonasUnicos());
            setIdPersonasUnicos(new ArrayList<>(conjuntoId));
            for (int i = 0; i <= getIdPersonasUnicos().size() - 1; i++) {
                getListaPersonas().add(getCustomerController().getPersonById(getIdPersonasUnicos().get(i)));

            }
            Set<Lote> conjuntoLote = new HashSet<>(getListaLote());
            setListaLote(new ArrayList<>(conjuntoLote));
            setTotalJuridico(0D);
            setPagoCuentasJuridico(0D);
            setTotalPagar(0d);
            setDetalleLoteEtapaController(new DetalleLoteEtapaController());
            setDescripcionPago("");
            setPagoJuridicoDado(0d);
            setEtapaJuridicoController(new EtapasJuridicoController());
            setEtapaJuridicoSeleccionada(new EtapasJuridico());
            setListaEtapasJuridico(getEtapaJuridicoController().fillAllEtapasJuridicas(getLoggedUser().getLocation()));
            setMandadoDado(0D);
            setPagoUrbanizacion(0D);
            setNuevoDetalleLoteUrbanizacion(new DetalleLoteUrbanizacion());
            setTotalPagarUrbanizacion(0D);
            setFechaPagoUrbanizacion(new Date());
            setTotalDado(0D);
            setDetalleLoteUrbanizacionController(new DetalleLoteUrbanizacionController());
            setUrbanizacionController(new UrbanizacionController());
            setSelectUrbanizacion(new Urbanizacion());
            setDetalleLoteUrbanizacionController(new DetalleLoteUrbanizacionController());
            setCobranzaDada(0D);
            loadBundlePropertyFile();
            setComboCobranza(false);
            setComboMandados(false);
            setSelectedUrbanizacion(new Urbanizacion());
            setGenericController(new GenericValidationController());
            setControladorPreventa(new PreventaController());
            
        } catch (Exception e) {
            logger.error("CobranzaBean init", e);
        }
    }

    public void calcularTotal() {
        setTotalPagar(getPagoDado());
        if (getComboCobranza() == true) {
            setTotalPagar(getTotalPagar() + getCobranzaDada());
        }
        if (getComboMandados() == true) {
            setTotalPagar(getTotalPagar() + getMandadoDado());
        }
    }

    public void calcularTotalJuridico() {
        setTotalJuridico(getPagoCuentasJuridico() - getPagoJuridicoDado());

    }

    public void calcularTotalUrbanizacion() {
        setTotalPagarUrbanizacion(getPagoUrbanizacion());
    }

    public void paidUrbanizacion() {
        getNuevoDetalleLoteUrbanizacion().setLote(getSelectedLote());
        getNuevoDetalleLoteUrbanizacion().setCreatedOn(getFechaPagoUrbanizacion());
        getNuevoDetalleLoteUrbanizacion().setSaldoAnterior(getSelectUrbanizacion().getCostoPorLote());
        getNuevoDetalleLoteUrbanizacion().setSaldoPagado(getPagoUrbanizacion());
        getNuevoDetalleLoteUrbanizacion().setSaldoNuevo(getSelectUrbanizacion().getCostoPorLote() - getPagoUrbanizacion());
        getNuevoDetalleLoteUrbanizacion().setUrbanizacion(getSelectUrbanizacion());
        boolean success = getDetalleLoteUrbanizacionController().addDetalleLoteUrbanizacion(getNuevoDetalleLoteUrbanizacion(), getLoggedUser());
        if (success) {
            showMessage(FacesMessage.SEVERITY_INFO,
                    "Pago Urbanizacion",
                    "El pago de guardo de manera correcta.");

        } else {
            showMessage(FacesMessage.SEVERITY_INFO,
                    "Pago Urbanizacion",
                    "El pago no se guardo de manera correcta.");
        }

    }

    public void addDetalleLoteEtapa() {
        setEtapaJuridicoSeleccionada(getEtapaJuridicoController().fillEtapaJuridicoById(getIdEtapa()));
        getNuevoDetalleLoteEtapa().setDescripcion(getDescipcionJuridico());
        getNuevoDetalleLoteEtapa().setDeudaTotal(getPagoCuentasJuridico());
        getNuevoDetalleLoteEtapa().setEstapaJuridico(getEtapaJuridicoSeleccionada());
        getNuevoDetalleLoteEtapa().setLote(getSelectedLote());
        getNuevoDetalleLoteEtapa().setEstatusActivo(GenericEnumType.ENABLED);
        try {
            getDetalleLoteEtapaController().addDetalleLoteEtapa(getNuevoDetalleLoteEtapa(), getLoggedUser());
            limpiarLotesJuridico();
            setNuevoDetalleLoteEtapa(new DetalleLoteEtapa());
            showMessage(FacesMessage.SEVERITY_INFO,
                    "Detalle lote estapa",
                    "Se guardo de manera correcta");
        } catch (Exception e) {
            showMessage(FacesMessage.SEVERITY_INFO,
                    "Detalle lote estapa",
                    "No se guardo de manera correcta.");
        }
    }

    private void limpiarLotesJuridico() {
        for (int i = 0; i <= getLotes().size() - 1; i++) {
            long numero = getDetalleLoteEtapaController().contarLoteEtapabyLote(getLotes().get(i), getLoggedUser().getLocation());
            if (numero == 0) {
                getLotes().remove(i);
                i--;
            }
        }
    }

    public void actionNull() {

    }

    public void actualizarTotal() {
        setComboCobranza(false);
        setPagoDado(getSelectAbono().getPago());
        setComboMandados(false);
        setTotalPagar(getSelectAbono().getPago());
        setMandadoDado(getSelectAbono().getLote().getManzana().getPredio().getMandado());
        setCobranzaDada(getSelectAbono().getLote().getManzana().getPredio().getCobranzaAtraso());
    }

    public void updateLotes() {
        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;
        }
        setCobranzaController(new CobranzaController());
        setLotes(getCobranzaController().fillLoteByFolioOrCliente(getFolioLote(), getSelectUser()));
        limpiarLotesJuridico();
        List<String> listaIdsLotes = new ArrayList<>();
        for (int i = 0; i <= getLotes().size() - 1; i++) {
            listaIdsLotes.add(getLotes().get(i).getManzana().getPredio().getId());
        }
        Set<String> conjunto = new HashSet<>(listaIdsLotes);
        List<String> listaUnicaIdsLotes = new ArrayList<>(conjunto);
        Map<String, Boolean> validacionLotes = new HashMap<>();
        for (int i = 0; i <= listaUnicaIdsLotes.size() - 1; i++) {
            boolean comprobar = getUrbanizacionController().checkIfUrbanizacionExistsByPredio(listaUnicaIdsLotes.get(i));
            validacionLotes.put(listaUnicaIdsLotes.get(i), comprobar);
        }
        for (String key : validacionLotes.keySet()) {
            Boolean value = validacionLotes.get(key);
            for (int i = 0; i <= getLotes().size() - 1; i++) {
                if (getLotes().get(i).getManzana().getPredio().getId().equals(key)) {
                    getLotes().get(i).setCargarUrbanizacion(value);
                }
            }
        }

    }

    public void fillAbonoLoteByLote() {
        setCobranzaController(new CobranzaController());
        setAbonos(getCobranzaController().fillAbonoLoteByLote(getSelectedLote()));

        try {
            for (int i = 0; i <= getAbonos().size() - 1; i++) {
                Integer suma = i + 1;
                getAbonos().get(i).setNumeroAbono(String.valueOf(suma));
            }
        } catch (Exception e) {
            System.out.println("error: " + e);
        }

    }

    public void fillAbonoLoteByLoteJuridico() {
        setCobranzaController(new CobranzaController());
        setAbonos(getCobranzaController().fillAbonoLoteByLote(getSelectedLote()));
        setTotalJuridico();
        setPagoCuentasJuridico(getTotalJuridico());
    }

    public void consultarAbonosRestantes() {
        setCobranzaController(new CobranzaController());
        // extraigo los abonos extra que no este pagados
        List<AbonoLote> abonosRestantesExtra = getCobranzaController().fillAbonoLoteExtraByLoteAndPagoEstatusAndMensualidad(getSelectedLote(), GenericEnumType.DISABLED, getSelectedLote().getMensualidad());
        // se ectraen los abonos lote que no estenten pagados
        List<AbonoLote> abonosRestantes;
        // verifico si existen pagos extra
        if (abonosRestantesExtra.isEmpty()) {
            abonosRestantes = getCobranzaController().fillAbonoLoteByLoteNoExtraAndPagoEstatusAndMensualidad(getSelectedLote(), GenericEnumType.DISABLED, 0.0);
        } else {
            abonosRestantes = getCobranzaController().fillAbonoLoteByLoteNoExtraAndPagoEstatusAndMensualidad(getSelectedLote(), GenericEnumType.DISABLED, abonosRestantesExtra.get(0).getPago());
        }
        Double total = 0.0;
        if (!abonosRestantes.isEmpty()) {
            for (AbonoLote abonosR : abonosRestantes) {
                total = total + abonosR.getPago();
            }
        }
        setTotalAbonosRestantes(total);
    }

    public void generarConvenio() {
        logger.info("Generando convenio");
        try {
            setCobranzaController(new CobranzaController());
            setAbonoLoteController(new AbonoLoteController());
            // extraigo los abonos extra que no este pagados
            List<AbonoLote> abonosRestantesExtra = getCobranzaController().fillAbonoLoteExtraByLoteAndPagoEstatusAndMensualidad(getSelectedLote(), GenericEnumType.DISABLED, getSelectedLote().getMensualidad());
            // se ectraen los abonos lote que no estenten pagados
            List<AbonoLote> abonosRestantes;
            // verifico si existen pagos extra
            if (!abonosRestantesExtra.isEmpty()) {
                abonosRestantes = getCobranzaController().fillAbonoLoteByLoteNoExtraAndPagoEstatusAndMensualidad(getSelectedLote(), GenericEnumType.DISABLED, abonosRestantesExtra.get(0).getPago());
            } else {
                abonosRestantes = getCobranzaController().fillAbonoLoteByLoteNoExtraAndPagoEstatusAndMensualidad(getSelectedLote(), GenericEnumType.DISABLED, -1.0);
            }
            // se valida que existan abonos lote
            if (!abonosRestantes.isEmpty()) {
                Double total = 0.0;
                for (AbonoLote abonosR : abonosRestantes) {
                    total = total + abonosR.getPago();
                }
                //Definición de la fecha de inicio y numero de pagos
                Calendar fechaInicial = Calendar.getInstance();
                fechaInicial.setTime(abonosRestantes.get(0).getFechaAPagar());
                // Se genera la lista de fechas
                List<Calendar> fechasDePago = generarFechasDePago(fechaInicial, getNewPagoPorConvenio(), total, getSelectedLote().getPeriodoPago() == PeriodoPago.MENSUAL);
                // SE ELIMINAN LOS ABONOS RESTANTES ANTES DE INSERTAR LOS DE REAJUSTADOS
                logger.info("Eliminado abono no pagados del lote ");
                for (AbonoLote abonosR : abonosRestantes) {
                    try {
                        getAbonoLoteController().deleteAbonoLote(abonosR);
                    } catch (Exception e) {
                        logger.error("Ocurrió un error al eliminar el abono lote: " + abonosR.getId());
                    }
                }
                // CREACIÓN DE PAGOS POR FECHA
                setActualizarPago(total);
                recorrerFechas(fechasDePago, getSelectedLote(), getNewPagoPorConvenio());
                showMessage(FacesMessage.SEVERITY_INFO, "Restructuración completada", "Los abonos se estructuraron correctamente a abonos de: $" + getNewPagoPorConvenio());
            } else {
                logger.error("No se encontraron abonos restantes");
                showMessage(FacesMessage.SEVERITY_WARN, "Error", "No se puede generar un convenio para un lote sin abonos restantes");
            }
        } catch (Exception e) {
            logger.error("generarConvenio()");
            showMessage(FacesMessage.SEVERITY_WARN, "Error", "Error al generar el convenio");
        }
    }

    private void recorrerFechas(List<Calendar> fechas, Lote lote, Double pagoPorMes) {
        logger.info("Insertando abonos por fecha");
        // Usamos Collections.sort() para ordenar la lista de fechas
        Collections.sort(fechas, new Comparator<Calendar>() {
            @Override
            public int compare(Calendar fecha1, Calendar fecha2) {
                // Comparamos las fechas usando el método compareTo()
                return fecha1.compareTo(fecha2);
            }
        });

        // recorre las fechas ordenadas
        int contador = 0;
        for (Calendar fecha : fechas) {
            contador++;
            try {
                setAbonoLoteController(new AbonoLoteController());
                AbonoLote abono = new AbonoLote();
                abono.setLote(lote);
                abono.setCliente(lote.getCliente());
                abono.setTipoAbono(TipoAbono.ABONO);
                abono.setEstatusActivo(GenericEnumType.ENABLED);
                abono.setPagoEstatus(GenericEnumType.DISABLED);
                abono.setConvenio(1);
                abono.setFechaAPagar(fecha.getTime());
                abono.setSaldoAnterior(getActualizarPago());
                // se valida si es el ultimo abono para colocar el rediduo de reajuste
                if (contador == fechas.size() && getResiduoReajuste() > 0) {
                    abono.setPago(getResiduoReajuste());
                    setActualizarPago(getActualizarPago() - getResiduoReajuste());
                    abono.setSaldoNuevo(getActualizarPago());
                } else {
                    abono.setPago(pagoPorMes);
                    setActualizarPago(getActualizarPago() - pagoPorMes);
                    abono.setSaldoNuevo(getActualizarPago());
                }
                abono.setSaldoNuevo(getActualizarPago());
                abono.setCreatedBy(getLoggedUser());
                abono.setCreatedOn(new Date());
                getAbonoLoteController().addAbonoLote(abono, getLoggedUser());
            } catch (Exception e) {
                logger.error("Error al capturar el abono del dia: (" + fecha + ") " + e);
                showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Error al capturar el abono del dia (" + fecha + ")");
            }
        }
    }

    public List<Calendar> generarFechasDePago(Calendar fechaInicial, Double montoconvenio, Double totalAbonos, Boolean mensual) {
        logger.info("Generación fechas");
        // Lista de fechas vacia
        List<Calendar> fechasDePago = new ArrayList<>();
        // Se introduse la fecha de inicio
        fechasDePago.add(fechaInicial);
        Calendar fechaActual = (Calendar) fechaInicial.clone();
        // Captura el dia de una fecha en caso de que no se encuntre en le mes siguinte 
        boolean detenerFecha = false;
        Calendar fechaDetenida = Calendar.getInstance();

        Integer numeroPagos = (int) Math.floor(totalAbonos / montoconvenio);
        Double residuo = totalAbonos % montoconvenio;
        setResiduoReajuste(residuo);

        // se agrega una fecha mas para el residuo
        if (residuo > 0) {
            numeroPagos++;
        }
        // se generan la lista de fechas        
        if (mensual) {
            for (int i = 1; i < numeroPagos; i++) {
                Calendar fechaSiguiente = (Calendar) fechaActual.clone();
                fechaSiguiente.add(Calendar.MONTH, 1);
                if (detenerFecha == false) {
                    if (fechaActual.get(Calendar.DAY_OF_MONTH) > fechaSiguiente.getActualMaximum(Calendar.DAY_OF_MONTH)) {
                        detenerFecha = true;
                        fechaDetenida = (Calendar) fechaActual.clone();
                        fechaSiguiente.set(Calendar.DAY_OF_MONTH, fechaSiguiente.getActualMaximum(Calendar.DAY_OF_MONTH));
                    }
                } else {
                    if (fechaSiguiente.get(Calendar.DAY_OF_MONTH) <= fechaDetenida.get(Calendar.DAY_OF_MONTH)) {
                        detenerFecha = false;
                        fechaSiguiente.set(Calendar.DAY_OF_MONTH, fechaDetenida.get(Calendar.DAY_OF_MONTH));
                    } else {
                        fechaSiguiente.set(Calendar.DAY_OF_MONTH, fechaSiguiente.getActualMaximum(Calendar.DAY_OF_MONTH));
                    }
                }
                fechasDePago.add(fechaSiguiente);
                fechaActual = fechaSiguiente;
            }
        } else {
            for (int i = 0; i < numeroPagos;) {
                Calendar fechaSiguiente = (Calendar) fechaActual.clone();
                fechaSiguiente.set(Calendar.DAY_OF_MONTH, 15);
                fechasDePago.add(fechaSiguiente);
                i++;

                if (i < numeroPagos) {
                    fechaSiguiente = (Calendar) fechaActual.clone();
                    fechaSiguiente.set(Calendar.DAY_OF_MONTH, fechaSiguiente.getActualMaximum(Calendar.DAY_OF_MONTH));
                    fechasDePago.add(fechaSiguiente);
                    i++;
                }
                fechaActual.add(Calendar.MONTH, 1);
            }
        }
        return fechasDePago;
    }

    public void fillUrbanizacionByProyect() {
        setListaUrbanizacion(getUrbanizacionController().fillAllUrbanizacionesByPredio(getSelectedLote().getManzana().getPredio()));
        for (int i = 0; i <= getListaUrbanizacion().size() - 1; i++) {
            List<DetalleLoteUrbanizacion> detalleUrbanizacion = getDetalleLoteUrbanizacionController().buscarDetallesLotesPorLotes(getSelectedLote().getId(), getListaUrbanizacion().get(i).getId());
            if (detalleUrbanizacion.size() != 0) {
                getListaUrbanizacion().get(i).setCostoPorLote(detalleUrbanizacion.get(0).getSaldoNuevo());
            }
        }

    }

    private void setTotalJuridico() {
        for (int i = 0; i <= getAbonos().size() - 1; i++) {
            if (getAbonos().get(i).getPagoEstatus().equals(GenericEnumType.ENABLED)) {

            } else {
                setTotalJuridico(getTotalJuridico() + getAbonos().get(i).getPago());
            }
        }
    }

    public void payAbono() {
        logger.info("init payAbono");
        setCobranzaController(new CobranzaController());
        System.out.println(getFechaPago());
        try {

            // Se valida si el proyecto del lote cuenta con una abreviación
            String abreviacion = getSelectAbono().getLote().getManzana().getPredio().getAbreviatura();
            if (abreviacion == null || abreviacion.isEmpty()) {
                showMessage(FacesMessage.SEVERITY_WARN, "Error",
                        "Debe de definir una abreviación para el proyecto, ya que es requerida para crear el folio");
                return;
            }
            abreviacion = abreviacion+"-";

            // Redondeo el pago esperado a 2 decimales para verificar que el pago dado no sea mayor al esperado
            BigDecimal bd = new BigDecimal(getSelectAbono().getPago());
            bd = bd.setScale(2, RoundingMode.HALF_UP);
            double pagoRedondeado = bd.doubleValue();
            // valido que el abono dado no sea mayor a abono a dar 
            if (getPagoDado() <= pagoRedondeado) {
                setCobranzaController(new CobranzaController());
                getSelectAbono().setPagoEstatus(GenericEnumType.ENABLED);

                //Verificar si ahi una diferencia de pago en el ultimo abono actualizado
                //AbonoLote ultimoBonoActulizado = getCobranzaController().fillLastUpdateAbonoLoteByLote(getSelectAbono().getLote());                    
                getSelectAbono().setDiferenciaPago(getSelectAbono().getPago() - getPagoDado());

                getSelectAbono().setCantidadPagada(getPagoDado());
                getSelectAbono().setDescripcion(getDescripcionPago());
                setUrbanizacionController(new UrbanizacionController());

                setTotalDado(getPagoDado());
                Calendar fecha = Calendar.getInstance();
                fecha.setTime(new Date());
                fecha.add(Calendar.DATE, 1);
                getSelectAbono().setLastUpdatedOn(fecha.getTime());
                if (getComboCobranza() == true) {
                    getSelectAbono().setCobranzaPagar(getSelectedLote().getManzana().getPredio().getCobranzaAtraso());
                    getSelectAbono().setCobranzaPagada(getCobranzaDada());
                } else {
                    setCobranzaDada(0D);
                    getSelectAbono().setCobranzaPagada(0D);
                    getSelectAbono().setCobranzaPagar(0D);
                }
                if (getComboMandados() == true) {
                    getSelectAbono().setMandadoPagar(getSelectedLote().getManzana().getPredio().getMandado());
                    getSelectAbono().setMandadoPagado(getMandadoDado());
                } else {
                    getSelectAbono().setMandadoPagar(0D);
                    getSelectAbono().setMandadoPagado(0D);
                    setMandadoDado(0D);
                }

                 // Se cargan los abonos para validar el folio
                AbonosView ultimoFolio = getCobranzaController().fillAbonosViewByFolioAndProyecto(getSelectAbono().getLote().getManzana().getPredio().getId(), abreviacion);

                // Se valida si ya existen folios registrados para el proyecto y se le asigna el último encontrado
                int consecutivo = 0;
                if (ultimoFolio != null) {
                    String folior = ultimoFolio.getFolio(); // Reemplaza con tu variable que contiene el folio
                    // Dividir el folio en partes utilizando el guion como separador
                    String[] partes = folior.split("-");
                    // Obtener la parte del consecutivo
                    String consecutivoParte = partes[4];
                    // Convertir el consecutivo a un entero
                    consecutivo = Integer.parseInt(consecutivoParte);
                }

                // se formatea la fecha                
                SimpleDateFormat formatoF = new SimpleDateFormat("dd-MM-yyyy");
                String fechaFormateada = formatoF.format(new Date());

                // se formatea el consecutivo                                         
                String numeroFormateado = String.format("%06d", consecutivo + 1);
                String folio;
                if (consecutivo == 0) {
                    folio = abreviacion + fechaFormateada + "-" + "000001";
                } else {
                    folio = abreviacion + fechaFormateada + "-" + numeroFormateado;
                }
                
                // se coloca el folioa la bono
                getSelectAbono().setFolio(folio);

                getCobranzaController().addAbonoLoteWithJuridico(getSelectAbono(), getLoggedUser(), false);
                DecimalFormat formato = new DecimalFormat("#.##");
                String resultado = formato.format(getTotalPagar());
                setTotalPagar(Double.valueOf(resultado));
                // Se consultan los registros en DetalleLoteEtapa para actualizar el último registro asociado al lote seleccionado
                setDetalleLoteEtapaList(getDetalleLoteEtapaController().fillDetalleLoteEtapaByLote(getSelectedLote()));
                getDetalleLoteEtapaList().get(0).setDeudaTotal(getDetalleLoteEtapaList().get(0).getDeudaTotal() - getPagoDado());
                getDetalleLoteEtapaController().addDetalleLoteEtapa(getDetalleLoteEtapaList().get(0), getLoggedUser());
                setTotalJuridico(0.0);
                setDetalleLoteEtapaList(getDetalleLoteEtapaController().fillDetalleLoteEtapaByLote(getSelectedLote()));
                setPagoExitoso(true);
                showMessage(FacesMessage.SEVERITY_INFO, "Pagado", "Abono pagado correctamente ");
            } else {
                setPagoExitoso(false);
                showMessage(FacesMessage.SEVERITY_ERROR, "Error", "El pago dado no puede ser mayor al pago predefinido");
            }
        } catch (Exception e) {
            logger.error("payAbono: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Error al pagar");
        }

    }

    public void fillEtapasJuridicas() {
        setDetalleLoteEtapaList(getDetalleLoteEtapaController().fillDetalleLoteEtapaByLote(getSelectedLote()));
    }

    public void resetTotalJuridico() {
        setTotalJuridico(0.0);
    }

    public PreventaController getControladorPreventa() {
        return controladorPreventa;
    }

    public void setControladorPreventa(PreventaController controladorPreventa) {
        this.controladorPreventa = controladorPreventa;
    }

    public List<Lote> getLotes() {
        return lotes;
    }

    public void setLotes(List<Lote> lotes) {
        this.lotes = lotes;
    }

    public List<PersonListView> getPersonas() {
        return personas;
    }

    public void setPersonas(List<PersonListView> personas) {
        this.personas = personas;
    }

    public String getSelectUser() {
        return selectUser;
    }

    public void setSelectUser(String selectUser) {
        this.selectUser = selectUser;
    }

    public String getFolioLote() {
        return folioLote;
    }

    public void setFolioLote(String folioLote) {
        this.folioLote = folioLote;
    }

    public Lote getSelectedLote() {
        return selectedLote;
    }

    public void setSelectedLote(Lote selectedLote) {
        this.selectedLote = selectedLote;
    }

    public List<AbonoLote> getAbonos() {
        return abonos;
    }

    public void setAbonos(List<AbonoLote> abonos) {
        this.abonos = abonos;
    }

    public AbonoLote getSelectAbono() {
        return selectAbono;
    }

    public void setSelectAbono(AbonoLote selectAbono) {
        this.selectAbono = selectAbono;
    }

    public CobranzaController getCobranzaController() {
        return cobranzaController;
    }

    public void setCobranzaController(CobranzaController cobranzaController) {
        this.cobranzaController = cobranzaController;
    }

    public Double getPagoDado() {
        return pagoDado;
    }

    public void setPagoDado(Double pagoDado) {
        this.pagoDado = pagoDado;
    }

    public Date getFechaPago() {
        return FechaPago;
    }

    public Boolean getComboMandados() {
        return comboMandados;
    }

    public void setComboMandados(Boolean comboMandados) {
        this.comboMandados = comboMandados;
    }

    public Boolean getComboCobranza() {
        return comboCobranza;
    }

    public void setComboCobranza(Boolean comboCobranza) {
        this.comboCobranza = comboCobranza;
    }

    public Double getMandadoDado() {
        return mandadoDado;
    }

    public void setMandadoDado(Double mandadoDado) {
        this.mandadoDado = mandadoDado;
    }

    public Double getCobranzaDada() {
        return cobranzaDada;
    }

    public void setCobranzaDada(Double cobranzaDada) {
        this.cobranzaDada = cobranzaDada;
    }

    public void setFechaPago(Date FechaPago) {
        this.FechaPago = FechaPago;
    }

    public GenericValidationController getGenericController() {
        return genericController;
    }

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

    public Double getTotalPagar() {
        return totalPagar;
    }

    public void setTotalPagar(Double totalPagar) {
        this.totalPagar = totalPagar;
    }

    public String getDescripcionPago() {
        return descripcionPago;
    }

    public void setDescripcionPago(String descripcionPago) {
        this.descripcionPago = descripcionPago;
    }

    public Double getTotalDado() {
        return totalDado;
    }

    public void setTotalDado(Double totalDado) {
        this.totalDado = totalDado;
    }

    public List<Urbanizacion> getListaUrbanizacion() {
        return listaUrbanizacion;
    }

    public void setListaUrbanizacion(List<Urbanizacion> listaUrbanizacion) {
        this.listaUrbanizacion = listaUrbanizacion;
    }

    public UrbanizacionController getUrbanizacionController() {
        return urbanizacionController;
    }

    public void setUrbanizacionController(UrbanizacionController urbanizacionController) {
        this.urbanizacionController = urbanizacionController;
    }

    public Urbanizacion getSelectedUrbanizacion() {
        return selectedUrbanizacion;
    }

    public void setSelectedUrbanizacion(Urbanizacion selectedUrbanizacion) {
        this.selectedUrbanizacion = selectedUrbanizacion;
    }

    public DetalleLoteUrbanizacionController getDetalleLoteUrbanizacionController() {
        return detalleLoteUrbanizacionController;
    }

    public void setDetalleLoteUrbanizacionController(DetalleLoteUrbanizacionController detalleLoteUrbanizacionController) {
        this.detalleLoteUrbanizacionController = detalleLoteUrbanizacionController;
    }

    public Urbanizacion getSelectUrbanizacion() {
        return selectUrbanizacion;
    }

    public void setSelectUrbanizacion(Urbanizacion selectUrbanizacion) {
        this.selectUrbanizacion = selectUrbanizacion;
    }

    public Double getPagoUrbanizacion() {
        return pagoUrbanizacion;
    }

    public void setPagoUrbanizacion(Double pagoUrbanizacion) {
        this.pagoUrbanizacion = pagoUrbanizacion;
    }

    public Double getTotalPagarUrbanizacion() {
        return totalPagarUrbanizacion;
    }

    public void setTotalPagarUrbanizacion(Double totalPagarUrbanizacion) {
        this.totalPagarUrbanizacion = totalPagarUrbanizacion;
    }

    public DetalleLoteUrbanizacion getNuevoDetalleLoteUrbanizacion() {
        return nuevoDetalleLoteUrbanizacion;
    }

    public void setNuevoDetalleLoteUrbanizacion(DetalleLoteUrbanizacion nuevoDetalleLoteUrbanizacion) {
        this.nuevoDetalleLoteUrbanizacion = nuevoDetalleLoteUrbanizacion;
    }

    public Date getFechaPagoUrbanizacion() {
        return fechaPagoUrbanizacion;
    }

    public void setFechaPagoUrbanizacion(Date fechaPagoUrbanizacion) {
        this.fechaPagoUrbanizacion = fechaPagoUrbanizacion;
    }

    public List<EtapasJuridico> getListaEtapasJuridico() {
        return listaEtapasJuridico;
    }

    public void setListaEtapasJuridico(List<EtapasJuridico> listaEtapasJuridico) {
        this.listaEtapasJuridico = listaEtapasJuridico;
    }

    public EtapasJuridico getEtapaJuridicoSeleccionada() {
        return etapaJuridicoSeleccionada;
    }

    public void setEtapaJuridicoSeleccionada(EtapasJuridico etapaJuridicoSeleccionada) {
        this.etapaJuridicoSeleccionada = etapaJuridicoSeleccionada;
    }

    public EtapasJuridicoController getEtapaJuridicoController() {
        return etapaJuridicoController;
    }

    public void setEtapaJuridicoController(EtapasJuridicoController etapaJuridicoController) {
        this.etapaJuridicoController = etapaJuridicoController;
    }

    public String getEtapaJuridicoComentario() {
        return etapaJuridicoComentario;
    }

    public void setEtapaJuridicoComentario(String etapaJuridicoComentario) {
        this.etapaJuridicoComentario = etapaJuridicoComentario;
    }

    public Double getTotalJuridico() {
        return totalJuridico;
    }

    public void setTotalJuridico(Double totalJuridico) {
        this.totalJuridico = totalJuridico;
    }

    public Double getPagoJuridicoDado() {
        return pagoJuridicoDado;
    }

    public void setPagoJuridicoDado(Double pagoJuridicoDado) {
        this.pagoJuridicoDado = pagoJuridicoDado;
    }

    public Double getPagoCuentasJuridico() {
        return pagoCuentasJuridico;
    }

    public void setPagoCuentasJuridico(Double pagoCuentasJuridico) {
        this.pagoCuentasJuridico = pagoCuentasJuridico;
    }

    public DetalleLoteEtapa getNuevoDetalleLoteEtapa() {
        return nuevoDetalleLoteEtapa;
    }

    public void setNuevoDetalleLoteEtapa(DetalleLoteEtapa nuevoDetalleLoteEtapa) {
        this.nuevoDetalleLoteEtapa = nuevoDetalleLoteEtapa;
    }

    public String getDescipcionJuridico() {
        return descipcionJuridico;
    }

    public void setDescipcionJuridico(String descipcionJuridico) {
        this.descipcionJuridico = descipcionJuridico;
    }

    public DetalleLoteEtapaController getDetalleLoteEtapaController() {
        return detalleLoteEtapaController;
    }

    public void setDetalleLoteEtapaController(DetalleLoteEtapaController detalleLoteEtapaController) {
        this.detalleLoteEtapaController = detalleLoteEtapaController;
    }

    public String getIdEtapa() {
        return idEtapa;
    }

    public void setIdEtapa(String idEtapa) {
        this.idEtapa = idEtapa;
    }

    public Double getTotalAbonosRestantes() {
        return totalAbonosRestantes;
    }

    public void setTotalAbonosRestantes(Double totalAbonosRestantes) {
        this.totalAbonosRestantes = totalAbonosRestantes;
    }

    public List<AbonoLote> getAbonosRestantes() {
        return abonosRestantes;
    }

    public void setAbonosRestantes(List<AbonoLote> abonosRestantes) {
        this.abonosRestantes = abonosRestantes;
    }

    public Double getNewPagoPorConvenio() {
        return newPagoPorConvenio;
    }

    public void setNewPagoPorConvenio(Double newPagoPorConvenio) {
        this.newPagoPorConvenio = newPagoPorConvenio;
    }

    public Double getResiduoReajuste() {
        return residuoReajuste;
    }

    public void setResiduoReajuste(Double residuoReajuste) {
        this.residuoReajuste = residuoReajuste;
    }

    public Double getActualizarPago() {
        return actualizarPago;
    }

    public void setActualizarPago(Double actualizarPago) {
        this.actualizarPago = actualizarPago;
    }

    public AbonoLoteController getAbonoLoteController() {
        return abonoLoteController;
    }

    public void setAbonoLoteController(AbonoLoteController abonoLoteController) {
        this.abonoLoteController = abonoLoteController;
    }

    public List<String> getListaIdsLotesJuridico() {
        return listaIdsLotesJuridico;
    }

    public void setListaIdsLotesJuridico(List<String> listaIdsLotesJuridico) {
        this.listaIdsLotesJuridico = listaIdsLotesJuridico;
    }

    public List<DetalleLoteEtapa> getListaDetalleLote() {
        return listaDetalleLote;
    }

    public void setListaDetalleLote(List<DetalleLoteEtapa> listaDetalleLote) {
        this.listaDetalleLote = listaDetalleLote;
    }

    public List<Person> getListaPersonas() {
        return listaPersonas;
    }

    public void setListaPersonas(List<Person> listaPersonas) {
        this.listaPersonas = listaPersonas;
    }

    public List<Lote> getListaLote() {
        return listaLote;
    }

    public void setListaLote(List<Lote> listaLote) {
        this.listaLote = listaLote;
    }

    public DetalleLoteEtapa getDetalleLoteEtapa() {
        return detalleLoteEtapa;
    }

    public void setDetalleLoteEtapa(DetalleLoteEtapa detalleLoteEtapa) {
        this.detalleLoteEtapa = detalleLoteEtapa;
    }

    public CustomerController getCustomerController() {
        return customerController;
    }

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

    public List<String> getIdPersonasUnicos() {
        return idPersonasUnicos;
    }

    public void setIdPersonasUnicos(List<String> idPersonasUnicos) {
        this.idPersonasUnicos = idPersonasUnicos;
    }

    public List<DetalleLoteEtapa> getDetalleLoteEtapaList() {
        return detalleLoteEtapaList;
    }

    public void setDetalleLoteEtapaList(List<DetalleLoteEtapa> detalleLoteEtapaList) {
        this.detalleLoteEtapaList = detalleLoteEtapaList;
    }

    public Boolean getPagoExitoso() {
        return PagoExitoso;
    }

    public void setPagoExitoso(Boolean PagoExitoso) {
        this.PagoExitoso = PagoExitoso;
    }

}
