package mx.gob.jumapacelaya.ui;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.checkbox.CheckboxGroup;
import com.vaadin.flow.component.checkbox.CheckboxGroupVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.grid.HeaderRow;
import com.vaadin.flow.component.grid.contextmenu.GridContextMenu;
import com.vaadin.flow.component.grid.contextmenu.GridMenuItem;
import com.vaadin.flow.component.grid.dataview.GridListDataView;
import com.vaadin.flow.component.html.*;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.notification.NotificationVariant;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.popover.Popover;
import com.vaadin.flow.component.popover.PopoverPosition;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.upload.Upload;
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.StreamRegistration;
import com.vaadin.flow.server.StreamResource;
import jakarta.annotation.security.PermitAll;
import mx.gob.jumapacelaya.models.PlanAnual;
import mx.gob.jumapacelaya.models.encuestas.MantenimientosSinEncuesta;
import mx.gob.jumapacelaya.services.DatabaseService;
import mx.gob.jumapacelaya.services.EmailService;
import mx.gob.jumapacelaya.services.ReportService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.vaadin.lineawesome.LineAwesomeIcon;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@PermitAll
@PageTitle("Plan Anual de Mantenimiento")
@Route(value = "/", layout = MainLayout.class)
@CssImport("./themes/sistema-mantenimiento/styles.css")
public class PlanAnualView extends VerticalLayout {

    private static final Logger logger = LoggerFactory.getLogger(PlanAnualView.class);

    private final EmailService emailService;
    @Value("${app.base-url}")
    private String baseUrl;
    private final Environment env;
    private final ReportService reportService;

    H4 titulo = new H4();
    H5 titulo1 = new H5();
    Button btnInsertar;
    private byte[] fileContent;
    VerticalLayout gridLayout = new VerticalLayout();
    HorizontalLayout uploadLayout = new HorizontalLayout();
    HorizontalLayout filtrosLayout = new HorizontalLayout();
    private final DatabaseService databaseService;
    Grid<PlanAnual> planAnualGrid;
    Button btnColumns;
    Button btnImprimirRpt;
    Button btnAddEquipo;
    Button btnEnviarEncuestas;
    HorizontalLayout btnImprimirLayout;
    private Popover reportePopover;
    ComboBox<Integer> yearFilter;

    public PlanAnualView(DatabaseService databaseService, Environment env, ReportService reportService, EmailService emailService) {
        this.databaseService = databaseService;
        this.env = env;
        this.reportService = reportService;

        setupHeader();
        Grid<PlanAnual> planAnualGrid = setupGrid();

        // Notificación de conexión activa
        String perfil = String.join(",", env.getActiveProfiles());
        String url = env.getProperty("db.url");
        Notification.show("Conectado a: " + perfil + "\nURL DB: " + url, 5000, Notification.Position.BOTTOM_START);

        // Obtenemos la lista de items y establecemos un GridListDataView para gestionar
        // los datos
        List<PlanAnual> planAnualItems = databaseService.getPlanAnual();
        GridListDataView<PlanAnual> dataView = planAnualGrid.setItems(planAnualItems);


        // Se crea el filtro para el grid.
        PlanAnualFilter planAnualFilter = new PlanAnualFilter(dataView);
        planAnualFilter.setExcludeRealizado(true);

        // Aplicar el valor actual del ComboBox al filtro al inicializar
        if (yearFilter != null && yearFilter.getValue() != null) {
            planAnualFilter.setYear(yearFilter.getValue());
        }

        if (yearFilter != null) {
            yearFilter.addValueChangeListener(event -> planAnualFilter.setYear(event.getValue()));
        }

        HeaderRow headerRow = planAnualGrid.appendHeaderRow();
        /*headerRow.getCell(planAnualGrid.getColumnByKey("smtColumnKey"))
            .setComponent(createFilterHeader("S.M.T", planAnualFilter::setSmt));*/
        
        headerRow.getCell(planAnualGrid.getColumnByKey("equipo"))
            .setComponent(createFilterHeader("Equipo", planAnualFilter::setEquipo));

        headerRow.getCell(planAnualGrid.getColumnByKey("departamento"))
            .setComponent(createFilterHeader("Departamento", planAnualFilter::setDepartamento));

        headerRow.getCell(planAnualGrid.getColumnByKey("mesplaneado"))
            .setComponent(createFilterHeader("Mes Planeado", planAnualFilter::setMesPlaneado));

        headerRow.getCell(planAnualGrid.getColumnByKey("encuesta"))
                .setComponent(createFilterHeader("Encuesta", planAnualFilter::setEncuesta));



        // MENU CONTEXTUAL DEL GRID
        PersonContextMenu contextMenu = new PersonContextMenu(planAnualGrid);


        
        // Componente UPLOAD para subir archivos
        MemoryBuffer buffer = new MemoryBuffer();
        Upload upload = new Upload();
        upload.setAcceptedFileTypes(".xls", ".xlsx");
        upload.setMaxFiles(1);
        upload.setDropLabel(new com.vaadin.flow.component.html.Span("Arrastra un archivo Excel aquí o selecciona uno"));

        upload.addSucceededListener(event -> {
            try {
                // Almacena el contenido del archivo en un arreglo de bytes
                try (InputStream inputStream = buffer.getInputStream();
                     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

                    inputStream.transferTo(byteArrayOutputStream);
                    fileContent = byteArrayOutputStream.toByteArray();
                }

                // Validación del archivo cargado
                List<String> errores = validarExcel(new ByteArrayInputStream(fileContent));
                if (!errores.isEmpty()) {
                    // Crear notificación con mensaje de error y sin duración
                    final Notification ntfError = new Notification();
                    ntfError.setText("Errores en el archivo: " + String.join(", ", errores));
                    ntfError.setDuration(0); // La notificación no se cerrará automáticamente
                    ntfError.setPosition(Notification.Position.MIDDLE);
                    ntfError.addThemeVariants(NotificationVariant.LUMO_ERROR);

                    // Texto del mensaje de error
                    Span errorMessage = new Span("Errores en el archivo: " + String.join(", ", errores));
                    errorMessage.getStyle().set("margin-right", "10px");

                    // Crear botón de cierre
                    final Button closeButton = new Button(new Icon(VaadinIcon.CLOSE));
                    closeButton.addClickListener(e -> ntfError.close());

                    // Agregar el mensaje y el botón de cierre a la notificación
                    HorizontalLayout notificationLayout = new HorizontalLayout(errorMessage, closeButton);
                    ntfError.add(notificationLayout);

                    ntfError.open(); // Abrir la notificación en pantalla
                    // Ocultar el botón de insertar si hay errores
                    btnInsertar.setVisible(false);
                } else {
                    btnInsertar.setVisible(true);
                }
            } catch (IOException e) {
                Notification.show("Error al leer el archivo: " + e.getMessage())
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
            }
        });

        btnInsertar = new Button("Insertar archivo", event -> insertarDatos());
        btnInsertar.setVisible(false);

        gridLayout.add(btnImprimirLayout,planAnualGrid);
        gridLayout.setSizeFull();

        uploadLayout.add(upload, btnInsertar);
        toggleLayouts(dataView);


        filtrosLayout.addClassNames("lumo-justify-content-center", "lumo-gap-m", "lumo-padding-s");
        filtrosLayout.setWidthFull();
        filtrosLayout.setJustifyContentMode(JustifyContentMode.CENTER);

        Button btnPendientes = new Button("Pendientes", VaadinIcon.CLOCK.create());
        Button btnRealizados = new Button("Realizados", VaadinIcon.CHECK_CIRCLE.create());

        btnPendientes.addClassName("selected-tab");

        btnPendientes.addClickListener(e -> {
            planAnualFilter.setExcludeRealizado(true);
            btnPendientes.addClassName("selected-tab");
            btnRealizados.removeClassName("selected-tab");
        });
        btnRealizados.addClickListener(e -> {
            planAnualFilter.setExcludeRealizado(false);
            btnRealizados.addClassName("selected-tab");
            btnPendientes.removeClassName("selected-tab");
        });

        filtrosLayout.add(btnPendientes, btnRealizados);
        mostrarPopoverReportes();


        this.setPadding(false);
        this.setMargin(false);
        this.setSpacing(false);
        this.setSizeFull();
        add(filtrosLayout, uploadLayout);
        add(gridLayout);
        this.emailService = emailService;
    }

    private void setupHeader() {
        VerticalLayout headerLayout = new VerticalLayout();
        headerLayout.addClassName("plan-anual-header");

        titulo.addClassName("plan-anual-titulo");
        titulo1.addClassName("plan-anual-titulo1");
        titulo.setText("Plan Anual de Mantenimiento Preventivo de Equipo de Computo");
        titulo1.setText(Year.now().toString());

        TextField nomenclaturaTxt = new TextField();
        nomenclaturaTxt.setValue("FR01-PA-7.1.3-02");
        nomenclaturaTxt.setReadOnly(true);
        nomenclaturaTxt.addClassName("nomenclatura-txt");

        headerLayout.add(titulo, titulo1);
        headerLayout.setAlignItems(Alignment.CENTER);
        add(headerLayout);
    }


    private Grid<PlanAnual> setupGrid() {

        planAnualGrid = new Grid<>(PlanAnual.class, false);
        planAnualGrid.addColumn((ValueProvider<PlanAnual, Integer>) PlanAnual::getNumero)
                .setHeader("No.").setSortable(true).setAutoWidth(true).setFrozen(true);

        // Botón condicional
        planAnualGrid.addComponentColumn(planAnual -> {
            String estado = planAnual.getEstado();
            Button btn;

            if ("PENDIENTE".equalsIgnoreCase(estado)) {
                btn = new Button(new Icon(VaadinIcon.EDIT));
                btn.setTooltipText("Realizar mantenimiento");

                btn.addClickListener(event -> {
                    int idPlananual = planAnual.getNumero();
                    LocalDate fechaSistema = LocalDate.now();
                    String nomEquipo = planAnual.getNomEquipo();
                    String departamento = planAnual.getDepartamento();
                    String encuesta = planAnual.getEncuesta();

                    btn.getUI().ifPresent(ui -> ui.navigate(
                            "mantenimiento?id=" + idPlananual +
                                    "&fecha=" + fechaSistema +
                                    "&tipo=1" +
                                    "&nomEquipo=" + nomEquipo +
                                    "&departamento=" + departamento +
                                    "&enc=" + encuesta
                    ));
                });

            } else if ("REALIZADO".equalsIgnoreCase(estado)) {
                btn = new Button(new Icon(VaadinIcon.EYE));
                btn.setTooltipText("Ver detalles");

                btn.addClickListener(event -> {
                    int idPlananual = planAnual.getNumero();
                    String encuesta = planAnual.getEncuesta();

                    btn.getUI().ifPresent(ui -> ui.navigate(
                            "detalles?id=" + idPlananual +
                                    "&enc=" + encuesta
                    ));
                });
            } else {
                btn = new Button("N/A");
                btn.setEnabled(false);
            }

            return btn;
        }).setAutoWidth(true).setFrozen(true);

        planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getNomEquipo)
                .setHeader("Equipo").setAutoWidth(true).setKey("equipo");

        planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getDepartamento)
                .setHeader("Departamento").setAutoWidth(true).setKey("departamento");

        planAnualGrid.addColumn(planAnual -> {
            String mesPlaneado = planAnual.getMesplaneado();
            return mesPlaneado != null ? mesPlaneado.toUpperCase() : "N/A";
        }).setHeader("Mes Planeado").setAutoWidth(true).setKey("mesplaneado");

        // Fechas formateadas
        planAnualGrid.addColumn(planAnual -> {
            LocalDate fecha = planAnual.getFechaProgramada();
            return fecha != null ? fecha.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) : "No programada";
        }).setHeader("Fecha Programada").setAutoWidth(true).setSortable(true).setKey("fechaProgramada");

        planAnualGrid.addColumn(planAnual -> {
            LocalDate fecha = planAnual.getFechaMantenimiento();
            return fecha != null ? fecha.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) : "";
        }).setHeader("Fecha Realización").setAutoWidth(true).setSortable(true).setKey("fechaMantenimiento");


        planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getEstado)
                .setHeader("Estado").setAutoWidth(true).setKey("estado");

        planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getSituacion)
                .setHeader("Situación").setAutoWidth(true).setKey("situacion");

        planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getEncuesta)
                .setHeader("Encuesta").setAutoWidth(true).setKey("encuesta");

        /*planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getSmt)
                .setHeader("S.M.T").setKey("smtColumnKey");*/

        // Iconos en columnas booleanas
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isMonitor())).setHeader("Monitor").setKey("monitor");
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isTeclado())).setHeader("Teclado").setKey("teclado");
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isMouse())).setHeader("Mouse").setKey("mouse");
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isRegulador())).setHeader("Regulador").setKey("regulador");
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isCpu())).setHeader("CPU").setKey("cpu");
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isImpresora())).setHeader("Impresora").setKey("impresora");
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isMiniPrint())).setHeader("MiniPrint").setKey("miniprint");
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isLaptop())).setHeader("Laptop").setKey("laptop");
        planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isEscaner())).setHeader("Escáner").setKey("escaner");

        planAnualGrid.addThemeVariants(GridVariant.LUMO_WRAP_CELL_CONTENT);
        planAnualGrid.addThemeVariants(GridVariant.LUMO_ROW_STRIPES);


        btnColumns = new Button(VaadinIcon.GRID_H.create());
        btnColumns.addThemeVariants(ButtonVariant.LUMO_ICON);
        btnColumns.setAriaLabel("Show/Hide Columns");
        btnColumns.setTooltipText("Show/Hide Columns");

        btnImprimirRpt = new Button(VaadinIcon.PRINT.create());
        btnImprimirRpt.addClickListener(event -> reportePopover.open());
        btnImprimirRpt.setTooltipText("Imprimir reporte");

        btnAddEquipo = new Button(VaadinIcon.PLUS.create());
        btnAddEquipo.addClickListener(event -> addNuevoEquipo());
        btnAddEquipo.setTooltipText("Agregar nuevo equipo");

        btnEnviarEncuestas = new Button(VaadinIcon.ENVELOPE.create());
        btnEnviarEncuestas.addClickListener(e -> showParametrosDialog());
        btnEnviarEncuestas.setTooltipText("Enviar encuestas masivamente");

        yearFilter = new ComboBox<>();
        int currentYear = Year.now().getValue();
        List<Integer> years = IntStream.rangeClosed(currentYear - 1, currentYear + 4)
                .boxed().collect(Collectors.toList());
        yearFilter.setItems(years);
        yearFilter.setPlaceholder("Año");
        yearFilter.setValue(currentYear);
        yearFilter.setClearButtonVisible(true);


        List<PlanAnual> todosLosPlanes = databaseService.getPlanAnual();


        btnImprimirLayout = new HorizontalLayout(btnColumns, btnImprimirRpt, btnAddEquipo, btnEnviarEncuestas, yearFilter);
        btnImprimirLayout.setAlignItems(Alignment.BASELINE);
        HorizontalLayout columnSelectorLayout = new HorizontalLayout();
        columnSelectorLayout.setAlignItems(Alignment.END);

        Popover popover = new Popover();
        popover.setModal(true);
        popover.setBackdropVisible(true);
        popover.setPosition(PopoverPosition.BOTTOM_END);
        popover.setTarget(btnColumns);

        Div heading = new Div("Ver/Ocultar columnas");
        heading.getStyle().set("font-weight", "600");
        heading.getStyle().set("padding", "var(--lumo-space-xs)");

        List<String> columns = List.of("equipo", "departamento", "mesplaneado", "fechaProgramada",
                "fechaMantenimiento", "estado", "situacion", "monitor", "teclado", "mouse", "regulador",
                "cpu", "impresora", "miniprint", "laptop", "escaner");

        CheckboxGroup<String> chkColumns = new CheckboxGroup<>();
        chkColumns.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL);
        chkColumns.setItems(columns);
        chkColumns.setItemLabelGenerator((item) -> {
            String label = StringUtils
                    .join(StringUtils.splitByCharacterTypeCamelCase(item), " ");
            return StringUtils.capitalize(label.toLowerCase());
        });
        chkColumns.addValueChangeListener((e) -> {
            columns.forEach((key) -> {
                Grid.Column<?> col = planAnualGrid.getColumnByKey(key);
                if (col != null) {
                    col.setVisible(e.getValue().contains(key));
                } else {
                    System.out.println("Columna no encontrada para key: " + key);
                }
            });
        });

        Set<String> defaultColumns = Set.of("equipo", "departamento", "mesplaneado",
                "fechaProgramada", "fechaMantenimiento", "estado", "situacion", "encuesta");
        chkColumns.setValue(defaultColumns);

        popover.add(heading, chkColumns);

        return planAnualGrid;
    }

    /*
     * (∩ ͡° ͜ʖ ͡°)⊃━☆ﾟ. * SUSTITUIR VALORES BOOLEANOS POR UN ICONO (∩ ͡° ͜ʖ
     * ͡°)⊃━☆ﾟ. *
     */
    private Icon getIcon(boolean value) {
        if (value) {
            return new Icon(VaadinIcon.CHECK_CIRCLE);
        } else {
            return new Icon();
        }
    }

    /*
     * (∩ ͡° ͜ʖ ͡°)⊃━☆ﾟ. * METODO PARA VALIDAR QUE EL ARCHIOVO TENGA LA ESTRUCTURA
     * CORRECTA (∩ ͡° ͜ʖ ͡°)⊃━☆ﾟ. *
     */
    private List<String> validarExcel(InputStream inputStream) throws IOException {
        List<String> errores = new ArrayList<>();
        Workbook workbook = WorkbookFactory.create(inputStream);
        Sheet sheet = workbook.getSheetAt(0);

        // Lista de nombres de columnas esperados en el encabezado
        List<String> columnas = Arrays.asList("NOMEQUIPO", "DEPARTAMENTO", "MONITOR", "TECLADO", "MOUSE", "REGULADOR",
                "CPU", "IMPRESORA", "MINIPRINT", "LAPTOP", "ESCANER", "FECHAPROG", "TECNICO", "ESTADO");

        // Obtener la primera fila como encabezado
        Row headerRow = sheet.getRow(0);
        if (headerRow != null) {
            // Validar que cada celda en el encabezado tiene el nombre correcto
            for (int i = 0; i < headerRow.getPhysicalNumberOfCells(); i++) {
                Cell cell = headerRow.getCell(i);
                if (cell != null) { // Verificar si la celda no es null antes de acceder a su valor
                    String columnName = cell.getStringCellValue();
                    if (!columnas.contains(columnName)) {
                        errores.add("Columna inesperada: " + columnName);
                    }
                } else {
                    errores.add("Celda vacía en la columna de índice " + i);
                }
            }
        } else {
            errores.add("La hoja no contiene un encabezado en la primera fila.");
        }

        // Verificar si faltan columnas esperadas en el encabezado
        for (String columnName : columnas) {
            boolean found = false;
            if (headerRow != null) {
                for (int i = 0; i < headerRow.getPhysicalNumberOfCells(); i++) {
                    Cell cell = headerRow.getCell(i);
                    if (cell != null && cell.getStringCellValue().equals(columnName)) {
                        found = true;
                        break;
                    }
                }
            }
            if (!found) {
                errores.add("Falta la columna: " + columnName);
            }
        }

        workbook.close();
        return errores;
    }

    // Valida que haya un archivo cargado en el UPLOAD y si si, llama al metodo para
    // insertar el archivo en la base de datos
    private void insertarDatos() {
        if (fileContent == null) {
            Notification.show("Error: No hay archivo cargado.").addThemeVariants(NotificationVariant.LUMO_ERROR);
            return;
        }

        try (InputStream inputStream = new ByteArrayInputStream(fileContent)) {
            databaseService.insertarDesdeExcel(inputStream);
            Notification.show("Archivo insertado correctamente").addThemeVariants(NotificationVariant.LUMO_SUCCESS);
            btnInsertar.setVisible(false); // Ocultar el botón después de la inserción
        } catch (Exception e) {
            Notification.show("Error al insertar el archivo: " + e.getMessage())
                    .addThemeVariants(NotificationVariant.LUMO_ERROR);
        }
    }

    private static Component createFilterHeader(String labelText, Consumer<String> filterChangeConsumer) {
        TextField textField = new TextField();
        textField.setPlaceholder("Buscar...");
        textField.setValueChangeMode(ValueChangeMode.EAGER);
        textField.setClearButtonVisible(true);
        textField.setWidthFull();
        textField.addValueChangeListener(event -> filterChangeConsumer.accept(event.getValue()));

        VerticalLayout layout = new VerticalLayout(textField);
        layout.setSpacing(false);
        layout.setPadding(false);
        return layout;
    }

    private static class PlanAnualFilter {

        private final GridListDataView<PlanAnual> dataView;

        private String smt;
        private String equipo;
        private String departamento;
        private String mesPlaneado;
        private LocalDate fechaProgramada;
        private LocalDate fechaRealizacion;
        private String encuesta;
        private String estado;
        private String situacion;
        private Integer year;
        private boolean excludeRealizado = true;

        public PlanAnualFilter(GridListDataView<PlanAnual> dataView) {
            this.dataView = dataView;
            this.dataView.addFilter(this::test);
        }

        public void setSmt(String smt) {
            this.smt = smt;
            this.dataView.refreshAll();
        }

        public void setEquipo(String equipo) {
            this.equipo = equipo;
            this.dataView.refreshAll();
        }

        public void setDepartamento(String departamento) {
            this.departamento = departamento;
            this.dataView.refreshAll();
        }

        public void setMesPlaneado(String mesPlaneado) {
            this.mesPlaneado = mesPlaneado;
            this.dataView.refreshAll();
        }

        public void setEncuesta(String encuesta) {
            this.encuesta = encuesta;
            this.dataView.refreshAll();
        }

        public void setYear(Integer year) {
            this.year = year;
            dataView.refreshAll();
        }

        public void setExcludeRealizado(boolean excludeRealizado) {
            this.excludeRealizado = excludeRealizado;
            this.dataView.refreshAll();
        }

        public boolean test(PlanAnual planAnual) {
            if (planAnual == null) return false;

            boolean matchesSmt = matches(planAnual.getSmt(), smt);
            boolean matchesEquipo = matches(planAnual.getNomEquipo(), equipo);
            boolean matchesDepartamento = matches(planAnual.getDepartamento(), departamento);
            boolean matchesMesPlaneado = matches(planAnual.getMesplaneado(), mesPlaneado);
            boolean matchesEncuesta = matches(planAnual.getEncuesta(), encuesta);
            
            boolean matchesYear = true;
            if (year != null) {
                LocalDate fecha = planAnual.getFechaProgramada();
                matchesYear = fecha != null && fecha.getYear() == year;
            }

            boolean matchesEstado;
            if (excludeRealizado) {
                matchesEstado = planAnual.getEstado() == null
                        || !"REALIZADO".equalsIgnoreCase(planAnual.getEstado());
            } else {
                matchesEstado =
                        "REALIZADO".equalsIgnoreCase(planAnual.getEstado()) &&
                                !"NO REALIZADO".equalsIgnoreCase(planAnual.getSituacion());
            }

            return matchesSmt
                    && matchesEquipo
                    && matchesDepartamento
                    && matchesMesPlaneado
                    && matchesYear
                    && matchesEstado
                    && matchesEncuesta;
        }

        private boolean matches(String value, String serachTerm) {
            return serachTerm ==  null || serachTerm.isEmpty()
                    || (value != null && value.toLowerCase().contains(serachTerm.toLowerCase()));
        }
    }

    // Aqui validamos que haya registros en el plan anual y si no hay muestra el
    // upload para cargar un nuevo plan anual
    private void toggleLayouts(GridListDataView<PlanAnual> dataView) {
        boolean hasItems = dataView.getItemCount() > 0;

        gridLayout.setVisible(hasItems);
        uploadLayout.setVisible(!hasItems);
    }


    private void sacarReporte() {
        Dialog dialog = new Dialog();
        dialog.setHeaderTitle("Seleccione la fecha de inicio y fin");

        DatePicker.DatePickerI18n i18n = new DatePicker.DatePickerI18n()
                .setWeekdays(List.of("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sabado"))
                .setWeekdaysShort(List.of("Dom", "Lun",  "Mar", "Mié", "Jue", "Vie", "Sáb"))
                .setMonthNames(List.of("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"))
                .setFirstDayOfWeek(1)
                .setToday("Hoy")
                .setCancel("Cancelar")
                .setDateFormat("dd/MM/yyyy");

        DatePicker fechaInicio = new DatePicker("Fecha de inicio:");
        fechaInicio.setRequired(true);
        fechaInicio.setI18n(i18n);

        DatePicker fechaFin = new DatePicker("Fecha de fin:");
        fechaFin.setRequired(true);
        fechaFin.setI18n(i18n);


        Button btnGenerar = new Button("Generar", VaadinIcon.PRINT.create());
        btnGenerar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        btnGenerar.addClickListener(e -> {
            if (fechaInicio.getValue() == null || fechaFin.getValue() == null) {
                Notification.show("Por favor, seleccione ambas fechas.", 3000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
                return;
            }

            LocalDate inicio = fechaInicio.getValue();
            LocalDate fin = fechaFin.getValue();


            try {
                // Prepara los parámetros para el reporte
                Map<String, Object> parametros = new HashMap<>();
                parametros.put("FECHAINICIO", java.sql.Date.valueOf(inicio));
                parametros.put("FECHAFIN", java.sql.Date.valueOf(fin));

                // Genera el PDF
                byte[] pdf = reportService.generarReporte("mantenimientoFechas", parametros);

                // Creando el recurso de descarga
                StreamResource resource = new StreamResource("reporte.pdf", () -> new ByteArrayInputStream(pdf));
                /*Anchor downloadLink = new Anchor(resource, "Descargar Reporte");
                downloadLink.setTarget("_blank");
                downloadLink.setId("descargar-reporte-link");
                add(downloadLink);

                getUI().ifPresent(ui ->
                        ui.getPage().executeJs("document.getElementById('descargar-reporte-link').click();")
                );*/

                StreamRegistration registration = UI.getCurrent().getSession().getResourceRegistry().registerResource(resource);
                UI.getCurrent().getPage().executeJs("window.open('" + registration.getResourceUri().toString() + "','_blank')");


            } catch (Exception ex) {
                Notification.show("Error al genrar el reporte: " + ex.getMessage(), 5000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
                logger.error("Error al generar el reporte", ex);
            }
        });

        Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close());
        dialog.getFooter().add(btnCancelar);
        dialog.getFooter().add(btnGenerar);

        HorizontalLayout fechasLayout = new HorizontalLayout(fechaInicio, fechaFin);
        dialog.add(fechasLayout);

        dialog.open();
    }


    private void addNuevoEquipo() {
        Dialog dialog = new Dialog();
        dialog.setHeaderTitle("Agregar nuevo equipo");

        TextField nombreEquipo = new TextField("Nombre equipo:");
        TextField area = new TextField("Área:");

        DatePicker.DatePickerI18n i18n = new DatePicker.DatePickerI18n()
                .setWeekdays(List.of("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sabado"))
                .setWeekdaysShort(List.of("Dom", "Lun",  "Mar", "Mié", "Jue", "Vie", "Sáb"))
                .setMonthNames(List.of("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"))
                .setFirstDayOfWeek(1)
                .setToday("Hoy")
                .setCancel("Cancelar")
                .setDateFormat("dd/MM/yyyy");
        DatePicker fechaProgramada = new DatePicker("Fecha programada:");
        fechaProgramada.setI18n(i18n);

        List<String> items = List.of("ENERO", "FEBRERO", "MARZO", "ABRIL", "MAYO", "JUNIO",
                "JULIO", "AGOSTO", "SEPTIEMBRE", "OCTUBRE", "NOVIEMBRE", "DICIEMBRE");
        ComboBox<String> cmbMes = new ComboBox<>("Mes Planeado:");
        cmbMes.setItems(items);

        CheckboxGroup<String> group1 = new CheckboxGroup<>();
        group1.setLabel("Seleccione los componentes del equipo");
        group1.setItems("MONITOR","TECLADO","MOUSE","REGULADOR");

        CheckboxGroup<String> group2 = new CheckboxGroup<>();
        group2.setItems("CPU","IMPRESORA","MINIPRINT","LAPTOP","ESCANER");

        HorizontalLayout layout1 = new HorizontalLayout(nombreEquipo, area);
        HorizontalLayout layout2 = new HorizontalLayout(fechaProgramada,cmbMes);
        VerticalLayout layout3 = new VerticalLayout(group1,group2);
        layout3.setSpacing(false);


        Button btnGuardar = new Button("Guardar", LineAwesomeIcon.SAVE_SOLID.create());
        btnGuardar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        btnGuardar.addClickListener(e -> {
            if (nombreEquipo.getValue().isEmpty() || area.getValue().isEmpty() ||
                    fechaProgramada.getValue() == null || cmbMes.getValue() == null) {
                Notification.show("Por favor, complete todos los campos.", 3000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
                return;
            }

            final Map<String, Integer> MES_ID_MAP = new HashMap<>();
            MES_ID_MAP.put("ENERO", 1);
            MES_ID_MAP.put("FEBRERO", 2);
            MES_ID_MAP.put("MARZO", 3);
            MES_ID_MAP.put("ABRIL", 4);
            MES_ID_MAP.put("MAYO", 5);
            MES_ID_MAP.put("JUNIO", 6);
            MES_ID_MAP.put("JULIO", 7);
            MES_ID_MAP.put("AGOSTO", 8);
            MES_ID_MAP.put("SEPTIEMBRE", 9);
            MES_ID_MAP.put("OCTUBRE", 10);
            MES_ID_MAP.put("NOVIEMBRE", 11);
            MES_ID_MAP.put("DICIEMBRE", 12);
            String mesSeleccionado = cmbMes.getValue();
            Integer mesId = MES_ID_MAP.get(mesSeleccionado);


            if (group1.getValue().isEmpty() && group2.getValue().isEmpty()) {
                Notification.show("Debe seleccionar al menos un componente del equipo.", 3000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
                return;
            }

            Set<String> seleccionados = new HashSet<>();
            seleccionados.addAll(group1.getValue());
            seleccionados.addAll(group2.getValue());

            boolean monitor = seleccionados.contains("MONITOR");
            boolean teclado = seleccionados.contains("TECLADO");
            boolean mouse = seleccionados.contains("MOUSE");
            boolean regulador = seleccionados.contains("REGULADOR");
            boolean cpu = seleccionados.contains("CPU");
            boolean impresora = seleccionados.contains("IMPRESORA");
            boolean miniprint = seleccionados.contains("MINIPRINT");
            boolean laptop = seleccionados.contains("LAPTOP");
            boolean escaner = seleccionados.contains("ESCANER");


            databaseService.insertarNuevoEquipo(
                    nombreEquipo.getValue().toUpperCase(),
                    area.getValue().toUpperCase(),
                    monitor,
                    teclado,
                    mouse,
                    regulador,
                    cpu,
                    impresora,
                    miniprint,
                    laptop,
                    escaner,
                    java.sql.Date.valueOf(fechaProgramada.getValue()),
                    "",
                    "PENDIENTE",
                    mesId
            );

            Notification.show("Equipo agregado correctamente", 3000, Notification.Position.MIDDLE)
                    .addThemeVariants(NotificationVariant.LUMO_SUCCESS);
            dialog.close();
            // Recargar el grid para mostrar el nuevo equipo
            planAnualGrid.setItems(databaseService.getPlanAnual());
        });

        Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close());
        dialog.getFooter().add(btnGuardar);
        dialog.getFooter().add(btnCancelar);

        dialog.add(layout1,layout2,layout3);
        dialog.open();
    }

    private void mostrarPopoverReportes() {
        reportePopover = new Popover();
        reportePopover.setModal(true);
        reportePopover.setBackdropVisible(true);
        reportePopover.setPosition(PopoverPosition.BOTTOM_END);
        reportePopover.setTarget(btnImprimirRpt);

        Div headding = new Div("Reportes disponibles");
        headding.getStyle().set("font-weight", "600");
        headding.getStyle().set("padding", "var(--lumo-space-xs)");

        VerticalLayout listaRrportes = new VerticalLayout();
        //listaRrportes.setSpacing(false);
        listaRrportes.setPadding(false);

        Button btnReporteFechas = new Button("Mantenimiento por fechas", VaadinIcon.STAR.create(), e -> {
            reportePopover.close();
            sacarReporte();
        });
        btnReporteFechas.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE);

        Button btnListadoMant = new Button("Listado de mantenimientos", VaadinIcon.STAR.create(), e -> {
            reportePopover.close();
            obtenerListadoRpt();
        });
        btnListadoMant.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE);

        listaRrportes.add(btnReporteFechas, btnListadoMant);
        reportePopover.add(headding, listaRrportes);
    }


    private void obtenerListadoRpt() {
        Dialog dialog = new Dialog();
        dialog.setHeaderTitle("Ingresa el peridodo a consultar");

        TextField txtMes = new TextField("Mes:");
        txtMes.setRequired(true);

        NumberField txtAnio = new NumberField("Año:");
        txtAnio.setRequired(true);

        HorizontalLayout layout = new HorizontalLayout(txtMes, txtAnio);

        Button btnGenerar = new Button("Generar", VaadinIcon.PRINT.create());
        btnGenerar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        btnGenerar.addClickListener(e -> {
            String mes = txtMes.getValue().toUpperCase();
            Integer anio = txtAnio.getValue() != null ? txtAnio.getValue().intValue() : null;

            if (mes.isEmpty() || anio == null) {
                Notification.show("Por favor, completa todos los campos.", 2000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
                return;
            }

            try {
                // Preparando los parámetros para el reporte
                Map<String, Object> parametros = new HashMap<>();
                parametros.put("pMES", mes);
                parametros.put("pANIO", anio);

                // Generando el PDF
                byte[] pdf = reportService.generarReporte("listadoMantenimientos", parametros);

                // Creando el recurso de descarga
                StreamResource resource = new StreamResource("listado_mantenimientos.pdf", () -> new ByteArrayInputStream(pdf));
                /*Anchor downloadLink = new Anchor(resource, "Descargar Reporte");
                downloadLink.setTarget("_blank");
                downloadLink.setId("descargar-listado-link");
                add(downloadLink);

                getUI().ifPresent(ui ->
                        ui.getPage().executeJs("document.getElementById('descargar-listado-link').click();")
                );*/

                StreamRegistration registration = UI.getCurrent().getSession().getResourceRegistry().registerResource(resource);
                UI.getCurrent().getPage().executeJs("window.open('" + registration.getResourceUri().toString() + "','_blank')");

            } catch (Exception ex) {
                Notification.show("Error al generar el reporte: " + ex.getMessage(), 5000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
                logger.error("Error al generar el reporte", ex);
            }
        });

        Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close());
        dialog.getFooter().add(btnCancelar, btnGenerar);

        dialog.add(layout);
        dialog.open();
    }


    private class PersonContextMenu extends GridContextMenu<PlanAnual> {
        public PersonContextMenu(Grid<PlanAnual> target) {
            super(target);

            addItem("Realizar", e -> e.getItem().ifPresent(planAnual -> {
                int idPlananual = planAnual.getNumero();
                LocalDate fechaSistema = LocalDate.now();
                String nomEquipo = planAnual.getNomEquipo();
                String departamento = planAnual.getDepartamento();

                getUI().ifPresent(ui -> ui.navigate(
                        "mantenimiento?id=" + idPlananual +
                                "&fecha=" + fechaSistema +
                                "&tipo=1" +
                                "&nomEquipo=" + nomEquipo +
                                "&departamento=" + departamento));
            }));

            addItem("Borrar", e -> e.getItem().ifPresent(planAnual -> {
                eliminarPlanAnual(planAnual);
            }));

            add(new Hr());

            GridMenuItem<PlanAnual> nomEquipo = addItem("Equipo",
                    e -> e.getItem().ifPresent(planAnual -> {
                        planAnual.getNomEquipo();
                    }));

            GridMenuItem<PlanAnual> depto = addItem("Departamento",
                    e -> e.getItem().ifPresent(planAnual -> {
                        planAnual.getDepartamento();
                    }));

            setDynamicContentHandler(planAnual -> {
                if (planAnual == null)
                    return false;
                nomEquipo.setText(String.format("Equipo: %s", planAnual.getNomEquipo()));
                depto.setText(String.format("Area: %s", planAnual.getDepartamento()));

                return true;
            });
        }
    }

    private void eliminarPlanAnual(PlanAnual planAnual) {
        Dialog dialog = new Dialog();
        dialog.setHeaderTitle("Eliminar Mantenimiento");

        TextField txtMotivo = new TextField("Justifica el motivo de la eliminación");
        txtMotivo.setWidthFull();
        txtMotivo.setRequired(true);

        dialog.add(
                new VerticalLayout(
                        new Span("¿Estás seguro de que deseas eliminar el mantenimiento del equipo: " + planAnual.getNomEquipo()),
                        txtMotivo
                )
        );

        Button btnEliminar = new Button("Eliminar", VaadinIcon.TRASH.create(), event -> {
            String motivo = txtMotivo.getValue();
            if (motivo.isEmpty()) {
                txtMotivo.setErrorMessage("El motivo es requerido.");
                txtMotivo.setInvalid(true);
                return;
            }
            txtMotivo.setInvalid(false);

            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String usuarioId = authentication != null ? authentication.getName().toUpperCase() : "DESCONOCIDO";
            LocalDate fecha = LocalDate.now();

            // Llamar al servicio para insertar la bitácora de eliminación
            databaseService.insertarBitacoraEliminacion(planAnual.getNumero(), usuarioId, fecha, motivo);

            // Llamar al servicio para eliminar el plan anual
            databaseService.eliminarEquipoPlanAnual(planAnual.getNumero());
            Notification.show("Equipo eliminado correctamente", 3000, Notification.Position.MIDDLE)
                    .addThemeVariants(NotificationVariant.LUMO_SUCCESS);
            dialog.close();
            UI.getCurrent().getPage().executeJs("setTimeout(() => { location.reload(); }, 2000);");
        });

        Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close());

        HorizontalLayout dialogFooter = new HorizontalLayout(btnEliminar, btnCancelar);
        dialog.getFooter().add(dialogFooter);
        dialog.open();
    }



    private void showParametrosDialog() {
        Dialog dialog = new Dialog();
        dialog.setHeaderTitle("Ingresar periodo");

        TextField txtMes = new TextField("Mes:");
        txtMes.setPlaceholder("ENERO, FEBRERO, MARZO...");
        txtMes.setClearButtonVisible(true);

        TextField txtAnio = new TextField("Año");
        txtAnio.setPlaceholder("Ej. 2025");

        Button btnBuscar = new Button("Buscar", VaadinIcon.SEARCH.create(), e -> {
            String mes = txtMes.getValue();
            String anioTexto = txtAnio.getValue();

            if (mes.isEmpty() || anioTexto.isEmpty()) {
                Notification.show("Mes y año son requeridos.", 3000, Notification.Position.MIDDLE);
                return;
            }

            int anio;
            try {
                anio = Integer.parseInt(anioTexto);
            } catch (NumberFormatException ex) {
                Notification.show("El año debe ser numérico.", 3000, Notification.Position.MIDDLE);
                return;
            }

            dialog.close();
            showEncuestasDialog(mes, anio);
        });
        btnBuscar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);

        Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close());

        HorizontalLayout actions = new HorizontalLayout(btnBuscar, btnCancelar);

        VerticalLayout layout = new VerticalLayout(txtMes, txtAnio, actions);
        layout.setPadding(false);
        layout.setSpacing(true);

        dialog.add(layout);
        dialog.open();
    }

    private void showEncuestasDialog(String mes, int anio) {
        Dialog dialog = new Dialog();
        dialog.setWidth("95%");
        dialog.setHeight("90%");
        dialog.setHeaderTitle("Encuestas pendientes por enviar...");

        Grid<MantenimientosSinEncuesta> grid = new Grid<>(MantenimientosSinEncuesta.class, false);
        grid.addColumn(MantenimientosSinEncuesta::getMantenimientoId)
                        .setHeader("ID")
                                .setAutoWidth(true);

        grid.addColumn(item -> item.getFecha().format(DateTimeFormatter.ofPattern("dd/MM/yyyy")))
                .setHeader("Fecha")
                        .setAutoWidth(true);

        grid.addColumn(MantenimientosSinEncuesta::getPeriodo)
                .setHeader("Periodo")
                        .setAutoWidth(true);

        grid.addColumn(createStatusRender())
                .setHeader("Encuesta");

        grid.addColumn(createTokenRender())
                        .setHeader("Token");

        /*grid.addColumn(MantenimientosSinEncuesta::getDepartamento)
                .setHeader("Departamento");*/

        grid.addColumn(MantenimientosSinEncuesta::getNomUsuario)
                .setHeader("Usuario")
                .setAutoWidth(true);

        grid.addColumn(MantenimientosSinEncuesta::getEmail)
                .setHeader("Correo")
                .setAutoWidth(true);

        grid.addComponentColumn(item -> {
            Button btnEnviar = new Button(
                    "Enviar",
                    LineAwesomeIcon.ENVELOPE_SOLID.create()
            );
            btnEnviar.addThemeVariants(ButtonVariant.LUMO_PRIMARY,
                    ButtonVariant.LUMO_SUCCESS);

            if (item.isTieneToken()) {
                btnEnviar.setEnabled(false);
                btnEnviar.setText("Enviado");
            }

            btnEnviar.addClickListener(e -> {
                enviarEncuestaDesdeGrid(item);
                btnEnviar.setEnabled(false);
            });

            return btnEnviar;
        }).setHeader("Accion")
                .setFrozen(true);

        List<MantenimientosSinEncuesta> lista = databaseService.getEncuestPendientes(mes, anio);

        grid.setItems(lista);
        grid.addThemeVariants(GridVariant.LUMO_WRAP_CELL_CONTENT);
        dialog.add(grid);
        dialog.getFooter().add(new Button("Cerrar", LineAwesomeIcon.TIMES_SOLID.create(), e -> dialog.close()));

        dialog.open();
    }

    private void enviarEncuestaDesdeGrid(MantenimientosSinEncuesta item) {

        if (item.getEmail() == null || item.getEmail().isBlank()) {
            Notification.show("El usuario no tiene correo", 3000, Notification.Position.MIDDLE)
                    .addThemeVariants(NotificationVariant.LUMO_ERROR);
            return;
        }

        int mantenimientoId = item.getMantenimientoId();

        String token = databaseService.crearTokenEncuesta(mantenimientoId);
        String linkEncuesta = baseUrl + "/encuesta?token=" + token;

        String cuerpo = """
            <html>
              <body>
                <a href="%s">
                  <img src="cid:image_id"/>
                </a>
              </body>
            </html>
            """.formatted(linkEncuesta);

        String asunto = "Encuesta de satisfacción - Mantenimiento #" + mantenimientoId;
        String imagePath = "META-INF/resources/images/imgCorreo/imgEncuesta.png";

        emailService.enviarCorreo(
                item.getEmail(),
                asunto,
                cuerpo,
                imagePath
        );

        Notification.show("Encuesta enviada correctamente", 3000, Notification.Position.MIDDLE)
                .addThemeVariants(NotificationVariant.LUMO_SUCCESS);
    }

    private ComponentRenderer<Span, MantenimientosSinEncuesta> createStatusRender() {
        return new ComponentRenderer<>(encuesta -> {
            Span span = new Span(encuesta.getEncuesta());

            switch (encuesta.getEncuesta().toUpperCase()) {
                case "N":
                    String theme1 = String.format("badge %s", "error");
                    span.getElement().setAttribute("theme", theme1);
                    break;
                case "S":
                    String theme2 = String.format("badge %s", "success");
                    span.getElement().setAttribute("theme", theme2);
                    break;
                default:
                    String theme3 = String.format("badge %s", "");
                    span.getElement().setAttribute("theme", theme3);
            }

            return span;
        });
    }

    private ComponentRenderer<Span, MantenimientosSinEncuesta> createTokenRender() {
        return new ComponentRenderer<>(token -> {
            Span span = new Span(String.valueOf(token.isTieneToken()));

            if (token.isTieneToken()) {
                span.setText("S");
                String theme2 = String.format("badge %s", "success");
                span.getElement().setAttribute("theme", theme2);
            } else {
                span.setText("N");
                String theme1 = String.format("badge %s", "error");
                span.getElement().setAttribute("theme", theme1);
            }

            return span;
        });
    }
}
