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

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.GenericValidationController;
import com.arrebol.taxiservicios.controller.spa.CabinasController;
import com.arrebol.taxiservicios.controller.spa.VentasBeanController;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.PersonType;
import com.arrebol.taxiservicios.model.spa.Cabinas;
import com.arrebol.taxiservicios.model.spa.CatalogoProductos;
import com.arrebol.taxiservicios.model.spa.Cesiones;
import com.arrebol.taxiservicios.model.spa.Pagos;
import com.arrebol.taxiservicios.model.spa.VentaDetalles;
import com.arrebol.taxiservicios.model.spa.Ventas;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
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;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.LazyScheduleModel;
import org.primefaces.model.ScheduleEvent;
import org.primefaces.model.ScheduleModel;

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

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

   private VentasBeanController ventasBeanController;
   private CabinasController cabinasController;
   private GenericValidationController genericController;

   private String peridoFechas;

   private ScheduleModel lazyModel;
   private ScheduleModel lazyModelCumpleClientes;
   private ScheduleEvent event = new DefaultScheduleEvent();

   private List<Cabinas> listCabinas;
   private String selectCabina;
   private List<Cesiones> listCesiones;
   private Cesiones selectCesion;
   private List<Ventas> listVentas;
   private String selectVenta;
   private Date fechaBusqueda;

   private List<CatalogoProductos> listPaquetesSesion;
   private Date fechaCesion;
   private Integer horaSesion;
   private Integer minutosSesion;
   private String selectPaqueteSesion;
   private String idSesion;
   private int cumplesHoy;
   private String idCabina;

   @PostConstruct
   public void init() {
      logger.info("Start  init()");
      try {
         setCabinasController(new CabinasController());
         setVentasBeanController(new VentasBeanController());
         setGenericController(new GenericValidationController());
         Long noC = (Long) getVentasBeanController().contarCumpleanosClientesHoy();
         setCumplesHoy(noC.intValue());
         setSelectCabina("");
         setPeridoFechas("mes_actual");
         createScheduler();
         cargarCumples();
         setLazyModelCumpleClientes(new LazyScheduleModel());
         setFechaBusqueda(new Date());
         setListCabinas(getCabinasController().fillCabinasByLocation(getLoggedUser().getLocation()));
      } catch (Exception e) {
         logger.error("init(): ", e);
      }
   }

   public List<Cesiones> cargarCesiones(String idCabina) {
      logger.info("cargando cesiones de la cabina: " + idCabina);
      List<Cesiones> cesion = new ArrayList<>();
      try {
         cesion = getVentasBeanController().fillCesionesByCabinaAndFecha(idCabina, getFechaBusqueda());
         List<String> sesionesL = generarHoras("9:00", "23:00");
         // se insertan todas las horas disponibles del día
         for (String hora : sesionesL) {
            String[] horas = hora.split(":");
            Cesiones ce = new Cesiones();
            ce.setHora(Integer.valueOf(horas[0]));
            ce.setMinutos(Integer.valueOf(horas[1]));
            ce.setDuracion(0);
            ce.setConfirmada(false);
            ce.setEstatusCesion(GenericEnumType.DISABLED);
            ce.setEstatusActivo(GenericEnumType.ENABLED);
            ce.setId("");
            cesion.add(ce);
         }
         // se ordena la lista de cesiones por horas y minutos
         cesion.sort(Comparator.comparingInt(Cesiones::getHora).thenComparingInt(Cesiones::getMinutos));
         // se limpia la lista de sesiones repetidas entre las generadas y las ya agendadas
         for (int i = 0; i < cesion.size();) {
            if (i < (cesion.size() - 1) && (Objects.equals(cesion.get(i).getHora(), cesion.get(i + 1).getHora()) && Objects.equals(cesion.get(i).getMinutos(), cesion.get(i + 1).getMinutos()))) {
               if (cesion.get(i).getId().isEmpty()) {
                  cesion.remove(i);
               } else {
                  cesion.remove(i + 1);
               }
            }
            i++;
         }
         // Se eliminan las sesiones con base en la duración de la sesiones agendadas
         for (int i = 0; i < cesion.size();) {
            Cesiones sesion = cesion.get(i);
            if (!sesion.getId().isEmpty() && i < (cesion.size() - 1)) {

               double number = sesion.getDuracion();
               int parteEntera = (int) number;
               double fraccion = number - (double) parteEntera;
               BigDecimal bd = new BigDecimal(Double.toString(fraccion));
               bd = bd.setScale(2, RoundingMode.HALF_UP);
               int parteFraccional = (int) (bd.doubleValue() * 100);

               Integer duracion = (parteEntera * 60) + parteFraccional;
               Integer noCesiones = (int) Math.floor(Double.valueOf(duracion) / 30);
               int n = 1;
               for (int j = (i + 1); n <= noCesiones;) {
                  if (j < cesion.size() && cesion.get(j).getId().isEmpty()) {
                     cesion.remove(j);
                     j--;
                  } else {
                     n = noCesiones;
                  }
                  j++;
                  n++;
               }
            }
            i++;
         }

         return cesion;
      } catch (NumberFormatException e) {
         logger.error("Ocurrió un error al cargar las cesiones");
         return cesion;
      }
   }

   public void recargarSesiones() {
      logger.info("cargarSesiones()");
      try {
         createScheduler();
         setListCabinas(getCabinasController().fillCabinasByLocation(getLoggedUser().getLocation()));
      } catch (Exception e) {
         logger.error("cargarSesiones()" + e);
      }
   }

   public void confirmarCesion() {
      logger.info("confirmarCesion()");
      try {
         getSelectCesion().setConfirmada(true);
         getVentasBeanController().addCesiones(getSelectCesion(), getLoggedUser(), false);
         recargarSesiones();
         logger.info("La sesión se marcó como confirmada");
         showMessage(FacesMessage.SEVERITY_INFO, "Cesión actualizada", "La sesión se marcó como confirmada");
      } catch (Exception e) {
         logger.error("confirmarCesion(): " + e);
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al marcar la sesión como confirmada");
      }
   }

   public void marcarCesion() {
      logger.info("marcarCesion()");
      try {
         getSelectCesion().setEstatusCesion(GenericEnumType.ENABLED);
         getVentasBeanController().addCesiones(getSelectCesion(), getLoggedUser(), false);
         recargarSesiones();
         logger.info("La sesión se marcó como tomada");
         showMessage(FacesMessage.SEVERITY_INFO, "Cesión actualizada", "La sesión se marcó como tomada");
      } catch (Exception e) {
         logger.error("marcarCesion(): " + e);
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al marcar la sesión como tomada");
      }
   }

   public String validarColor(Cesiones sesion) {
      try {
         if (sesion.getEstatusCesion().equals(GenericEnumType.ENABLED)) {
            return "bgVerde";
         } else if (sesion.isConfirmada()) {
            return "bgNaranja";
         } else if (!sesion.getId().isEmpty()) {
            return "bgGris";
         } else {
            return "";
         }
      } catch (Exception e) {
         logger.error("Error al validar el color: " + e);
         return "";
      }
   }

   private void createScheduler() {
      logger.info("createScheduler");
      try {

         setLazyModel(new LazyScheduleModel() {
            private static final long serialVersionUID = 1297279688835547588L;

            @Override
            public void loadEvents(Date start, Date end) {

               setVentasBeanController(new VentasBeanController());

               List<Cesiones> cesiones = new ArrayList<>();
               List<Pagos> listPagos = new ArrayList<>();
               Date fechaInicio;
               Date fechaFin;

               try {
                  switch (getPeridoFechas()) {
                     case "mes_actual":
                        logger.info("Cargado fechas depagos en el calendario del mes actual");
                        fechaInicio = primerDiaDelMes(new Date());
                        fechaFin = ultimoDiaDelMes(new Date());

                        listPagos = getVentasBeanController().fillPagosByLocationAndFechas(getLoggedUser().getLocation(), fechaInicio, fechaFin);
                        if (getSelectCabina() == null || getSelectCabina().isEmpty()) {
                           cesiones = getVentasBeanController().fillCesionesByLocationAndFechas(getLoggedUser().getLocation(), fechaInicio, fechaFin);
                        } else {
                           cesiones = getVentasBeanController().fillCesionesByLocationAndCabinasAndFechas(getLoggedUser().getLocation(), getSelectCabina(), fechaInicio, fechaFin);
                        }

                        showMessage(FacesMessage.SEVERITY_INFO, "Agenda del mes actual", "Fechas agendadas para el mes actual");
                        break;
                     case "proximas_citas":
                        logger.info("Cargado fechas proximas depagos en el calendario del mes actual");
                        fechaInicio = primerDiaDelMes(new Date());

                        listPagos = getVentasBeanController().fillPagosFuturosByLocationAndFechas(getLoggedUser().getLocation(), fechaInicio);
                        if (getSelectCabina() == null || getSelectCabina().isEmpty()) {
                           cesiones = getVentasBeanController().fillCesionesFuturasByLocationAndFechas(getLoggedUser().getLocation(), fechaInicio);
                        } else {
                           cesiones = getVentasBeanController().fillCesionesFuturasByLocationAndCabinasAndFechas(getLoggedUser().getLocation(), getSelectCabina(), fechaInicio);
                        }

                        showMessage(FacesMessage.SEVERITY_INFO, "Agenda de fechas proximas", "Fechas proximas");
                        break;
                     case "todas":
                        logger.info("Cargando todas la fechas de pagos");

                        listPagos = getVentasBeanController().fillPagosByLocation(getLoggedUser().getLocation());
                        if (getSelectCabina() == null || getSelectCabina().isEmpty()) {
                           cesiones = getVentasBeanController().fillCesionesByLocation(getLoggedUser().getLocation());
                        } else {
                           cesiones = getVentasBeanController().fillCesionesByLocationAndCabinas(getLoggedUser().getLocation(), getSelectCabina());
                        }

                        showMessage(FacesMessage.SEVERITY_INFO, "Agenda completa", "Se cargó la agenda completa");
                        break;
                     default:
                        cesiones = new ArrayList<>();
                        listPagos = new ArrayList<>();
                        showMessage(FacesMessage.SEVERITY_ERROR, "Error", "No se seleccionó un periodo de cargado válido");
                        logger.error("No se seleccionó ninguna opción valida para cargar las fechas de pagos");
                        break;
                  }
               } catch (Exception e) {
                  cesiones = new ArrayList<>();
                  listPagos = new ArrayList<>();;
                  showMessage(FacesMessage.SEVERITY_FATAL, "Error", "No se seleccionó un periodo de cargado válido");
                  logger.error(" (catch) No se seleccionó ninguna opción valida para cargar las fechas de pagos " + e);
               }

               listPagos.forEach((Pagos pago) -> {
                  if (null != pago.getFechaPago()) {
                     DefaultScheduleEvent ev = new DefaultScheduleEvent();

                     Calendar c = Calendar.getInstance();
                     c.setTime(correcciónDeHr(pago.getFechaPago(), -7));
                     c.add(Calendar.DATE, 1);
                     c.set(Calendar.HOUR_OF_DAY, 0);
                     c.set(Calendar.MINUTE, 0);
                     c.set(Calendar.SECOND, 0);
                     c.set(Calendar.MILLISECOND, 0);

                     ev.setData(pago.getPago());
                     String description = "Cliente: " + pago.getVenta().getCliente().getFirstName() + " " + pago.getVenta().getCliente().getSecondName()
                             + "\n" + "Cabina: " + pago.getVenta().getCabina().getNombre();
                     ev.setDescription(description);
                     ev.setStartDate(c.getTime());
                     ev.setEndDate(c.getTime());
                     ev.setAllDay(true);
                     if (pago.getVenta().getProducto() != null) {
                        ev.setTitle("Pago del " + pago.getVenta().getProducto().getDescripcion());
                     } else {
                        ev.setTitle("Pago del " + pago.getVenta().getProductosVendidos());
                     }
                     ev.setStyleClass(validadorStyleClass(pago.getFechaPago(), pago.getPagoEstatus()));

                     lazyModel.addEvent(ev);
                  }
               });

               cesiones.forEach((Cesiones cesion) -> {
                  if (null != cesion.getFechaCesion()) {
                     DefaultScheduleEvent ev = new DefaultScheduleEvent();

                     Calendar c = Calendar.getInstance();
                     c.setTime(correcciónDeHr(cesion.getFechaCesion(), -7));
                     c.add(Calendar.DATE, 1);
                     c.set(Calendar.HOUR_OF_DAY, 0);
                     c.set(Calendar.MINUTE, 0);
                     c.set(Calendar.SECOND, 0);
                     c.set(Calendar.MILLISECOND, 0);

                     ev.setData(cesion.getId());
                     String description = "Cliente: " + cesion.getVenta().getCliente().getFirstName() + " " + cesion.getVenta().getCliente().getSecondName()
                             + "\n" + "Cabina: " + cesion.getVenta().getCabina().getNombre();
                     ev.setDescription(description);
                     ev.setStartDate(c.getTime());
                     ev.setEndDate(c.getTime());
                     ev.setAllDay(true);
                     if (cesion.getVenta().getProducto() != null) {
                        ev.setTitle("Reservación del " + cesion.getVenta().getProducto().getDescripcion());
                     } else {
                        ev.setTitle("Reservación del " + cesion.getVenta().getProductosVendidos());
                     }
                     ev.setStyleClass(validarColorCesion(cesion.getFechaCesion(), cesion.getEstatusCesion(), cesion.isConfirmada(), cesion.getHora(), cesion.getMinutos()));

                     lazyModel.addEvent(ev);
                  }
               });

            }
         });

      } catch (Exception e) {
         logger.error("createScheduler", e);
         setLazyModel(new LazyScheduleModel() {
            private static final long serialVersionUID = 3109256773218160485L;
         });
      }
   }

   public void cargarCumples() {
      logger.info("Cargando cumpleaños");
      try {
         createSchedulerCumpleClientes();
      } catch (Exception e) {
         logger.error("cargarCumples(): " + e);
      }
   }

   private void createSchedulerCumpleClientes() {
      logger.info("createSchedulerCumpleClientes");
      try {

         setLazyModelCumpleClientes(new LazyScheduleModel() {
            private static final long serialVersionUID = 1297279688835547588L;

            @Override
            public void loadEvents(Date start, Date end) {

               setVentasBeanController(new VentasBeanController());
               SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");

               List<Person> clientes;

               try {

                  clientes = getVentasBeanController().getAllPersonsByPersonTye(PersonType.CUSTOMER, getLoggedUser().getLocation());

               } catch (Exception e) {
                  clientes = new ArrayList<>();
                  showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Ocurrió un error al tratar de cargar la lista de clientes ");
                  logger.error("Ocurrió un error al tratar de cargar la lista de clientes: " + e);
               }

               clientes.forEach((Person person) -> {
                  if (null != person.getBirthdate()) {
                     DefaultScheduleEvent ev = new DefaultScheduleEvent();

                     // se extrae la equivalencia de la fecha de nacimiento en el año actual
                     Date cumple = correcciónDeHr(person.getBirthdate(), -7);
                     LocalDate fechaCumple = cumple.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                     LocalDate fechaActual = LocalDate.now();
                     LocalDate cumpleEsteAno = LocalDate.of(fechaActual.getYear(), fechaCumple.getMonth(), fechaCumple.getDayOfMonth());
                     Date cumpleEsteAnoDate = Date.from(cumpleEsteAno.atStartOfDay(ZoneId.systemDefault()).toInstant());

                     Calendar c = Calendar.getInstance();
                     c.setTime(cumpleEsteAnoDate);
                     c.add(Calendar.DATE, 1);
                     c.set(Calendar.HOUR_OF_DAY, 0);
                     c.set(Calendar.MINUTE, 0);
                     c.set(Calendar.SECOND, 0);
                     c.set(Calendar.MILLISECOND, 0);

                     ev.setData(person.getId());
                     ev.setDescription(formatter.format(cumpleEsteAnoDate));
                     ev.setStartDate(c.getTime());
                     ev.setEndDate(c.getTime());
                     ev.setAllDay(true);
                     ev.setTitle("Cumpleaños de " + person.getFirstName() + " " + person.getSecondName());
                     ev.setStyleClass("bgRosa");

                     lazyModelCumpleClientes.addEvent(ev);
                  }
               });

            }
         });

      } catch (Exception e) {
         logger.error("createSchedulerCumpleClientes", e);
         setLazyModelCumpleClientes(new LazyScheduleModel() {
            private static final long serialVersionUID = 3109256773218160485L;
         });
      }
   }

   public void cargarSesiones() {
      logger.info("cargarSesiones()");
      try {
         createScheduler();
      } catch (Exception e) {
         logger.error("cargarSesiones()" + e);
      }
   }

   public String validadorStyleClass(Date fechaPago, GenericEnumType estatus) {
      if (estatus.equals(GenericEnumType.ENABLED)) {
         return "datatableRowGreen";
      } else if (fechaPago.before(new Date())) {
         return "datatableRowEmpty";
      } else {

         return "";
      }
   }

   public String validadorStyleClassTour(int totalEspacios, int espaciosDiponibles) {
      if (espaciosDiponibles < totalEspacios) {
         return "datatableRowGreen";
      } else if (totalEspacios == espaciosDiponibles) {
         return "datatableRowEmpty";
      } else {
         return "";
      }
   }

   public String validarColorCesion(Date fechaPago, GenericEnumType estatus, boolean conf, int hora, int min) {
      if (estatus.equals(GenericEnumType.ENABLED)) {
         return "bgVerde";
      } else if (fechaPago.before(new Date())) {
         return "bgRojo";
      } else if (hora == 0 && min == 0) {
         return "bgNaranja";
      } else if (conf == true && (hora > 0 || min > 0)) {
         return "bgAzulMenos";
      } else if (conf == false && (hora > 0 || min > 0)) {
         return "bgAzulMas";
      }
      return "";
   }

   public void cargarSesionDashboard() {
      logger.info("cargando sesion");
      try {
         Cesiones sesion = getSelectCesion();
         // se cargan los paquetes de la sesion
         if (sesion.getVenta().getProducto() == null) {
            List<VentaDetalles> listVentaDetalles = getVentasBeanController().fillVentaDetallesByVenta(sesion.getVenta());
            List<CatalogoProductos> pro = new ArrayList<>();
            for (VentaDetalles listVentaDetalle : listVentaDetalles) {
               pro.add(listVentaDetalle.getProducto());
            }
            setListPaquetesSesion(pro);
         } else {
            List<CatalogoProductos> pro = new ArrayList<>();
            pro.add(sesion.getVenta().getProducto());
            setListPaquetesSesion(pro);
         }

         // se carga el paquete de la sesion si la ahi
         if (sesion.getProducto() != null) {
            setSelectPaqueteSesion(sesion.getProducto().getId());
         }

         // se cargan la fecha y hora de la sesión
         //FECHA
         if (sesion.getFechaCesion() != null) {
            setFechaCesion(correcciónDeHr(sesion.getFechaCesion(), 7));
         } else {
            setFechaCesion(new Date());
         }
         //HORA
         if (sesion.getHora() != null) {
            setHoraSesion(sesion.getHora());
         } else {
            setHoraSesion(1);
         }
         //MINUTOS
         if (sesion.getMinutos() != null) {
            setHoraSesion(sesion.getMinutos());
         } else {
            setHoraSesion(0);
         }
      } catch (Exception e) {
         logger.error("Error al cargar la sesion" + e);
      }
   }

   public void cargarNewSesionDashboard(String idCabina) {
      logger.info("cargando sesion");
      try {
         if (idCabina != null && !idCabina.isEmpty()) {
            setIdCabina(idCabina);
            setListVentas(getVentasBeanController().fillVentasEnProsesoOConCesionesPendientes(getLoggedUser().getLocation(), idCabina));
         }
         Cesiones sesion = getSelectCesion();
         //HORA
         if (sesion.getHora() != null) {
            setHoraSesion(sesion.getHora());
         } else {
            setHoraSesion(1);
         }
         //MINUTOS
         if (sesion.getMinutos() != null) {
            setHoraSesion(sesion.getMinutos());
         } else {
            setHoraSesion(0);
         }
      } catch (Exception e) {
         logger.error("Error al cargar la sesion" + e);
      }
   }

   // Si se actualiza esta función ahí que utilizarla también en el dasbord
   public void editarCesion() {
      logger.info("editarCesion()");
      try {
         // Actualizando datos de la sesión actualizada 
         if (!getSelectPaqueteSesion().isEmpty() && getSelectPaqueteSesion() != null) {
            getSelectCesion().setProducto(new CatalogoProductos(getSelectPaqueteSesion()));
         } else {
            getSelectCesion().setProducto(null);
         }
         getSelectCesion().setFechaCesion(getFechaCesion());
         getVentasBeanController().addCesiones(getSelectCesion(), getLoggedUser(), false);
         // Reagendando cesiones no tomadas
         //reagendarCesiones(getSelectCesion(), getFechaCesion());
         // Actualizando datos 
         clearSelectedCesion();
         recargarSesiones();
         logger.info("Sesión editada correctamente");
         showMessage(FacesMessage.SEVERITY_INFO, "Sesión editada", "Sesión editada correctamente ");
      } catch (Exception e) {
         logger.error("agregarCesion(): " + e);
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al editar la sesión");
      }
   }

   public void agendarCesion() {
      logger.info("agendarCesion()");
      try {
         int ver = getVentasBeanController().verificarCesionExistente(getIdCabina(), getFechaBusqueda(), getSelectCesion().getHora(), getSelectCesion().getMinutos(), getSelectCesion().getDuracion());
         if (ver == 0) {
            // se agrega la nueva sesió
            getSelectCesion().setVenta(new Ventas(getSelectVenta()));
            getSelectCesion().setFechaCesion(getFechaBusqueda());
            getVentasBeanController().addCesiones(getSelectCesion(), getLoggedUser(), true);
            // Actualizando datos 
            clearSelectedCesion();
            recargarSesiones();
            logger.info("Sesión agendada correctamente");
            showMessage(FacesMessage.SEVERITY_INFO, "Sesión agendada", "Sesión agendada correctamente");
         } else {
            logger.info("Ya ahí una sesión en este horario");
            showMessage(FacesMessage.SEVERITY_WARN, "ERROR", "Ya ahí una sesión en este horario");
         }
      } catch (Exception e) {
         logger.error("agendarCesion(): " + e);
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al agendar la sesión");
      }
   }

   private void reagendarCesiones(Cesiones sesion, Date fechaSesion) {
      logger.info("Reagendando sesiones");
      try {
         List<Cesiones> sesionesPendientes = getVentasBeanController().fillCesionesByVentaAndEstatus(sesion.getVenta(), GenericEnumType.DISABLED);
         // numero de dia de la nueva fecha
         Calendar calendario = Calendar.getInstance();
         calendario.setTime(fechaSesion);
         int numeroDia = calendario.get(Calendar.DAY_OF_MONTH);
         int numeroMes = calendario.get(Calendar.MONTH);
         // Actualizando fecha de las sesiones restantes
         for (Cesiones sesionesP : sesionesPendientes) {
            sesionesP.setFechaCesion(actualizarDiaMes(numeroMes, numeroDia));
            getVentasBeanController().addCesiones(sesionesP, getLoggedUser(), false);
            numeroMes++;
         }
      } catch (Exception e) {
         logger.error("Error al reagendar las cesiones");
      }
   }

   public void editarComentarioCesion() {
      logger.info("editarCesion()");
      try {
         // Actualizando datos de la sesión actualizada 
         setVentasBeanController(new VentasBeanController());
         getVentasBeanController().addCesiones(getSelectCesion(), getLoggedUser(), false);
         // Actualizando datos 
         clearSelectedCesion();
         recargarSesiones();
         logger.info("Sesión editada correctamente");
         showMessage(FacesMessage.SEVERITY_INFO, "Sesión editada", "Sesión editada correctamente ");
      } catch (Exception e) {
         logger.error("editarCesion(): " + e);
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al editar la sesión");
      }
   }

   public Date actualizarDiaMes(int numeroMeses, int numeroDia) {
      // Obtener la fecha actual
      Calendar calendario = Calendar.getInstance();
      calendario.setTime(new Date());
      // Establecer el número de meses
      calendario.set(Calendar.MONTH, numeroMeses);
      // Establecer el número del día
      calendario.set(Calendar.DAY_OF_MONTH, numeroDia);
      // Valida si el nuevo número del día es mayor que el máximo del mes
      int maximoDia = calendario.getActualMaximum(Calendar.DAY_OF_MONTH);
      if (numeroDia > maximoDia) {
         calendario.set(Calendar.DAY_OF_MONTH, maximoDia);
      }
      calendario.set(Calendar.HOUR_OF_DAY, 0);
      calendario.set(Calendar.MINUTE, 0);
      calendario.set(Calendar.SECOND, 0);
      calendario.set(Calendar.MILLISECOND, 0);
      // Obtener la fecha resultante
      Date fecha = calendario.getTime();
      return fecha;
   }

   public void clearSelectedCesion() {
      logger.info("clearSelectedCesion()");
      try {
         setSelectVenta(null);
         setSelectPaqueteSesion(null);
         setIdCabina(null);
         getListPaquetesSesion().clear();
      } catch (Exception e) {
         logger.error("clearSelectedCesion(): " + e);
      }
   }

   private Date correcciónDeHr(Date fecha, int horas) {
      Calendar calendar = Calendar.getInstance();
      calendar.setTime(fecha);
      calendar.add(Calendar.HOUR_OF_DAY, horas);
      Date nuevaFecha = calendar.getTime();
      return nuevaFecha;
   }

   private static Date primerDiaDelMes(Date fecha) {
      Calendar cal = Calendar.getInstance();
      cal.setTime(fecha);
      cal.set(Calendar.DAY_OF_MONTH, 1);
      cal.set(Calendar.HOUR_OF_DAY, 0);
      cal.set(Calendar.MINUTE, 0);
      cal.set(Calendar.SECOND, 0);
      cal.set(Calendar.MILLISECOND, 0);
      return cal.getTime();
   }

   private static Date ultimoDiaDelMes(Date fecha) {
      Calendar cal = Calendar.getInstance();
      cal.setTime(fecha);
      cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
      cal.set(Calendar.HOUR_OF_DAY, 23);
      cal.set(Calendar.MINUTE, 59);
      cal.set(Calendar.SECOND, 59);
      cal.set(Calendar.MILLISECOND, 999);
      return cal.getTime();
   }

   private List<String> generarHoras(String horaInicio, String horaFinal) {
      List<String> horas = new ArrayList<>();
      try {
         SimpleDateFormat format = new SimpleDateFormat("HH:mm");
         Date dateInicio = format.parse(horaInicio);
         Date dateFinal = format.parse(horaFinal);
         Date temp = dateInicio;
         while (temp.before(dateFinal)) {
            horas.add(format.format(temp));
            temp.setTime(temp.getTime() + 30 * 60 * 1000); // hr cada 30 minutos
         }
         horas.add(format.format(dateFinal));
         return horas;
      } catch (ParseException e) {
         logger.error("Ocurrió un error al parsear las hr recibidas " + e);
         return horas;
      } catch (Exception e) {
         logger.error("Ocurrió un error al generar la lista de hr " + e);
         return horas;
      }
   }

   public List<Calendar> generarFechasDePago(Calendar fechaInicial, int numeroPagos, Boolean mensual) {
      logger.info("Generación fechas");
      //lista de fechas
      List<Calendar> fechasDePago = new ArrayList<>();
      if (mensual) {
         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();

      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 onEventSelect(SelectEvent selectEvent) {
      event = (ScheduleEvent) selectEvent.getObject();
   }

   public ScheduleModel getLazyModel() {
      return lazyModel;
   }

   public void setLazyModel(ScheduleModel lazyModel) {
      this.lazyModel = lazyModel;
   }

   public ScheduleEvent getEvent() {
      return event;
   }

   public void setEvent(ScheduleEvent event) {
      this.event = event;
   }

   public VentasBeanController getVentasBeanController() {
      return ventasBeanController;
   }

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

   public List<CatalogoProductos> getListPaquetesSesion() {
      return listPaquetesSesion;
   }

   public void setListPaquetesSesion(List<CatalogoProductos> listPaquetesSesion) {
      this.listPaquetesSesion = listPaquetesSesion;
   }

   public Integer getHoraSesion() {
      return horaSesion;
   }

   public void setHoraSesion(Integer horaSesion) {
      this.horaSesion = horaSesion;
   }

   public Integer getMinutosSesion() {
      return minutosSesion;
   }

   public void setMinutosSesion(Integer minutosSesion) {
      this.minutosSesion = minutosSesion;
   }

   public Date getFechaCesion() {
      return fechaCesion;
   }

   public void setFechaCesion(Date fechaCesion) {
      this.fechaCesion = fechaCesion;
   }

   public String getSelectPaqueteSesion() {
      return selectPaqueteSesion;
   }

   public void setSelectPaqueteSesion(String selectPaqueteSesion) {
      this.selectPaqueteSesion = selectPaqueteSesion;
   }

   public String getIdSesion() {
      return idSesion;
   }

   public void setIdSesion(String idSesion) {
      this.idSesion = idSesion;
   }

   public Cesiones getSelectCesion() {
      return selectCesion;
   }

   public void setSelectCesion(Cesiones selectCesion) {
      this.selectCesion = selectCesion;
   }

   public CabinasController getCabinasController() {
      return cabinasController;
   }

   public void setCabinasController(CabinasController cabinasController) {
      this.cabinasController = cabinasController;
   }

   public List<Cabinas> getListCabinas() {
      return listCabinas;
   }

   public void setListCabinas(List<Cabinas> listCabinas) {
      this.listCabinas = listCabinas;
   }

   public String getSelectCabina() {
      return selectCabina;
   }

   public void setSelectCabina(String selectCabina) {
      this.selectCabina = selectCabina;
   }

   public String getPeridoFechas() {
      return peridoFechas;
   }

   public void setPeridoFechas(String peridoFechas) {
      this.peridoFechas = peridoFechas;
   }

   public List<Cesiones> getListCesiones() {
      return listCesiones;
   }

   public void setListCesiones(List<Cesiones> listCesiones) {
      this.listCesiones = listCesiones;
   }

   public Date getFechaBusqueda() {
      return fechaBusqueda;
   }

   public void setFechaBusqueda(Date fechaBusqueda) {
      this.fechaBusqueda = fechaBusqueda;
   }

   public List<Ventas> getListVentas() {
      return listVentas;
   }

   public void setListVentas(List<Ventas> listVentas) {
      this.listVentas = listVentas;
   }

   public String getSelectVenta() {
      return selectVenta;
   }

   public void setSelectVenta(String selectVenta) {
      this.selectVenta = selectVenta;
   }

   public ScheduleModel getLazyModelCumpleClientes() {
      return lazyModelCumpleClientes;
   }

   public void setLazyModelCumpleClientes(ScheduleModel lazyModelCumpleClientes) {
      this.lazyModelCumpleClientes = lazyModelCumpleClientes;
   }

   public int getCumplesHoy() {
      return cumplesHoy;
   }

   public void setCumplesHoy(int cumplesHoy) {
      this.cumplesHoy = cumplesHoy;
   }

   public GenericValidationController getGenericController() {
      return genericController;
   }

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

   public String getIdCabina() {
      return idCabina;
   }

   public void setIdCabina(String idCabina) {
      this.idCabina = idCabina;
   }

}
