/*
 * 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.predio.PreventaController;
import com.arrebol.taxiservicios.controller.spa.CabinasController;
import com.arrebol.taxiservicios.controller.spa.VentasBeanController;
import com.arrebol.taxiservicios.controller.tours.ToursController;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.MetodoPago;
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.enums.TipoAvitacion;
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 com.arrebol.taxiservicios.model.tours.DetallesPagoEspacios;
import com.arrebol.taxiservicios.model.tours.EspaciosTour;
import com.arrebol.taxiservicios.model.tours.PagosEspacioTour;
import com.arrebol.taxiservicios.model.tours.PagosEspaciosTourView;
import com.arrebol.taxiservicios.model.tours.Tours;
import com.arrebol.taxiservicios.model.view.PersonListView;
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.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
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;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.DualListModel;
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 ToursController toursController;
   private CabinasController cabinasController;
   private PreventaController controladorPreventa;
   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 tipoUser;

   private String idTour;
   private Tours selectTours;
   private String metodoPago;
   private List<Tours> listTourCliente;
   private DualListModel<EspaciosTour> dualEspaciosTourLst;
   private List<PersonListView> personas;
   private Double costoPorEspacio;
   private Boolean ninos;
   private Boolean PagaAlAbordar;
   private int numeroNinos;
   private Double costoPorNino;
   private Boolean adutosMayores;
   private int numeroAdultosMayores;
   private Double costoPorAdultoMayor;
   private Double totalPago;
   private String selectPersona;
   private String selectTipotour;
   private String selectTipoAbitacion;
   private String periodoPago;
   private Date fechaAPagar;
   private Integer numeroPagos;
   private Double anticipo;
   private String comentariosVenta;
   private String observacionEspacio;

   private Person provider;
   private Date sixteenYearsOld;

   private String idCabina;

   @PostConstruct
   public void init() {
      logger.info("Start  init()");
      try {
         setCabinasController(new CabinasController());
         setVentasBeanController(new VentasBeanController());
         setControladorPreventa(new PreventaController());
         setGenericController(new GenericValidationController());
         setTipoUser(getLoggedUser().getPerson().getClienteSpa() ? "MOSA" : "ABORDO");
         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()));
         setPersonas(getControladorPreventa().findListOfPersonsByTypeAndTipoCliente(PersonType.CUSTOMER, getLoggedUser().getLocation(), getLoggedUser().getPerson().getClienteSpa()));
         setDualEspaciosTourLst(new DualListModel<>(new ArrayList<>(), new ArrayList<>()));
         clearVentaForm();
         cleanProvider();
      } 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());
               setToursController(new ToursController());

               List<Cesiones> cesiones = new ArrayList<>();
               List<Pagos> listPagos = new ArrayList<>();
               List<Tours> listTours = 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());

                        if (getTipoUser().equals("MOSA")) {
                           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);
                           }
                        } else {
                           listTours = getToursController().fillToursActivosByLocationAndFechas(getLoggedUser().getLocation(), 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());
                        if (getTipoUser().equals("MOSA")) {
                           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);
                           }
                        } else {
                           listTours = getToursController().fillToursActivosByLocationAndFechas(getLoggedUser().getLocation(), fechaInicio);
                        }
                        showMessage(FacesMessage.SEVERITY_INFO, "Agenda de fechas proximas", "Fechas proximas");
                        break;
                     case "todas":
                        logger.info("Cargando todas la fechas de pagos");
                        if (getTipoUser().equals("MOSA")) {
                           listPagos = getVentasBeanController().fillPagosByLocation(getLoggedUser().getLocation());
                           if (getSelectCabina() == null || getSelectCabina().isEmpty()) {
                              cesiones = getVentasBeanController().fillCesionesByLocation(getLoggedUser().getLocation());
                           } else {
                              cesiones = getVentasBeanController().fillCesionesByLocationAndCabinas(getLoggedUser().getLocation(), getSelectCabina());
                           }
                        } else {
                           listTours = getToursController().fillToursByLocation(getLoggedUser().getLocation());
                        }
                        showMessage(FacesMessage.SEVERITY_INFO, "Agenda completa", "Se cargó la agenda completa");
                        break;
                     default:
                        cesiones = new ArrayList<>();
                        listPagos = new ArrayList<>();
                        listTours = 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<>();
                  listTours = 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);
                  }
               });

               listTours.forEach((Tours tour) -> {
                  if (null != tour.getFechaInicio()) {
                     DefaultScheduleEvent ev = new DefaultScheduleEvent();

                     Calendar c = Calendar.getInstance();
                     c.setTime(correcciónDeHr(tour.getFechaInicio(), -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(tour.getId());
                     ev.setDescription(tour.getComentario() + "\n" + tour.getNumeroReservados() + "-" + tour.getNumeroEspacios());
                     ev.setStartDate(c.getTime());
                     ev.setEndDate(c.getTime());
                     ev.setAllDay(true);
                     ev.setTitle("TOUR: " + tour.getDescripcion());
                     ev.setStyleClass(validadorStyleClassTour(tour.getNumeroEspacios(), tour.getNumeroReservados()));

                     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 {
                  if (getTipoUser().equals("MOSA")) {
                     clientes = getVentasBeanController().getAllPersonsByPersonTyeAndTipoCliente(PersonType.CUSTOMER, getLoggedUser().getLocation(), Boolean.TRUE);
                  } else {
                     clientes = getVentasBeanController().getAllPersonsByPersonTyeAndTipoCliente(PersonType.CUSTOMER, getLoggedUser().getLocation(), Boolean.FALSE);
                  }

               } 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 void clearVentaForm() {
      setSelectTours(null);
      setSelectPersona(null);
      setPeriodoPago(null);
      setFechaAPagar(null);
      setMetodoPago(null);
      setNumeroPagos(1);
      setAnticipo(0.0);
      setNumeroNinos(0);
      setCostoPorNino(0.0);
      setTotalPago(0.0);
      setCostoPorAdultoMayor(0.0);
      setNumeroAdultosMayores(0);
      setComentariosVenta(null);
      setSelectTipoAbitacion("0");
      setCostoPorEspacio(0.0);
      setListTourCliente(new ArrayList<>());
   }

   public void cargarEspaciosDisponibles() {
      logger.info("cargarEspaciosDisponibles()");
      try {
         setToursController(new ToursController());
         Tours tourC = getToursController().fillToursById(idTour);
         if (tourC != null) {
            setSelectTours(tourC);
            setSelectPersona(null);
            setPeriodoPago(null);
            setFechaAPagar(null);
            setMetodoPago(null);
            setNumeroPagos(1);
            setAnticipo(0.0);
            setNumeroNinos(0);
            setCostoPorNino(0.0);
            setTotalPago(0.0);
            setCostoPorAdultoMayor(0.0);
            setNumeroAdultosMayores(0);
            setComentariosVenta(null);
            setSelectTipoAbitacion("0");
            setCostoPorEspacio(getSelectTours().getCostoIndividual());

            List<EspaciosTour> disponobles = getToursController().fillEspaciosTourByTourDisponibles(getSelectTours());
            List<EspaciosTour> apartados = new ArrayList<>();
            setDualEspaciosTourLst(new DualListModel<>(disponobles, apartados));
            setListTourCliente(new ArrayList<>());
            actulizarTotalAPagar();
         } else {
            logger.error("No se encontró el tour seleccionado");
            showMessage(FacesMessage.SEVERITY_ERROR, "Error", "No se encontró el tour seleccionado");
         }
      } catch (Exception e) {
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al cargar la lista de espacios");
         logger.error("cargarEspaciosDisponibles() " + e);
      }
   }

   public void actulizarTotalAPagar() {
      // se actualiza el total de los pagos segun el numero de asientos, el costo por espacio
      try {
         Double totalAPagar = 0.0;
         totalAPagar = totalAPagar + ((getDualEspaciosTourLst().getTarget().size() - getNumeroNinos() - getNumeroAdultosMayores()) * getCostoPorEspacio());
         if (getNinos()) {
            totalAPagar = totalAPagar + (getNumeroNinos() * getCostoPorNino());
         }
         if (getAdutosMayores()) {
            totalAPagar = totalAPagar + (getNumeroAdultosMayores() * getCostoPorAdultoMayor());
         }
         setTotalPago(totalAPagar);
         setSelectTipoAbitacion("0");
      } catch (Exception e) {
         logger.info("Ocurrió un error al tratar de calcular el total a pagar por la compra de los espacios");
      }
   }

   public void cargarEspaciosPorCliente() {
      logger.info("cargarEspaciosPorCliente()");
      try {
         setListTourCliente(getToursController().getlistToursByCliente(getSelectPersona()));
      } catch (Exception e) {
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al tratar de cargar el historial de tours");
         logger.error("cargarEspaciosPorCliente(): " + e);
      }
   }

   public void definirEspaciosNinos() {
      if (getNinos()) {
         logger.info("si");
      } else {
         logger.info("no");
         setNumeroNinos(0);
         setCostoPorNino(0.0);
      }
      actulizarTotalAPagar();
   }

   public void definirAdultosMayores() {
      if (getAdutosMayores()) {
         logger.info("si");
      } else {
         logger.info("no");
         setNumeroAdultosMayores(0);
         setCostoPorAdultoMayor(0.0);
      }
      actulizarTotalAPagar();
   }

   public void addVentaEspacio() {
      logger.info("addVentaEspacio()");
      try {

         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;
         }
         if (getGenericController().existStableGeneralBoxByCurdate(getLoggedUser())) {
            showMessage(FacesMessage.SEVERITY_WARN, "Dia cerrado", "No se puede hacer ninguna acción porque ya existe un cuadre de caja chica del día");
            return;
         }

         if (getNumeroPagos() < 1) {
            showMessage(FacesMessage.SEVERITY_WARN, "Advertencia", "El número de pagos debe de ser mayor a 0");
            return;
         }

         if (getTotalPago() < 0) {
            showMessage(FacesMessage.SEVERITY_WARN, "Advertencia", "El total del pago debe ser mínimo 0");
            return;
         }

         if (getAnticipo() > getTotalPago()) {
            showMessage(FacesMessage.SEVERITY_WARN, "Advertencia", "El anticipo no puede ser mayor que el costo total delos espacios del tour");
            return;
         }

         if (getDualEspaciosTourLst().getTarget().size() < (getNumeroNinos() + getNumeroAdultosMayores())) {
            showMessage(FacesMessage.SEVERITY_WARN, "Advertencia", "El número de espacios especiales es mayor al número de espacios seleccionados");
            return;
         }

         setToursController(new ToursController());

         // se crea el detalle de los campos asociados 
         DetallesPagoEspacios detalleEspacios = new DetallesPagoEspacios();
         detalleEspacios.setCliente(new Person(getSelectPersona()));
         detalleEspacios.setEstatusActivo(GenericEnumType.ENABLED);
         detalleEspacios.setTour(getSelectTours());
         detalleEspacios.setCostoEspacio(getCostoPorEspacio());
         detalleEspacios.setNoEspacios(getDualEspaciosTourLst().getTarget().size() - getNumeroNinos() - getNumeroAdultosMayores());
         detalleEspacios.setCostoEspacioNino(getCostoPorNino());
         detalleEspacios.setNoEspaciosNino(getNumeroNinos());
         detalleEspacios.setCostoEspacioAdultoMayor(getCostoPorAdultoMayor());
         detalleEspacios.setNoEspaciosAdultoMayor(getNumeroAdultosMayores());
         detalleEspacios.setTotalEspacios(getDualEspaciosTourLst().getTarget().size());
         detalleEspacios.setAnticipo(getAnticipo());
         detalleEspacios.setPago(getTotalPago());
         detalleEspacios.setPagoTotal(getTotalPago() - getAnticipo());
         detalleEspacios.setCantidadPagada(0.0);
         if (getPagaAlAbordar()) {
            detalleEspacios.setPagaAlAbordar(GenericEnumType.ENABLED);
         } else {
            detalleEspacios.setPagaAlAbordar(GenericEnumType.DISABLED);
         }
         detalleEspacios.setComentario(getComentariosVenta());
         detalleEspacios.setEstatus(GenericEnumType.INCOMPLETE);
         // se define el periodo de pago para espacios del tour
         switch (getPeriodoPago()) {
            case "MENSUAL":
               detalleEspacios.setPeriodoPago(PeriodoPago.MENSUAL);
               break;
            case "QUINCENAL":
               detalleEspacios.setPeriodoPago(PeriodoPago.QUINCENAL);
               break;
            default:
               showMessage(FacesMessage.SEVERITY_WARN, "Error", "No se seleccionó un periodo válido ");
               logger.error("No se seleccionó un periodo válido ");
               return;
         }
         switch (getSelectTipoAbitacion()) {
            case "Sencilla":
               detalleEspacios.setIncluyeAviacion(TipoAvitacion.SENCILLA);
               break;
            case "Doble":
               detalleEspacios.setIncluyeAviacion(TipoAvitacion.DOBLE);
               break;
            case "Triple":
               detalleEspacios.setIncluyeAviacion(TipoAvitacion.TRIPLE);
               break;
            case "Cuádruple":
               detalleEspacios.setIncluyeAviacion(TipoAvitacion.CUADRUPLE);
               break;
            case "No Incluye":
               detalleEspacios.setIncluyeAviacion(TipoAvitacion.NO_INCLUYE);
               break;
            default:
               detalleEspacios.setIncluyeAviacion(TipoAvitacion.NO_INCLUYE);
               break;
         }
         getToursController().addDetallesPagoEspacios(detalleEspacios, getLoggedUser(), true);

         // se actualizan los espacios seleccionados
         Boolean valPrimerCampo = true;
         for (EspaciosTour espaciosTour : getDualEspaciosTourLst().getTarget()) {
            // se le asigna el primer espacio al cliente que pagara 
            if (valPrimerCampo) {
               espaciosTour.setCliente(new Person(getSelectPersona()));
               espaciosTour.setEspacioClientePago(true);
            }
            valPrimerCampo = false;
            espaciosTour.setEstatusEspacio(GenericEnumType.ENABLED);
            espaciosTour.setClientePago(new Person(getSelectPersona()));
            espaciosTour.setDetallesPagoEspacios(detalleEspacios);
            getToursController().addEspaciosTour(espaciosTour, getLoggedUser(), false);
         }

         //Se actualiza el número de espacios vendidos del tour
         getSelectTours().setNumeroReservados(getSelectTours().getNumeroReservados() + getDualEspaciosTourLst().getTarget().size());
         getToursController().addTour(getSelectTours(), getLoggedUser(), false);

         // se genera el listado de fechas para los pagos
         Calendar fechaInicial = Calendar.getInstance();
         fechaInicial.setTime(getFechaAPagar());
         fechaInicial.add(Calendar.DATE, 1);
         Boolean mensual;
         mensual = detalleEspacios.getPeriodoPago() == PeriodoPago.MENSUAL;
         List<Calendar> fechasPago = new ArrayList<>();
         fechasPago = generarFechasDePago(fechaInicial, getNumeroPagos(), mensual);

         // monto a pagar sin el anticipo
         Double montoInd = detalleEspacios.getPagoTotal() / getNumeroPagos();

         //Se valida si se dio algun anticipo
         if (getAnticipo() > 0.0) {
            // se optiene el folio consecutivo
            String folio = obtenerFolio("T");
            if (folio != null) {
               PagosEspacioTour ant = new PagosEspacioTour();
               ant.setEstatusActivo(GenericEnumType.ENABLED);
               ant.setDetallesPagoEspacios(detalleEspacios);
               ant.setTipoPago(TipoAbono.ANTICIPO);
               ant.setPagoEstatus(GenericEnumType.ENABLED);
               switch (getMetodoPago()) {
                  case "TARJETA_DEBITO":
                     ant.setMetodoPago(MetodoPago.TARJETA_DEBITO);
                     break;
                  case "TARJETA_CREDITO":
                     ant.setMetodoPago(MetodoPago.TARJETA_CREDITO);
                     break;
                  case "DEPOSITO_TRANSFERENCIA":
                     ant.setMetodoPago(MetodoPago.DEPOSITO_TRANSFERENCIA);
                     break;
                  case "EFECTIVO":
                     ant.setMetodoPago(MetodoPago.EFECTIVO);
                     break;
                  case "TRES_MESES_SIN_INTERESES":
                     ant.setMetodoPago(MetodoPago.TRES_MESES_SIN_INTERESES);
                     break;
                  case "SEIS_MESES_SIN_INTERESES":
                     ant.setMetodoPago(MetodoPago.SEIS_MESES_SIN_INTERESES);
                     break;
                  case "NUEVE_MESES_SIN_INTERESES":
                     ant.setMetodoPago(MetodoPago.NUEVE_MESES_SIN_INTERESES);
                     break;
                  case "DOCE_MESES_SIN_INTERESES":
                     ant.setMetodoPago(MetodoPago.DOCE_MESES_SIN_INTERESES);
                     break;
                  case "CLIP":
                     ant.setMetodoPago(MetodoPago.CLIP);
                     break;
                  case "OTRO":
                     ant.setMetodoPago(MetodoPago.OTRO);
                     break;
                  default:
                     ant.setMetodoPago(MetodoPago.OTRO);
               }
               ant.setFechaPago(correcciónDeHr(new Date(), -7));
               ant.setCobro(getLoggedUser());
               ant.setFechaAPagar(correcciónDeHr(new Date(), -7));
               ant.setFolio(folio);
               ant.setPago(getAnticipo());
               ant.setCantidadPagada(getAnticipo());
               ant.setDiferenciaPago(getTotalPago() - getAnticipo());// Es el pago restante de la venta total solo para el anticipo
               getToursController().addPagosEspacioTour(ant, getLoggedUser(), true);
               logger.info("Anticipo creado correctamente");
            } else {
               logger.error("Ocurrió un error al generar el folio");
               showMessage(FacesMessage.SEVERITY_INFO, "Error", "Ocurrió un error al generar el folio");
            }
         }

         // se registran los pagos
         recorrerFechas(fechasPago, detalleEspacios, montoInd);

         // se actualizan  los listados
         recargarSesiones();

         logger.info("Espacio vendido");
         showMessage(FacesMessage.SEVERITY_INFO, "Espacio vendido", "El espacio del tour se ha vendido correctamente");

      } catch (Exception e) {
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al vender el espacio");
         logger.error("addVentaEspacio() " + e);
      }
   }

   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;
   }

   private String obtenerFolio(String ab) {
      logger.info("Obteniendo último folio ");
      try {
         setToursController(new ToursController());
         // Se cargan los abonos para validar el folio
         String abreviacion = ab;
         PagosEspaciosTourView ultimoFolio = getToursController().fillFoliosByPagos(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();
            // Dividir el folio en partes utilizando el guion como separador
            String[] partes = folior.split("-");
            // Obtener la parte del consecutivo
            String consecutivoParte = partes[1];
            // Convertir el consecutivo a un entero
            consecutivo = Integer.parseInt(consecutivoParte);
         }
         // se formatea el consecutivo
         String numeroFormateado = String.format("%06d", consecutivo + 1);
         String folio;
         if (consecutivo == 0) {
            folio = abreviacion + "-" + "000001";
         } else {
            folio = abreviacion + "-" + numeroFormateado;
         }
         return folio;
      } catch (NumberFormatException e) {
         logger.error("Ocurrió un erro al obtener el último folio ");
         showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al generar el folio");
         return null;
      }
   }

   public void recorrerFechas(List<Calendar> fechas, DetallesPagoEspacios detalleEspacioTour, Double pagoPorMes) {
      logger.info("Insertando pagos 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
      setToursController(new ToursController());
      for (Calendar fecha : fechas) {
         try {
            PagosEspacioTour pago = new PagosEspacioTour();
            pago.setEstatusActivo(GenericEnumType.ENABLED);
            pago.setDetallesPagoEspacios(detalleEspacioTour);
            pago.setTipoPago(TipoAbono.ABONO);
            pago.setPagoEstatus(GenericEnumType.DISABLED);
            pago.setFechaAPagar(fecha.getTime());
            pago.setPago(pagoPorMes);
            getToursController().addPagosEspacioTour(pago, getLoggedUser(), true);
         } catch (Exception e) {
            logger.error("Error al generar el pago correspondiente a la fecha: (" + fecha + ") " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Error al generar el pago correspondiente a la fecha   (" + fecha + ")");
         }
      }
   }

   public void addProvider() {
      logger.info("addProvider");
      try {
         getProvider().setId(UUID.randomUUID().toString());
         getProvider().setActive(true);
         getProvider().setRoot(false);
         getProvider().setCreatedOn(new Date());
         getProvider().setLocation(new Location(getLoggedUser().getLocation().getId()));
         getProvider().setClienteSpa(false);
         boolean success = getToursController().addPerson(getProvider(), getLoggedUser().getUserName(), true);
         if (success) {
            setPersonas(getControladorPreventa().findListOfPersonsByTypeAndTipoCliente(PersonType.CUSTOMER, getLoggedUser().getLocation(), getLoggedUser().getPerson().getClienteSpa()));
            showMessage(FacesMessage.SEVERITY_INFO, "Cliente agregado", "Cliente agregado correctamente");
         } else {
            logger.error("Provider " + getProvider() + " was not saved");
            showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al crear el usuario");
         }
      } catch (Exception e) {
         logger.error("addProvider: " + e);
         showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Ocurrió un error al crear el usuario");
      }
      cleanProvider();
   }

   public void cleanProvider() {
      Calendar calendar = Calendar.getInstance();
      calendar.add(Calendar.YEAR, -15);
      setSixteenYearsOld(calendar.getTime());
      setProvider(new Person(PersonType.CUSTOMER));
   }

   public void onEventSelect(SelectEvent selectEvent) {
      event = (ScheduleEvent) selectEvent.getObject();
   }

   public ScheduleModel getLazyModel() {
      return lazyModel;
   }

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

   public ToursController getToursController() {
      return toursController;
   }

   public void setToursController(ToursController toursController) {
      this.toursController = toursController;
   }

   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 String getTipoUser() {
      return tipoUser;
   }

   public void setTipoUser(String tipoUser) {
      this.tipoUser = tipoUser;
   }

   public String getSelectPersona() {
      return selectPersona;
   }

   public void setSelectPersona(String selectPersona) {
      this.selectPersona = selectPersona;
   }

   public String getSelectTipotour() {
      return selectTipotour;
   }

   public void setSelectTipotour(String selectTipotour) {
      this.selectTipotour = selectTipotour;
   }

   public String getSelectTipoAbitacion() {
      return selectTipoAbitacion;
   }

   public void setSelectTipoAbitacion(String selectTipoAbitacion) {
      this.selectTipoAbitacion = selectTipoAbitacion;
   }

   public String getPeriodoPago() {
      return periodoPago;
   }

   public void setPeriodoPago(String periodoPago) {
      this.periodoPago = periodoPago;
   }

   public Date getFechaAPagar() {
      return fechaAPagar;
   }

   public void setFechaAPagar(Date fechaAPagar) {
      this.fechaAPagar = fechaAPagar;
   }

   public Integer getNumeroPagos() {
      return numeroPagos;
   }

   public void setNumeroPagos(Integer numeroPagos) {
      this.numeroPagos = numeroPagos;
   }

   public Double getAnticipo() {
      return anticipo;
   }

   public void setAnticipo(Double anticipo) {
      this.anticipo = anticipo;
   }

   public DualListModel<EspaciosTour> getDualEspaciosTourLst() {
      return dualEspaciosTourLst;
   }

   public void setDualEspaciosTourLst(DualListModel<EspaciosTour> dualEspaciosTourLst) {
      this.dualEspaciosTourLst = dualEspaciosTourLst;
   }

   public Double getCostoPorEspacio() {
      return costoPorEspacio;
   }

   public void setCostoPorEspacio(Double costoPorEspacio) {
      this.costoPorEspacio = costoPorEspacio;
   }

   public Boolean getNinos() {
      return ninos;
   }

   public void setNinos(Boolean ninos) {
      this.ninos = ninos;
   }

   public Boolean getPagaAlAbordar() {
      return PagaAlAbordar;
   }

   public void setPagaAlAbordar(Boolean PagaAlAbordar) {
      this.PagaAlAbordar = PagaAlAbordar;
   }

   public int getNumeroNinos() {
      return numeroNinos;
   }

   public void setNumeroNinos(int numeroNinos) {
      this.numeroNinos = numeroNinos;
   }

   public Double getCostoPorNino() {
      return costoPorNino;
   }

   public void setCostoPorNino(Double costoPorNino) {
      this.costoPorNino = costoPorNino;
   }

   public Double getTotalPago() {
      return totalPago;
   }

   public void setTotalPago(Double totalPago) {
      this.totalPago = totalPago;
   }

   public Boolean getAdutosMayores() {
      return adutosMayores;
   }

   public void setAdutosMayores(Boolean adutosMayores) {
      this.adutosMayores = adutosMayores;
   }

   public int getNumeroAdultosMayores() {
      return numeroAdultosMayores;
   }

   public void setNumeroAdultosMayores(int numeroAdultosMayores) {
      this.numeroAdultosMayores = numeroAdultosMayores;
   }

   public Double getCostoPorAdultoMayor() {
      return costoPorAdultoMayor;
   }

   public void setCostoPorAdultoMayor(Double costoPorAdultoMayor) {
      this.costoPorAdultoMayor = costoPorAdultoMayor;
   }

   public String getComentariosVenta() {
      return comentariosVenta;
   }

   public void setComentariosVenta(String comentariosVenta) {
      this.comentariosVenta = comentariosVenta;
   }

   public String getObservacionEspacio() {
      return observacionEspacio;
   }

   public void setObservacionEspacio(String observacionEspacio) {
      this.observacionEspacio = observacionEspacio;
   }

   public List<Tours> getListTourCliente() {
      return listTourCliente;
   }

   public void setListTourCliente(List<Tours> listTourCliente) {
      this.listTourCliente = listTourCliente;
   }

   public Tours getSelectTours() {
      return selectTours;
   }

   public void setSelectTours(Tours selectTours) {
      this.selectTours = selectTours;
   }

   public String getMetodoPago() {
      return metodoPago;
   }

   public void setMetodoPago(String metodoPago) {
      this.metodoPago = metodoPago;
   }

   public PreventaController getControladorPreventa() {
      return controladorPreventa;
   }

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

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

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

   public GenericValidationController getGenericController() {
      return genericController;
   }

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

   public String getIdTour() {
      return idTour;
   }

   public void setIdTour(String idTour) {
      this.idTour = idTour;
   }

   public Person getProvider() {
      return provider;
   }

   public void setProvider(Person provider) {
      this.provider = provider;
   }

   public Date getSixteenYearsOld() {
      return sixteenYearsOld;
   }

   public void setSixteenYearsOld(Date sixteenYearsOld) {
      this.sixteenYearsOld = sixteenYearsOld;
   }

   public String getIdCabina() {
      return idCabina;
   }

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

}
