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

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.ClosingDayController;
import com.arrebol.taxiservicios.controller.cobranza.CobranzaController;
import com.arrebol.taxiservicios.controller.predio.CambiaLoteController;
import com.arrebol.taxiservicios.controller.predio.DevolucionAbonoController;
import com.arrebol.taxiservicios.controller.predio.LoteController;
import com.arrebol.taxiservicios.model.admin.ClosingDay;
import com.arrebol.taxiservicios.model.enums.EstatusPagoMultiple;
import com.arrebol.taxiservicios.model.enums.EstatusSolicitud;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.TipoCaseacionFolio;
import com.arrebol.taxiservicios.model.predio.AbonoLote;
import com.arrebol.taxiservicios.model.predio.AbonoLoteDetalle;
import com.arrebol.taxiservicios.model.predio.DevolucionAbono;
import com.arrebol.taxiservicios.model.predio.DevolucionAbonoEntrada;
import com.arrebol.taxiservicios.model.predio.FoliosCancelados;
import com.arrebol.taxiservicios.model.predio.Lote;
import com.arrebol.taxiservicios.model.predio.SolicitudDevolucionAbonoMultiple;
import java.io.Serializable;
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.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 *
 * @author Crov
 */
@Named("devolucionAbonosMultiplesBean")
@ViewScoped
public class DevolucionAbonosMultiplesBean extends TaxiGenericBean implements Serializable {

    private static final long serialVersionUID = -7284027390656669184L;
    final Logger logger = LogManager.getLogger(getClass());

    private CobranzaController cobranzaController;
    private LoteController loteController;
    private List<SolicitudDevolucionAbonoMultiple> ListSolicitudes;
    private SolicitudDevolucionAbonoMultiple selectedSolicitud;
    private DevolucionAbonoController devolucionAbonoController;
    private ClosingDayController closingDayController;

    @PostConstruct
    public void init() {

        try {
            setCobranzaController(new CobranzaController());
            setListSolicitudes(getCobranzaController().fillSolicitudDevolucionAbonoMultipleByLocation(getLoggedUser().getLocation().getId()));
        } catch (Exception e) {
            logger.error("init", e);
        }
    }

    public void aprobarCancelacion() {
        logger.info("aprobarCancelacion");
        try {
            setCobranzaController(new CobranzaController());
            setLoteController(new LoteController());
            setDevolucionAbonoController(new DevolucionAbonoController());
            setClosingDayController(new ClosingDayController());

            // Se devuelven los abonos al estatus de no pagado 
            List<AbonoLote> abonosLote = getCobranzaController().fillAbonoLoteByHitorialAbonoMultiple(getSelectedSolicitud().getHitorialAbonoMultiple().getId());
            for (AbonoLote abono : abonosLote) {

                Double totalSubAbonos = 0.0;
                // Se deshabilitan los sub abonos si lo hay 
                List<AbonoLoteDetalle> abonoLoteDetalle = getCobranzaController().fillAbonoLoteDetalleByHitorialAbonoMultiple(getSelectedSolicitud().getHitorialAbonoMultiple().getId(), abono.getId());
                if (!abonoLoteDetalle.isEmpty()) {
                    for (AbonoLoteDetalle abD : abonoLoteDetalle) {
                        //se actuliza el abono lote detalle
                        abD.setEstatusActivo(GenericEnumType.DISABLED);
                        getCobranzaController().updateAbonoLoteDetalle(abD, getLoggedUser());
                        // Se guarda el total de los abonos múltiples cuando los ahí
                        totalSubAbonos = totalSubAbonos + abD.getPago();

                        // Se crea un nuevo registro en devolución abono salida
                        DevolucionAbono newDevolucion = new DevolucionAbono();
                        newDevolucion.setSolicitudDevolucionAbonoMultiple(getSelectedSolicitud());
                        newDevolucion.setLocation(getLoggedUser().getLocation());
                        newDevolucion.setPagoEstatus(GenericEnumType.ENABLED);
                        newDevolucion.setEstatusActivo(GenericEnumType.ENABLED);
                        newDevolucion.setCantidadDevuelta(abD.getPago());
                        newDevolucion.setSolicitante(getSelectedSolicitud().getCreatedBy());
                        getDevolucionAbonoController().addDevolucionAbono(newDevolucion, getLoggedUser(), true);

                        //Se obtinen el ultimo corte de caja                 
                        ClosingDay corteSub = getClosingDayController().findLastClosingDay(abD.getAbonoLote().getLote().getManzana().getPredio().getLocation().getId());

                        // Validar si la fecha del abono es posterior o higual a la fecha del último corte
                        if (abD.getCreatedOn().before(corteSub.getCreatedOn()) || abD.getCreatedOn().equals(corteSub.getCreatedOn())) {
                            logger.info("no nueva salida");
                        } else {
                            logger.info("nueva salida");
                            //Se crea un nuevo registro en devolución abono entrada
                            DevolucionAbonoEntrada newDevolucionEntrada = new DevolucionAbonoEntrada();
                            newDevolucionEntrada.setSolicitudDevolucionAbonoMultiple(getSelectedSolicitud());
                            newDevolucionEntrada.setLocation(getLoggedUser().getLocation());
                            newDevolucionEntrada.setPagoEstatus(GenericEnumType.ENABLED);
                            newDevolucionEntrada.setEstatusActivo(GenericEnumType.ENABLED);
                            newDevolucionEntrada.setCantidadDevuelta(abD.getPago());
                            newDevolucionEntrada.setSolicitante(getSelectedSolicitud().getCreatedBy());
                            getDevolucionAbonoController().addDevolucionAbonoEntrada(newDevolucionEntrada, getLoggedUser(), true);
                        }

                        // Se guarda registro del folio cancelado si lo tiene 
                        if (abD.getFolio() != null && !abD.getFolio().isEmpty()) {
                            FoliosCancelados foliosCancelados = new FoliosCancelados();
                            foliosCancelados.setFolio(abD.getFolio());
                            foliosCancelados.setPredio(abD.getAbonoLote().getLote().getManzana().getPredio());
                            foliosCancelados.setAbonoLote(abD.getAbonoLote());
                            foliosCancelados.setUserElimino(getLoggedUser());
                            foliosCancelados.setFechaEliminacion(new Date());
                            foliosCancelados.setTipoCaseacion(TipoCaseacionFolio.ABONO_MULTIPLE);
                            foliosCancelados.setMotivoCaseacion("SUB ABONO perteneciente al abono " + abD.getAbonoLote().getFechaAPagar() + ". Comentario: " + getSelectedSolicitud().getComentario());
                            getDevolucionAbonoController().addFoliosCancelados(foliosCancelados, getLoggedUser(), true);
                        }

                    }
                }

                // Se guarda registro del folio cancelado si lo tiene 
                if (!abono.getPagoEstatus().equals(GenericEnumType.INCOMPLETE)) {

                    // Se crea un nuevo registro en devolución abono salida
                    DevolucionAbono newDevolucion = new DevolucionAbono();
                    newDevolucion.setSolicitudDevolucionAbonoMultiple(getSelectedSolicitud());
                    newDevolucion.setLocation(getLoggedUser().getLocation());
                    newDevolucion.setPagoEstatus(GenericEnumType.ENABLED);
                    newDevolucion.setEstatusActivo(GenericEnumType.ENABLED);
                    newDevolucion.setCantidadDevuelta(abono.getCantidadPagada());
                    newDevolucion.setSolicitante(getSelectedSolicitud().getCreatedBy());
                    getDevolucionAbonoController().addDevolucionAbono(newDevolucion, getLoggedUser(), true);

                    //Se obtinen el ultimo corte de caja                 
                    ClosingDay corte = getClosingDayController().findLastClosingDay(abono.getLote().getManzana().getPredio().getLocation().getId());

                    // Validar si la fecha del abono es posterior o higual a la fecha del último corte
                    if (abono.getLastUpdatedOn().before(corte.getCreatedOn()) || abono.getLastUpdatedOn().equals(corte.getCreatedOn())) {
                        logger.info("no nueva salida");
                    } else {
                        logger.info("nueva salida");
                        //Se crea un nuevo registro en devolución abono entrada
                        DevolucionAbonoEntrada newDevolucionEntrada = new DevolucionAbonoEntrada();
                        newDevolucionEntrada.setSolicitudDevolucionAbonoMultiple(getSelectedSolicitud());
                        newDevolucionEntrada.setLocation(getLoggedUser().getLocation());
                        newDevolucionEntrada.setPagoEstatus(GenericEnumType.ENABLED);
                        newDevolucionEntrada.setEstatusActivo(GenericEnumType.ENABLED);
                        newDevolucionEntrada.setCantidadDevuelta(abono.getCantidadPagada());
                        newDevolucionEntrada.setSolicitante(getSelectedSolicitud().getCreatedBy());
                        getDevolucionAbonoController().addDevolucionAbonoEntrada(newDevolucionEntrada, getLoggedUser(), true);
                    }

                    if (abono.getFolio() != null && !abono.getFolio().isEmpty()) {
                        FoliosCancelados foliosCancelados = new FoliosCancelados();
                        foliosCancelados.setFolio(abono.getFolio());
                        foliosCancelados.setPredio(abono.getLote().getManzana().getPredio());
                        foliosCancelados.setAbonoLote(abono);
                        foliosCancelados.setUserElimino(getLoggedUser());
                        foliosCancelados.setFechaEliminacion(new Date());
                        foliosCancelados.setTipoCaseacion(TipoCaseacionFolio.ABONO_MULTIPLE);
                        foliosCancelados.setMotivoCaseacion(getSelectedSolicitud().getComentario());
                        getDevolucionAbonoController().addFoliosCancelados(foliosCancelados, getLoggedUser(), true);
                    }

                }

                // Se valida si el abono lote estaba incompleto antes de ser pagado por el abono multiple
                abono.setLastUpdatedOn(null);
                if (totalSubAbonos > 0.0 && totalSubAbonos < abono.getCantidadPagada()) {
                    abono.setPagoEstatus(GenericEnumType.INCOMPLETE);
                    abono.setCantidadPagada(abono.getCantidadPagada() - totalSubAbonos);
                    abono.setDiferenciaPago(abono.getPago() - abono.getCantidadPagada());
                    abono.setAbonoMultiple(null);
                } else {
                    abono.setPagoEstatus(GenericEnumType.DISABLED);
                    abono.setCantidadPagada(0.0);
                    abono.setDiferenciaPago(0.0);
                    abono.setCobranzaPagada(0D);
                    abono.setCobranzaPagar(0D);
                    abono.setMandadoPagado(0D);
                    abono.setMandadoPagar(0D);
                    abono.setDescripcion(null);
                    abono.setAbonoMultiple(null);
                    abono.setLastUpdatedOn(null);
                }
                // Se actualiza el abono lote 
                getCobranzaController().addAbonoLote(abono, getLoggedUser(), false);
            }

            // Se actualiza el monto pagado en el lote 
            Lote lote = getSelectedSolicitud().getHitorialAbonoMultiple().getLote();
            lote.setMontoPagado(lote.getMontoPagado() - getSelectedSolicitud().getMontoDevolucion());
            getLoteController().updateMontoPagado(lote, getLoggedUser());

            // Se actualiza la solicitud            
            getSelectedSolicitud().setEstatusSolicitud(EstatusSolicitud.APROBADO);
            getCobranzaController().addSolicitudDevolucionAbonoMultiple(getSelectedSolicitud(), getLoggedUser(), false);

            // Se actualiza el abono múltiple            
            getSelectedSolicitud().getHitorialAbonoMultiple().setEstatus(EstatusPagoMultiple.CANCELADO);
            getCobranzaController().addHitorialAbonoMultiple(getSelectedSolicitud().getHitorialAbonoMultiple(), getLoggedUser(), false);

            setListSolicitudes(getCobranzaController().fillSolicitudDevolucionAbonoMultipleByLocation(getLoggedUser().getLocation().getId()));

            logger.info("Solicitud aprobada");
            showMessage(FacesMessage.SEVERITY_INFO, "Solicitud aprobada", "La solicitud de caseación fue aprobada correctamente");
        } catch (Exception e) {
            showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al aprobar la solicitud de caseación");
            logger.error("aprobarCancelacion(): " + e);
        }
    }

    public void rechazarCancelacion() {
        logger.info("rechazarCancelacion");
        try {
            setCobranzaController(new CobranzaController());
            getSelectedSolicitud().setEstatusSolicitud(EstatusSolicitud.CANCELADO);
            getCobranzaController().addSolicitudDevolucionAbonoMultiple(getSelectedSolicitud(), getLoggedUser(), false);
            logger.info("Solicitud aprobada");
            showMessage(FacesMessage.SEVERITY_INFO, "Solicitud rechazada", "La solicitud de caseación fue rechazada correctamente");
        } catch (Exception e) {
            showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al rechazar la solicitud de caseación");
            logger.error("rechazarCancelacion(): " + e);
        }

    }

    public CobranzaController getCobranzaController() {
        return cobranzaController;
    }

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

    public List<SolicitudDevolucionAbonoMultiple> getListSolicitudes() {
        return ListSolicitudes;
    }

    public void setListSolicitudes(List<SolicitudDevolucionAbonoMultiple> ListSolicitudes) {
        this.ListSolicitudes = ListSolicitudes;
    }

    public SolicitudDevolucionAbonoMultiple getSelectedSolicitud() {
        return selectedSolicitud;
    }

    public void setSelectedSolicitud(SolicitudDevolucionAbonoMultiple selectedSolicitud) {
        this.selectedSolicitud = selectedSolicitud;
    }

    public LoteController getLoteController() {
        return loteController;
    }

    public void setLoteController(LoteController loteController) {
        this.loteController = loteController;
    }

    public DevolucionAbonoController getDevolucionAbonoController() {
        return devolucionAbonoController;
    }

    public void setDevolucionAbonoController(DevolucionAbonoController devolucionAbonoController) {
        this.devolucionAbonoController = devolucionAbonoController;
    }

    public ClosingDayController getClosingDayController() {
        return closingDayController;
    }

    public void setClosingDayController(ClosingDayController closingDayController) {
        this.closingDayController = closingDayController;
    }

}
