/*
 * 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.spa.DevolucionesController;
import com.arrebol.taxiservicios.controller.spa.VentasBeanController;
import com.arrebol.taxiservicios.model.admin.ClosingDay;
import com.arrebol.taxiservicios.model.enums.EstatusSolicitud;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.spa.DevolucionPagoVenta;
import com.arrebol.taxiservicios.model.spa.HistorialAbonoMultipleSpa;
import com.arrebol.taxiservicios.model.spa.Pagos;
import com.arrebol.taxiservicios.model.spa.PagosDetalle;
import com.arrebol.taxiservicios.model.spa.SolicitudDevolucionPagoVenta;
import com.arrebol.taxiservicios.model.spa.Ventas;
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("devolucionPagoBean")
@ViewScoped
public class AprobarDevolucionPagoBean extends TaxiGenericBean implements Serializable {

   private static final long serialVersionUID = -2400590341745672164L;
   final Logger logger = LogManager.getLogger(AprobarDevolucionPagoBean.class);

   private DevolucionesController devolucionesController;
   private VentasBeanController ventasBeanController;
   private ClosingDayController closingDayController;

   private List<SolicitudDevolucionPagoVenta> solicitudes;
   private SolicitudDevolucionPagoVenta selectSolicitud;

   @PostConstruct
   public void init() {
      logger.info("init");
      try {
         setDevolucionesController(new DevolucionesController());
         setVentasBeanController(new VentasBeanController());
         setSolicitudes(getDevolucionesController().fillSolicitudDevolucionPagoVentaByLocation(getLoggedUser().getLocation()));
      } catch (Exception e) {
         logger.error("init", e);
      }
   }

   public void aprobarCancelacion() {
      try {
         switch (getSelectSolicitud().getTipoPago()) {
            case ABONO:
               aprobarCancelacionP();
               break;
            case SUBABONO:
               aprobarCancelacionSubAbono();
               break;
            default:
               showMessage(FacesMessage.SEVERITY_INFO, "Error", "Tipo de abono a devolver no encontrado");
               break;
         }
      } catch (Exception e) {
         showMessage(FacesMessage.SEVERITY_INFO, "Error", "Ocurrió un error al tratar de aprobar la solicitud");
         logger.error("aprobarCancelacion(): " + e);
      }
   }

   public void aprobarCancelacionP() {
      try {
         // Se actualiza la solicitud de devolución
         getSelectSolicitud().setEstatusSolicitud(EstatusSolicitud.APROBADO);
         getDevolucionesController().addSolicitudDevolucionPagoVenta(getSelectSolicitud(), getLoggedUser(), false);
         // se actulisa el abono lote
         Pagos pago = getVentasBeanController().fillPagosById(getSelectSolicitud().getIdPagoODetalle());
         // Se guarda la fecha de actualización  del abono lote para verificarlos si le abono ya fue completado en el corte
         Date LastUpdatedOn = pago.getLastUpdatedOn();
         String idAbonoMuliple = pago.getAbonoMultiple() != null ? pago.getAbonoMultiple().getId() : null;
         // se resetea el estatus del pago a disponible
         pago.setPagoEstatus(GenericEnumType.DISABLED);
         pago.setFolio(null);
         pago.setMetodoPago(null);
         pago.setCantidadPagada(null);
         pago.setDiferenciaPago(null);
         pago.setFechaPago(null);
         pago.setCobro(null);
         pago.setLastUpdatedBy(null);
         pago.setLastUpdatedOn(null);
         getVentasBeanController().addPagos(pago, getLoggedUser(), false);

         // Se desactivan los abonos lote detalle si los hay
         List<PagosDetalle> subAbonos = getVentasBeanController().fillPagosDetalleByPagos(pago);
         if (!subAbonos.isEmpty()) {
            for (PagosDetalle abD : subAbonos) {
               abD.setEstatusActivo(GenericEnumType.DISABLED);
               getVentasBeanController().addPagosDetalle(abD, getLoggedUser(), false);
            }
         }
         // se actuliza el monto pagado en la venta
         Ventas venta = getSelectSolicitud().getVenta();
         venta.setCantidadPagada(venta.getCantidadPagada() - getSelectSolicitud().getMontoDevolucion());
         getVentasBeanController().addVenta(venta, getLoggedUser(), false);
         // Se crea un nuevo registro en devolución abono salida
         DevolucionPagoVenta devolucion = new DevolucionPagoVenta();
         devolucion.setSolicitud(getSelectSolicitud());
         devolucion.setLocation(getSelectSolicitud().getLocation());
         devolucion.setPagoEstatus(GenericEnumType.ENABLED);
         devolucion.setEstatusActivo(GenericEnumType.ENABLED);
         devolucion.setCantidadDevuelta(getSelectSolicitud().getMontoDevolucion());
         devolucion.setTipoMovimiento(1);
         devolucion.setSolicitante(pago.getCreatedBy());
         devolucion.setDetalles("Devolución de pago venta");
         getDevolucionesController().addDevolucionPagoVenta(devolucion, getLoggedUser(), true);
         //Se obtinen el ultimo corte de caja
         setClosingDayController(new ClosingDayController());
         ClosingDay corte = getClosingDayController().findLastClosingDay(pago.getVenta().getLocation().getId(), pago.getLastUpdatedBy().getId());

         // Validar si la fecha del abono es posterior o higual a la fecha del último corte
         if (LastUpdatedOn.before(corte.getCreatedOn()) || LastUpdatedOn.equals(corte.getCreatedOn())) {
            logger.info("NO nueva salida");
         } else {
            logger.info("Nueva salida");
            //Se crea un nuevo registro en devolución abono entrada
            DevolucionPagoVenta devolucionS = new DevolucionPagoVenta();
            devolucionS.setSolicitud(getSelectSolicitud());
            devolucionS.setLocation(getSelectSolicitud().getLocation());
            devolucionS.setPagoEstatus(GenericEnumType.ENABLED);
            devolucionS.setEstatusActivo(GenericEnumType.ENABLED);
            devolucionS.setCantidadDevuelta(getSelectSolicitud().getMontoDevolucion());
            devolucionS.setTipoMovimiento(0);
            devolucionS.setSolicitante(pago.getCreatedBy());
            devolucion.setDetalles("Devolución de pago venta");
            getDevolucionesController().addDevolucionPagoVenta(devolucionS, getLoggedUser(), true);
         }

         // se validaba si el abono lote tiene una relación con una abono múltiple
         if (idAbonoMuliple != null) {
            HistorialAbonoMultipleSpa abonoMultiple = getVentasBeanController().fillHistorialAbonoMultipleSpaById(idAbonoMuliple);
            if (abonoMultiple != null) {
               // Se le resta al total del pago múltiple el abono lote regresado de forma individual
               abonoMultiple.setTotalPago(abonoMultiple.getTotalPago() - getSelectSolicitud().getMontoDevolucion());
               abonoMultiple.setCometario(abonoMultiple.getCometario() + ". Se eliminó el pago del dia " + pago.getFechaAPagar() + " de forma individual");
               // Se elimina la relación del abono múltiple con sub abono devuelto de forma individual
               pago.setAbonoMultiple(null);
               getVentasBeanController().addPagos(pago, getLoggedUser(), false);
            }
         }

         // Se actualiza la lista de registros
         setSolicitudes(getDevolucionesController().fillSolicitudDevolucionPagoVentaByLocation(getLoggedUser().getLocation()));
         logger.info("Solicitud aprobada correctamente");
         showMessage(FacesMessage.SEVERITY_INFO, "Solicitud aprobada correctamente", "La solicitud se aprobó correctamente");
      } catch (Exception e) {
         logger.info("Ocurrió un error al realizar la aprobasion de devolución: " + e);
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un erro al aprobar la solicitud de devolución");
      }
   }

   public void aprobarCancelacionSubAbono() {
      logger.info("aprobarCancelacionSubAbono");
      try {
         // Validar el estatus del abono principal
         PagosDetalle abonoLoteDetalle = getVentasBeanController().fillPagosDetalleById(getSelectSolicitud().getIdPagoODetalle());

         // se validaba si el abono lote tiene una relación con una abono múltiple
         if (abonoLoteDetalle.getAbonoMultiple() != null) {
            HistorialAbonoMultipleSpa abonoMultiple = getVentasBeanController().fillHistorialAbonoMultipleSpaById(abonoLoteDetalle.getAbonoMultiple().getId());
            if (abonoMultiple != null) {
               // Se le resta al total del pago múltiple el abono lote regresado de forma individual
               abonoMultiple.setTotalPago(abonoMultiple.getTotalPago() - getSelectSolicitud().getMontoDevolucion());
               abonoMultiple.setCometario(abonoMultiple.getCometario() + ". Se eliminó el detalle de pago " + abonoLoteDetalle.getPago().getFechaAPagar() + " de forma individual");
               getVentasBeanController().addHitorialAbonoMultipleSpa(abonoMultiple, getLoggedUser(), false);
            }
         }

         Pagos pago = abonoLoteDetalle.getPago();
         if (pago.getLastUpdatedOn() == null && pago.getPagoEstatus().equals(GenericEnumType.ENABLED)) {
            // si el abono ya estaba pagado se devuelve a incompleto y se actualizan los montos
            pago.setPagoEstatus(GenericEnumType.INCOMPLETE);
            pago.setCantidadPagada(pago.getCantidadPagada() - getSelectSolicitud().getMontoDevolucion());
            pago.setDiferenciaPago(pago.getPago() - pago.getCantidadPagada());
         } else if (pago.getPagoEstatus().equals(GenericEnumType.INCOMPLETE)) {
            pago.setCantidadPagada(pago.getCantidadPagada() - getSelectSolicitud().getMontoDevolucion());
            pago.setDiferenciaPago(pago.getPago() - pago.getCantidadPagada());
         }
         pago.setLastUpdatedBy(getLoggedUser());

         // se valida si abono detalle devuelto era el último perteneciente al abono principal
         if (pago.getCantidadPagada() == 0.0) {
            pago.setPagoEstatus(GenericEnumType.DISABLED);
            pago.setFolio(null);
            pago.setMetodoPago(null);
            pago.setCantidadPagada(null);
            pago.setDiferenciaPago(null);
            pago.setFechaPago(null);
            pago.setCobro(null);
            pago.setLastUpdatedBy(null);
            pago.setLastUpdatedOn(null);
         }
         getVentasBeanController().addPagos(pago, getLoggedUser(), false);

         // Se actualiza el sub abono
         abonoLoteDetalle.setEstatusActivo(GenericEnumType.DISABLED);
         abonoLoteDetalle.setAbonoMultiple(null);
         getVentasBeanController().addPagosDetalle(abonoLoteDetalle, getLoggedUser(), false);

         // Se actualiza la solicitud de devolución
         getSelectSolicitud().setEstatusSolicitud(EstatusSolicitud.APROBADO);
         getDevolucionesController().addSolicitudDevolucionPagoVenta(getSelectSolicitud(), getLoggedUser(), false);

         // se actuliza el monto pagado
         Ventas venta = abonoLoteDetalle.getPago().getVenta();
         venta.setCantidadPagada(venta.getCantidadPagada() - getSelectSolicitud().getMontoDevolucion());
         getVentasBeanController().addVenta(venta, getLoggedUser(), false);

         // Se crea un nuevo registro en devolución abono salida
         DevolucionPagoVenta devolucion = new DevolucionPagoVenta();
         devolucion.setSolicitud(getSelectSolicitud());
         devolucion.setLocation(getSelectSolicitud().getLocation());
         devolucion.setPagoEstatus(GenericEnumType.ENABLED);
         devolucion.setEstatusActivo(GenericEnumType.ENABLED);
         devolucion.setCantidadDevuelta(getSelectSolicitud().getMontoDevolucion());
         devolucion.setTipoMovimiento(1);
         devolucion.setSolicitante(pago.getCreatedBy());
         getDevolucionesController().addDevolucionPagoVenta(devolucion, getLoggedUser(), true);

         //Se obtinen el ultimo corte de caja
         setClosingDayController(new ClosingDayController());
         ClosingDay corte = getClosingDayController().findLastClosingDay(abonoLoteDetalle.getPago().getVenta().getLocation().getId(), abonoLoteDetalle.getPago().getLastUpdatedBy().getId());

         // Validar si la fecha del abono es posterior o igual a la fecha del último corte
         if (abonoLoteDetalle.getCreatedOn().before(corte.getCreatedOn()) || abonoLoteDetalle.getCreatedOn().equals(corte.getCreatedOn())) {
            logger.info("no nueva salida");
         } else {
            logger.info("nueva salida");
            //Se crea un nuevo registro en devolución abono entrada
            DevolucionPagoVenta devolucionS = new DevolucionPagoVenta();
            devolucionS.setSolicitud(getSelectSolicitud());
            devolucionS.setLocation(getSelectSolicitud().getLocation());
            devolucionS.setPagoEstatus(GenericEnumType.ENABLED);
            devolucionS.setEstatusActivo(GenericEnumType.ENABLED);
            devolucionS.setCantidadDevuelta(getSelectSolicitud().getMontoDevolucion());
            devolucionS.setTipoMovimiento(0);
            devolucionS.setSolicitante(pago.getCreatedBy());
            getDevolucionesController().addDevolucionPagoVenta(devolucionS, getLoggedUser(), true);
         }

         showMessage(FacesMessage.SEVERITY_INFO, "Abono devuelto correctamente ", "Abono devuelto correctamente");
      } catch (Exception e) {
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Error al devolver el abono");
         logger.error("aprobarCancelacionSubAbono(): " + e);
      }
   }

   public void rechazarCancelacion() {
      try {
         rechazarCancelacionP();
      } catch (Exception e) {
         showMessage(FacesMessage.SEVERITY_INFO, "Error", "Ocurrió un error al tratar de rechazar la solicitud");
         logger.error("rechazarCancelacion(): " + e);
      }
   }

   public void rechazarCancelacionP() {
      try {
         // Se actualiza el abono
         switch (getSelectSolicitud().getTipoPago()) {
            case ABONO:
               Pagos pago = getVentasBeanController().fillPagosById(getSelectSolicitud().getIdPagoODetalle());
               pago.setPagoEstatus(GenericEnumType.ENABLED);
               getVentasBeanController().addPagos(pago, getLoggedUser(), false);
               break;
            case SUBABONO:
               PagosDetalle pagoD = getVentasBeanController().fillPagosDetalleById(getSelectSolicitud().getIdPagoODetalle());
               pagoD.setPagoEstatus(GenericEnumType.ENABLED);
               getVentasBeanController().addPagosDetalle(pagoD, getLoggedUser(), false);
               break;
            default:
               showMessage(FacesMessage.SEVERITY_INFO, "Error", "Tipo de abono a devolver no encontrado");
               break;
         }

         // Se actualiza la solicitud de devolución
         getSelectSolicitud().setEstatusSolicitud(EstatusSolicitud.CANCELADO);
         getDevolucionesController().addSolicitudDevolucionPagoVenta(selectSolicitud, getLoggedUser(), false);
         // Se actualiza la lista de registros
         setSolicitudes(getDevolucionesController().fillSolicitudDevolucionPagoVentaByLocation(getLoggedUser().getLocation()));
         logger.info("Solicitud rechazada correctamente");
         showMessage(FacesMessage.SEVERITY_INFO, "Solicitud rechazada correctamente", "La solicitud se rechazo correctamente ");
      } catch (Exception e) {
         logger.info("Ocurrió un error al rechazo la devolución" + e);
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al realizar el rechazo de devolución");
      }
   }

   public List<SolicitudDevolucionPagoVenta> getSolicitudes() {
      return solicitudes;
   }

   public void setSolicitudes(List<SolicitudDevolucionPagoVenta> solicitudes) {
      this.solicitudes = solicitudes;
   }

   public DevolucionesController getDevolucionesController() {
      return devolucionesController;
   }

   public void setDevolucionesController(DevolucionesController devolucionesController) {
      this.devolucionesController = devolucionesController;
   }

   public SolicitudDevolucionPagoVenta getSelectSolicitud() {
      return selectSolicitud;
   }

   public void setSelectSolicitud(SolicitudDevolucionPagoVenta selectSolicitud) {
      this.selectSolicitud = selectSolicitud;
   }

   public VentasBeanController getVentasBeanController() {
      return ventasBeanController;
   }

   public void setVentasBeanController(VentasBeanController ventasBeanController) {
      this.ventasBeanController = ventasBeanController;
   }

   public ClosingDayController getClosingDayController() {
      return closingDayController;
   }

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

}
