package mx.gob.jumapacelaya.ui;

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.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.html.Image;
import com.vaadin.flow.component.html.Span;
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.radiobutton.RadioButtonGroup;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import de.f0rce.signaturepad.SignaturePad;
import jakarta.annotation.security.PermitAll;
import mx.gob.jumapacelaya.models.*;
import mx.gob.jumapacelaya.services.DatabaseService;
import mx.gob.jumapacelaya.services.EmailService;
import mx.gob.jumapacelaya.services.SecurityService;
import mx.gob.jumapacelaya.services.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.lineawesome.LineAwesomeIcon;

import java.time.LocalDate;
import java.util.*;


@PermitAll
@PageTitle("Mantenimiento")
@Route(value = "mantenimiento", layout = MainLayout.class)
@CssImport("./themes/sistema-mantenimiento/styles.css")
public class MantenimientoView extends VerticalLayout implements BeforeEnterObserver {

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

    private final SecurityService securityService;
    private final VerticalLayout controlsLayout;
    private final DatabaseService databaseService;
    private final VerticalLayout actualizacionesLayout;
    private final VerticalLayout etiquetaLayout;
    private final HorizontalLayout firmasLayout;
    private final DatePicker fecha;
    private final TextField txtPlananualID;
    private final ComboBox<TiposMantenimiento> tipoMantt;
    private final ComboBox<DepartamentosModel> area;
    private final ComboBox<Usuario> usuario;
    private final TextField txtNombreEquipo;
    private final UserService userService;
    private final EmailService emailService;
    private RadioButtonGroup<String> formaGroup;
    private CheckboxGroup<String> actualizaciones;
    private final HorizontalLayout botonesLayout;
    private TextArea txtCuales;
    private RadioButtonGroup<String> masActualizacionesGroup;
    private SignaturePad userSignPad;
    private SignaturePad smtSignPad;
    //private SignaturePad gciatiSignPad;
    private PlanAnual planAnualActual;
    private LocalDate fechaProgramada;
    private LocalDate fechaSeleccionada;
    private TextArea jsutificacion;
    private VerticalLayout mainLayout;


    Span userSignSpan = new Span("Nombre Usuario");


    public MantenimientoView(UserService userService, SecurityService securityService, EmailService emailService, DatabaseService databaseService) {
        this.databaseService = databaseService;
        this.controlsLayout = new VerticalLayout();
        this.actualizacionesLayout = new VerticalLayout();
        this.etiquetaLayout = new VerticalLayout();
        this.firmasLayout = new HorizontalLayout();
        this.botonesLayout = new HorizontalLayout();
        this.securityService = securityService;
        this.userService = userService;
        this.emailService = emailService;

        mainLayout = new VerticalLayout();
        mainLayout.setHeightFull();
        mainLayout.getStyle()
                .set("box-shadow","0 4px 8px rgba(0,0,0,0.2)")
                .set("border-radius", "12px")
                .set("padding", "1rem")
                .set("margin", "1rem auto");

        HorizontalLayout fechaLayout = new HorizontalLayout();
        //Componentes de texto
        TextField nomenclatura = new TextField("Nomenclatura");
        nomenclatura.setReadOnly(true);
        nomenclatura.addClassName("mantenimiento-text-field");

        TextArea otras = new TextArea("¿Cuales?");
        otras.setEnabled(false);
        otras.addClassName("mantenimiento-text-field");

        //Selector de fecha
        this.fecha = new DatePicker("Fecha");
        fecha.setRequired(true);
        fecha.setLocale(new Locale("es", "MX"));
        DatePicker.DatePickerI18n i18n = new DatePicker.DatePickerI18n()
        .setWeekdays(List.of("Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"))
        .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");
        fecha.setI18n(i18n);


        // Campo de texto para el ID de MTTOPROGRAMADO
        this.txtPlananualID = new TextField("Plan Anual ID");
        txtPlananualID.setReadOnly(true);
        txtPlananualID.addClassName("mantenimiento-text-field");


        // ComboBox Tipo de Mantenimiento
        this.tipoMantt = new ComboBox<>("Tipo de Mantenimiento");
        List<TiposMantenimiento> tiposMantenimiento = databaseService.getTiposDeMantenimientos();
        tipoMantt.setItems(tiposMantenimiento);
        tipoMantt.addClassName("mantenimiento-combo");

        // Listener para manejar el cambio en el tipo de mantenimiento
        tipoMantt.addValueChangeListener(event -> {
            TiposMantenimiento tipoSeleccionado = event.getValue();
            if (tipoSeleccionado != null) {
                // Actualizar nomenclatura dependiendo del tipo de mantenimiento
                String nomenclaturaValue = databaseService.getNomenclatura(tipoSeleccionado.getTipomantId());
                nomenclatura.setValue(nomenclaturaValue);

                // Si el tipo es preventivo se establecerá la fecha automáticamente a la fecha del sistema
                if ("1".equals(tipoSeleccionado.getTipomantId())) { // 1 es para PREVENTIVO
                    this.fecha.setValue(LocalDate.now());
                    etiquetaLayout.setVisible(false);
                    // Limpiar el layout de correctivo si es necesario
                    etiquetaLayout.removeAll();
                } else if ("2".equals(tipoSeleccionado.getTipomantId())) { // 2 es para CORRECTIVO
                    this.fecha.clear();
                    etiquetaLayout.setVisible(true);
                    //correctivoLayout();
                } else {
                    // Para otros tipos de mantenimiento
                    this.fecha.clear();
                    etiquetaLayout.setVisible(false);
                    etiquetaLayout.removeAll(); // Limpia el layout para otros tipos
                }
            } else {
                nomenclatura.clear();
                this.fecha.clear();
                etiquetaLayout.setVisible(false);
                etiquetaLayout.removeAll(); // Limpia el layout
            }
        });
        fechaLayout.add(this.fecha/*, this.txtPlananualID*/);
        fechaLayout.addAndExpand(new HorizontalLayout());
        fechaLayout.add(tipoMantt, nomenclatura);
        fechaLayout.setWidthFull();


        HorizontalLayout departamentoLayout = new HorizontalLayout();
        //ComboBox Area o Departamento
        this.area = new ComboBox<>("Area o Departamento");
        area.setRequired(true);
        List<DepartamentosModel> areas = databaseService.getDepartamentos();
        area.setItems(areas);

        this.usuario = new ComboBox<>("Usuario");
        List<Usuario> usuarios = databaseService.getUsuarios();
        usuario.setItems(usuarios);
        usuario.setItemLabelGenerator(Usuario::getNombre);
        usuario.setRequired(true);

        usuario.addValueChangeListener(event -> {
            Usuario usuarioSeleccionado = event.getValue();
            if (usuarioSeleccionado != null) {
                String empleadoId = usuarioSeleccionado.getEmpleadoId();
                String nombreUsuario = usuarioSeleccionado.getNombre();
                userSignSpan.setText(nombreUsuario);
            } else {
                userSignSpan.setText("S.M.T Nombre");
            }
        });


        // Boton auxiliar para probar el envio de los correos electronicos
        Button btnEnviarCorreo = new Button("Enviar correo de prueba");
        btnEnviarCorreo.addClickListener(event -> enviarCorreo());


        this.txtNombreEquipo = new TextField("Nombre del Equipo");
        txtNombreEquipo.setRequired(true);
        //txtNombreEquipo.setReadOnly(true);


        departamentoLayout.add(area, usuario/*, btnEnviarCorreo*/, txtNombreEquipo);
        departamentoLayout.setWidthFull();

        createHardwareSection(databaseService);
        addActualizacionesSection();
        //correctivoLayout();
        signLayout();
        buttons();


        mainLayout.add(fechaLayout, departamentoLayout, controlsLayout, actualizacionesLayout, etiquetaLayout, firmasLayout, botonesLayout);
        add(mainLayout);
    }


    private void createHardwareSection(DatabaseService databaseService) {
        HorizontalLayout etiquetaLayout = new HorizontalLayout();
        Span etiqueta = new Span("Limpieza de Equipo Realizada");

        //Boton para agregar otro tipo de hardware
        Button btnAgregarTipo = new Button(new Icon(VaadinIcon.PLUS));
        btnAgregarTipo.addThemeVariants(ButtonVariant.LUMO_ICON);
        btnAgregarTipo.setAriaLabel("Agregar Tipo");

        //Listener del boton para agregar mas
        btnAgregarTipo.addClickListener(event -> {
            addNuevoTipo();
        });

        etiquetaLayout.add(etiqueta, btnAgregarTipo);
        controlsLayout.add(etiquetaLayout);
        controlsLayout.setSpacing(false);

        addNuevoTipo();
    }


    //Metodo para agregar un nuevo ComboBox de tipo de hardware y campos de texto
    private List<HorizontalLayout> hardwareLayouts = new ArrayList<>();
    private void addNuevoTipo() {
        ComboBox<TiposHardware> tipoHardware = new ComboBox<>();
        tipoHardware.setPlaceholder("Tipo de hardware");
        tipoHardware.setItemLabelGenerator(TiposHardware::getNombreHardware);
        tipoHardware.setItems(databaseService.getTiposHardware());
        tipoHardware.setSizeFull();

        TextField noSerie = new TextField();
        noSerie.setEnabled(false);
        noSerie.setRequired(true);
        noSerie.setPlaceholder("No. Serie");
        noSerie.setSizeFull();
        noSerie.addValueChangeListener(event -> {
            String upperCaseValue = event.getValue().toUpperCase();
            noSerie.setValue(upperCaseValue);
        });
        // Validacion para que este campo solo acepte numeros
        /*noSerie.getElement().executeJs(
                "this.addEventListener('input', function(e) { " +
                        "  e.target.value = e.target.value.replace(/[^0-9]/g, '');" + // Solo permite dígitos
                        "});"
        );*/

        TextField modelo = new TextField();
        modelo.setEnabled(false);
        modelo.setRequired(true);
        modelo.setPlaceholder("Modelo");
        modelo.setSizeFull();
        modelo.addValueChangeListener(event -> {
            String upperCaseValue = event.getValue().toUpperCase();
            modelo.setValue(upperCaseValue);
        });

        TextField placa = new TextField();
        placa.setEnabled(false);
        placa.setRequired(true);
        placa.setPlaceholder("Placa");
        placa.setSizeFull();
        // Validacion para que este campo solo acepte numeros
        placa.getElement().executeJs(
                "this.addEventListener('input', function(e) { " +
                        "  e.target.value = e.target.value.replace(/[^0-9]/g, '');" + // Solo permite dígitos
                        "});"
        );

        tipoHardware.addValueChangeListener(event -> {
            TiposHardware tipoSeleccionado = event.getValue();

            if (tipoSeleccionado != null) {
                String nombreTipo = tipoSeleccionado.getNombreHardware();
                if ("TECLADO".equals(nombreTipo)) {
                    noSerie.setEnabled(false);
                    modelo.setEnabled(false);
                    placa.setEnabled(false);
                } else if ("MOUSE".equals(nombreTipo)) {
                    noSerie.setEnabled(false);
                    modelo.setEnabled(false);
                    placa.setEnabled(false);
                } else {
                    noSerie.setEnabled(true);
                    modelo.setEnabled(true);
                    placa.setEnabled(true);
                }
            } else {
                noSerie.setEnabled(false);
                modelo.setEnabled(false);
                placa.setEnabled(false);
            }
        });


        //Boton para eliminar ese conjunto de hardware
        Button btnEliminar = new Button(new Icon(VaadinIcon.TRASH));
        btnEliminar.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_ERROR);
        btnEliminar.setAriaLabel("Eliminar Tipo");

        //Crear nuevo layout horizontal con estos campos
        HorizontalLayout hardwareDetailsLayout = new HorizontalLayout();
        hardwareDetailsLayout.add(tipoHardware, noSerie, modelo, placa, btnEliminar);
        hardwareDetailsLayout.setWidthFull();

        hardwareLayouts.add(hardwareDetailsLayout);
        controlsLayout.add(hardwareDetailsLayout);


        //Listener para eliminar el tipo
        btnEliminar.addClickListener(event -> {
            controlsLayout.remove(hardwareDetailsLayout);
        });


        controlsLayout.add(hardwareDetailsLayout);
        controlsLayout.setSizeFull();
    }


    private void addActualizacionesSection() {
        VerticalLayout etiquetaLayout = new VerticalLayout();
        Span Titulo = new Span("Actualizaciones de Seguridad Informatica:");
        etiquetaLayout.add(Titulo);

        this.actualizaciones = new CheckboxGroup<>();
        actualizaciones.setLabel("Actualizaciones Necesarias");
        actualizaciones.setItems("S.O", "Antivirus", "Firewall");

        this.formaGroup = new RadioButtonGroup<>();
        formaGroup.setRequired(true);
        formaGroup.setLabel("Actividad Realizada de Forma:");
        formaGroup.setItems("Remota", "Manual");

        this.txtCuales = new TextArea();
        txtCuales.setLabel("¿Cuales?");
        txtCuales.setEnabled(false);
        txtCuales.setWidthFull();

        this.masActualizacionesGroup= new RadioButtonGroup<>();
        masActualizacionesGroup.setRequired(true);
        masActualizacionesGroup.setLabel("¿Requiere Más Actualizaciones?");
        masActualizacionesGroup.setItems("Si","No");
        masActualizacionesGroup.addValueChangeListener(event -> {
            if ("Si".equals(event.getValue())) {
                txtCuales.setEnabled(true);
                txtCuales.setRequired(true);
                txtCuales.setMaxHeight("100px");
            } else {
                txtCuales.setEnabled(false);
                txtCuales.setRequired(false);
                txtCuales.clear();
            }
        });


        /*VerticalLayout actualizacionesGroup = new VerticalLayout();
        actualizacionesGroup.add(actualizaciones);*/


        HorizontalLayout formasLayout = new HorizontalLayout();
        formasLayout.add(formaGroup, masActualizacionesGroup, txtCuales);
        formasLayout.setSizeFull();


        actualizacionesLayout.add(Titulo, actualizaciones, formasLayout);
        actualizacionesLayout.setSpacing(false);
    }


    /* Formulario para cuando el mnatenimiento es de tipo CORRECTIVO */
    /*private void correctivoLayout() {
        Span Titulo = new Span("Reparación Realizada al Equipo: ");

        // Verificar el ID del tipo de mantenimiento
        TiposMantenimiento tiposMantenimiento = tipoMantt.getValue();
        if (tiposMantenimiento != null && "2".equals(tiposMantenimiento.getTipomantId())) { // Solo si el tipo es CORRECTIVO
            TextField txtModelo = new TextField();
            txtModelo.setPlaceholder("Modelo");
            txtModelo.setWidth("240px");

            NumberField txtSerie = new NumberField();
            txtSerie.setPlaceholder("No. Serie");
            txtSerie.setWidth("240px");

            TextField txtSoft = new TextField();
            txtSoft.setPlaceholder("Instalación de Software");
            txtSoft.setWidth("500px");

            TextField txtRepHard = new TextField();
            txtRepHard.setPlaceholder("Reparación de Hardware");
            txtRepHard.setWidth("500px");

            TextField txtCamDisp = new TextField();
            txtCamDisp.setPlaceholder("Cambio de Dispositivo");
            txtCamDisp.setWidth("500px");

            HorizontalLayout model = new HorizontalLayout();
            model.add(txtModelo, txtSerie, txtSoft);
            model.setSizeFull();

            HorizontalLayout hard = new HorizontalLayout();
            hard.add(txtRepHard, txtCamDisp);
            hard.setSizeFull();

            etiquetaLayout.add(Titulo, model, hard);
            etiquetaLayout.setVisible(true); // Asegúrate de que el layout esté visible
        } else {
            etiquetaLayout.setVisible(false); // Ocultar si no es correctivo
        }
    }*/



    private String emptySignature;

    private void signLayout() {
        VerticalLayout userSignLayout = new VerticalLayout();
        userSignPad = new SignaturePad();
        userSignPad.setBackgroundColor("#FFFFFF");
        userSignPad.setHeight("200px");
        userSignPad.setPenColor("#000000");
        userSignPad.getElement().getStyle().set("border", "1px solid black");
        Span tituloUser = new Span("Usuario Interno");
        userSignLayout.setSizeFull();
        userSignLayout.setSpacing(true);
        userSignLayout.setSpacing(false);
        userSignLayout.setAlignItems(Alignment.CENTER);
        userSignLayout.add(userSignPad, userSignSpan, tituloUser);


        VerticalLayout smtSignLayout = new VerticalLayout();
        smtSignPad = new SignaturePad();
        smtSignPad.setHeight("200px");
        smtSignPad.setBackgroundColor("#FFFFFF");
        smtSignPad.setPenColor("#000000");
        smtSignPad.getElement().getStyle().set("border", "1px solid black");
        String u = securityService.getAuthenticatedUser();
        Span smtSignSpan = new Span(u);
        Span tituloSMT = new Span("Responsable de Soporte");
        smtSignLayout.setSizeFull();
        smtSignLayout.setSpacing(true);
        smtSignLayout.setSpacing(false);
        smtSignLayout.setAlignItems(Alignment.CENTER);
        smtSignLayout.add(smtSignPad, smtSignSpan, tituloSMT);

        VerticalLayout gcialSignLayout = new VerticalLayout();
        Image firmaGcia = new Image("images/FirmaGerenteTI.png", "Firma Gerente de Sistemas");
        firmaGcia.setHeight("200px");
        firmaGcia.setWidthFull();
        Span gciatiSignSpan = new Span("Ing. Javier Patiño Martinez");
        Span tituloGerente = new Span("Gerente de T.I");
        gcialSignLayout.setSizeFull();
        gcialSignLayout.setSpacing(false);
        gcialSignLayout.setAlignItems(Alignment.CENTER);
        gcialSignLayout.add(firmaGcia, gciatiSignSpan, tituloGerente);



        firmasLayout.add(userSignLayout, smtSignLayout, gcialSignLayout);
        firmasLayout.setWidthFull();
        firmasLayout.setSpacing(false);
        firmasLayout.setJustifyContentMode(JustifyContentMode.CENTER);
    }


    // Metodo para verificar si la firma corresponde a una cadena de firma vacia
    private boolean esFirmaVacia(String firmaBase64) {

        String firmaVacia = "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";
        return firmaBase64.equals(firmaVacia);

    }


    private void buttons() {
        VerticalLayout buttonsLayout = new VerticalLayout();
        Button btnGuardar = new Button("Guardar", LineAwesomeIcon.SAVE.create());
        btnGuardar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        btnGuardar.addThemeVariants(ButtonVariant.LUMO_LARGE);


        btnGuardar.addClickListener(event -> {

            if (planAnualActual == null) {
                Notification.show("No se pudo cargar el Plan Anual. Verifica el ID.", 4000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
            }

            if (planAnualActual != null) {
                fechaProgramada = planAnualActual.getFechaProgramada();
                fechaSeleccionada = fecha.getValue();
                boolean mismoMes = fechaSeleccionada != null &&
                        fechaSeleccionada.getMonthValue() == fechaProgramada.getMonthValue() &&
                        fechaSeleccionada.getYear() == fechaProgramada.getYear();

                if (!mismoMes) {
                    Dialog confirmDialog = new Dialog();
                    Span aviso = new Span("El mantenimiento esta fuera de tiempo, justifique el motivo");
                    jsutificacion = new TextArea();
                    jsutificacion.setSizeFull();
                    Button btnSi = new Button("Guardar",LineAwesomeIcon.SAVE_SOLID.create(), e -> {
                        confirmDialog.close();
                        guardarMantenimiento();
                    });
                    btnSi.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
                    VerticalLayout layout = new VerticalLayout(aviso, jsutificacion, btnSi);
                    layout.setSizeFull();
                    layout.setAlignItems(Alignment.CENTER);
                    confirmDialog.add(layout);
                    confirmDialog.open();
                } else {
                    guardarMantenimiento();
                }
            }
        });

        buttonsLayout.setSizeFull();
        buttonsLayout.add(btnGuardar);
        buttonsLayout.setAlignItems(Alignment.CENTER);
        botonesLayout.add(buttonsLayout);
        botonesLayout.setSizeFull();
        //botonesLayout.setAlignItems(Alignment.CENTER);
    }


    // METODO PARA ENVIAR CORREOS ELECTRONICOS
    private void enviarCorreo() {
        Usuario usuarioSeleccionado = usuario.getValue();
        if (usuarioSeleccionado != null && usuarioSeleccionado.getEmail() != null) {
            String destinatario = usuarioSeleccionado.getEmail();
            String asunto = "MANTENIMIENTO DE EQUIPO DE COMPUTO REALIZADO";

            String cuerpo = "<html>" +
                                "<body>" +
                                    "<img src='cid:image_id'/>"+
                                "</body>" +
                            "</html>";

            String imagePath = "META-INF/resources/images/imgCorreo/MttoRealizado.png";

            emailService.enviarCorreo(destinatario, asunto, cuerpo, imagePath);

        } else {
            Notification.show("Por favor selecciona un usuario", 4000, Notification.Position.MIDDLE);
        }
    }


    private void guardarMantenimiento() {
        TiposMantenimiento tiposMantenimiento  = tipoMantt.getValue();
        String tipoMantId = tiposMantenimiento != null ? tiposMantenimiento.getTipomantId() : null;
        String planAnualValue = txtPlananualID.getValue();
        String justificacionValue = jsutificacion != null ? jsutificacion.getValue() : null;
        String reparacionValue = null;

        DepartamentosModel departamentoSeleccionado = area.getValue();
        String departamentoId = departamentoSeleccionado != null ? departamentoSeleccionado.getDepartamentoId().toString() : null;

        Usuario usuarioSeleccionado = usuario.getValue();
        String empleadoId = usuarioSeleccionado != null ? usuarioSeleccionado.getEmpleadoId().toString() : null;
        String equipoId = txtNombreEquipo.getValue();

        String formaSeleccionada = formaGroup.getValue();
        String formaMantt = null;
        if ("Remota".equals(formaSeleccionada)) {
            formaMantt = "R";
        } else if ("Manual".equals(formaSeleccionada)) {
            formaMantt = "M";
        }

        // Validación de campos obligatorios
        if (fechaSeleccionada == null || tipoMantId == null || departamentoId == null || empleadoId == null ||
                equipoId == null || equipoId.trim().isEmpty() || formaMantt == null || planAnualValue == null || planAnualValue.trim().isEmpty()) {
            Notification.show("Por favor, completa todos los campos requeridos", 4000, Notification.Position.MIDDLE);
            return;
        }

        byte[] userSignatureBytes = userSignPad.getImageBase64();
        byte[] smtSignatureBytes = smtSignPad.getImageBase64();
        //byte[] gciaSignatureBytes = gciatiSignPad.getImageBase64();

        String userSignatureBase64 = Base64.getEncoder().encodeToString(userSignatureBytes);
        String smtSignatureBase64 = Base64.getEncoder().encodeToString(smtSignatureBytes);
        //String gciaSignatureBase64 = Base64.getEncoder().encodeToString(gciaSignatureBytes);

        if (esFirmaVacia(userSignatureBase64)) userSignatureBase64 = null;
        if (esFirmaVacia(smtSignatureBase64)) smtSignatureBase64 = null;
        //if (esFirmaVacia(gciaSignatureBase64)) gciaSignatureBase64 = null;


        // Validación de campos de hardware
        List<Map<String, String>> detallesHardware = new ArrayList<>();
        for (HorizontalLayout layout : hardwareLayouts) {
            ComboBox<TiposHardware> tipoHardware = (ComboBox<TiposHardware>) layout.getComponentAt(0);
            TextField noSerie = (TextField) layout.getComponentAt(1);
            TextField modelo = (TextField) layout.getComponentAt(2);
            TextField placa = (TextField) layout.getComponentAt(3);

            TiposHardware tipoSeleccionado = tipoHardware.getValue();
            if (tipoSeleccionado == null) {
                Notification.show("Por favor, selecciona un tipo de hardware", 4000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_WARNING);
                return;
            }

            boolean esOpcional = Arrays.asList("TECLADO", "MOUSE").contains(tipoSeleccionado.getNombreHardware());

            String numSerie = noSerie.getValue();
            String modeloVal = modelo.getValue();
            String placaVal = placa.getValue();

            if (!esOpcional && (modeloVal == null || modeloVal.isEmpty() || numSerie == null || numSerie.isEmpty() || placaVal == null || placaVal.isEmpty())) {
                Notification.show("Por favor, completa todos los campos de hardware.", 4000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_WARNING);
                return;
            }

            Map<String, String> hw = new HashMap<>();
            hw.put("tipoHardwareId", tipoSeleccionado.getTipoHardwareId());
            hw.put("numSerie", numSerie);
            hw.put("modelo", modeloVal);
            hw.put("placa", placaVal);
            detallesHardware.add(hw);
        }

        Set<String> actualizacionesSeleccionadas = actualizaciones.getSelectedItems();
        String otrasActualizaciones = null;
        if ("Si".equals(masActualizacionesGroup.getValue())) {
            otrasActualizaciones = txtCuales.getValue();
            if (otrasActualizaciones == null || otrasActualizaciones.trim().isEmpty()) {
                Notification.show("Especifica las otras actualizaciones", 4000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_WARNING);
                return;
            }
        }

        // Una vez que validamos todos los campos del formulario, procedemos a insertar en BD
        try {
            int isInserted = databaseService.insertarMantenimiento(fechaSeleccionada, tipoMantId, departamentoId, empleadoId, formaMantt, equipoId, userSignatureBase64, smtSignatureBase64, planAnualValue, justificacionValue, reparacionValue);

            if (isInserted <= 0) {
                Notification.show("Error al guardar el mantenimiento", 4000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
                return;
            }

            int mantenimientoId = databaseService.getUltimoMantenimientoId();

            for (Map<String, String> hw : detallesHardware) {
                boolean ok = databaseService.insertarHardware(
                        hw.get("tipoHardwareId"),
                        hw.get("numSerie"),
                        hw.get("modelo"),
                        hw.get("placa"),
                        mantenimientoId
                );

                if (!ok) {
                    Notification.show("Error al insertar detalles del hardware: ", 4000, Notification.Position.MIDDLE)
                            .addThemeVariants(NotificationVariant.LUMO_ERROR);
                    return;
                }
            }

            for (String act : actualizacionesSeleccionadas) {
                boolean ok = databaseService.insertActualizacionSeg(act, null, mantenimientoId);
                if (!ok) {
                    Notification.show("Error al insertar actualización de seguridad", 4000, Notification.Position.MIDDLE)
                            .addThemeVariants(NotificationVariant.LUMO_ERROR);
                    return;
                }
            }

            if (otrasActualizaciones != null) {
                boolean ok = databaseService.insertActualizacionSeg("Otras", otrasActualizaciones, mantenimientoId);
                if (!ok) {
                    Notification.show("Error al insertar otras actualizaciones", 4000, Notification.Position.MIDDLE)
                            .addThemeVariants(NotificationVariant.LUMO_ERROR);
                    return;
                }
            }

            // === EXITO ===
            Notification.show("¡Mantenimiento guardado exitosamente!", 4000, Notification.Position.MIDDLE)
                    .addThemeVariants(NotificationVariant.LUMO_SUCCESS);

            try {
                enviarCorreo();
            } catch (Exception e) {
                Notification.show("Error al enviar el correo", 4000, Notification.Position.MIDDLE)
                        .addThemeVariants(NotificationVariant.LUMO_ERROR);
                logger.error("Error al enviar el correo", e);
            }

            // Limpiar campos
            fecha.clear();
            txtPlananualID.clear();
            tipoMantt.clear();
            area.clear();
            usuario.clear();
            txtNombreEquipo.clear();
            formaGroup.clear();
            actualizaciones.clear();
            masActualizacionesGroup.clear();
            txtCuales.clear();
            userSignPad.clear();
            smtSignPad.clear();
            //gciatiSignPad.clear();

            for (HorizontalLayout layout : hardwareLayouts) {
                ((ComboBox<?>) layout.getComponentAt(0)).clear();
                ((TextField) layout.getComponentAt(1)).clear();
                ((TextField) layout.getComponentAt(2)).clear();
                ((TextField) layout.getComponentAt(3)).clear();
            }

            UI.getCurrent().navigate("/");

        } catch (Exception ex) {
            Notification.show("Ocurrio un error inesperado: " + ex.getMessage(), 5000, Notification.Position.MIDDLE)
                    .addThemeVariants(NotificationVariant.LUMO_ERROR);
            logger.error("Error al insertar mantenimiento", ex);
        }
    }


    @Override
    public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
        String fechaParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("fecha") != null
                ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("fecha").stream().findFirst().orElse(null)
                : null;

        String tipoParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("tipo") != null
                ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("tipo").stream().findFirst().orElse(null)
                : null;

        String idParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("id") != null
                ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("id").stream().findFirst().orElse(null)
                : null;
        if (idParam != null) {
            try {
                int id = Integer.parseInt(idParam);
                planAnualActual = databaseService.getPlanAnualPorId(id);
            } catch (NumberFormatException e) {
                planAnualActual = null;
            }
        }

        String equipoParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("nomEquipo") != null
                ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("nomEquipo").stream().findFirst().orElse(null)
                : null;

        String deptoParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("departamento") != null
                ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("departamento").stream().findFirst().orElse(null)
                : null;

        if (fechaParam != null) {
            try {
                LocalDate fechaActual = LocalDate.parse(fechaParam);
                this.fecha.setValue(fechaActual); // Establece la fecha en el DatePicker
            } catch (Exception e) {
                Notification.show("Error al establecer la fecha: " + e.getMessage(), 3000, Notification.Position.MIDDLE);
            }
        }

        // Cambiamos el valor por el ID
        if ("1".equals(tipoParam)) { // 1 es para PREVENTIVO
            TiposMantenimiento preventivo = tipoMantt.getDataProvider()
                    .fetch(new com.vaadin.flow.data.provider.Query<>())
                    .filter(tipo -> "1".equals(tipo.getTipomantId()))
                    .findFirst()
                    .orElse(null);

            if (preventivo != null) {
                tipoMantt.setValue(preventivo);
                tipoMantt.setReadOnly(true);
            }

        }  else if ("2".equals(tipoParam)) { // 2 es para CORRECTIVO
            TiposMantenimiento correctivo = tipoMantt.getDataProvider()
                    .fetch(new com.vaadin.flow.data.provider.Query<>())
                    .filter(tipo -> "2".equals(tipo.getTipomantId()))
                    .findFirst()
                    .orElse(null);

            if (correctivo != null) {
                tipoMantt.setValue(correctivo);
                tipoMantt.setReadOnly(true);
            }
        }

        // Establecemos el ID desde el plan anual
        if (idParam != null) {
            txtPlananualID.setValue(idParam); // Establece el ID en el campo de texto
        } else {
            txtPlananualID.setValue("Sin ID"); // O un valor por defecto si no hay ID
        }


        // Establecemos el valor del campo de texto Nombre de Equipo con el parametro que viene en la url
        if (equipoParam != null) {
            txtNombreEquipo.setValue(equipoParam);
        } else {
            txtNombreEquipo.setValue("Sin nombre");
        }


        // Establecemos el campo del departamento con el departamento desde el plan anual
        if (deptoParam != null) {
            Optional<DepartamentosModel> departamentoSeleccionado = area.getDataProvider()
                            .fetch(new com.vaadin.flow.data.provider.Query<>())
                                    .filter(departamento -> departamento.getNombre().equals(deptoParam))
                                            .findFirst();

            if (departamentoSeleccionado.isPresent()) {
                area.setValue(departamentoSeleccionado.get());
                area.setReadOnly(true);
            } else {
                area.setValue(null);
            }
        }

    }
}
