package mx.gob.jumapacelaya.ui;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.UI;
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.html.H1;
import com.vaadin.flow.component.html.H2;
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.orderedlayout.FlexComponent;
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.NumberField;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.button.Button;
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.services.DatabaseService;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;


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

    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 ComboBox<String> tipoMantt;
    private final ComboBox<String> area;
    private final ComboBox<String> usuario;
    private RadioButtonGroup<String> formaGroup;
    private CheckboxGroup<String> actualizaciones;
    private final HorizontalLayout botonesLayout;
    private TextArea txtCuales;
    private RadioButtonGroup<String> masActualizacionesGroup;


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


    public MantenimientoView() {
        this.databaseService = new DatabaseService();
        this.controlsLayout = new VerticalLayout();
        this.actualizacionesLayout = new VerticalLayout();
        this.etiquetaLayout = new VerticalLayout();
        this.firmasLayout = new HorizontalLayout();
        this.botonesLayout = new HorizontalLayout();

        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.setPlaceholder("Fecha");



        //ComboBox Tipo de Mantenimiento
        this.tipoMantt = new ComboBox<>("Tipo de Mantenimiento");
        tipoMantt.setItems(databaseService.getTiposDeMantenimientos());
        tipoMantt.addClassName("mantenimiento-combo");
        tipoMantt.addValueChangeListener(event -> {
            String tipoSeleccionado = event.getValue();
            if (tipoSeleccionado != null) {
                //Actualizar nomenclatura dependiendo al tipo de mantenimiento
                String nomenclaturaValue = databaseService.getNomenclatura(tipoSeleccionado);
                nomenclatura.setValue(nomenclaturaValue);

                //Si el tipo es preventivo se establecera la fecha automaticamente a la fecha del sistema
                if ("PREVENTIVO".equals(tipoSeleccionado)) {
                    this.fecha.setValue(LocalDate.now());
                    etiquetaLayout.setVisible(false);
                } else {
                    this.fecha.clear();
                    etiquetaLayout.setVisible(true);
                }
            } else {
                nomenclatura.clear();
                this.fecha.clear();
            }
        });
        fechaLayout.add(this.fecha);
        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");
        List<String> areas = databaseService.getDepartamentos();
        area.setItems(areas);

        this.usuario = new ComboBox<>("Usuario");
        usuario.setItems(databaseService.getUsuarios());
        usuario.addValueChangeListener(event -> {
            String usuarioSeleccionado = event.getValue();
            if (usuarioSeleccionado != null) {
                String nombreUsuario = databaseService.getNombreUsuario(usuarioSeleccionado);
                userSignSpan.setText(nombreUsuario);
            } else {
                userSignSpan.setText("S.M.T Nombre");
            }
        });

        departamentoLayout.add(area, usuario);
        departamentoLayout.setWidthFull();

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


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


    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<String> tipoHardware = new ComboBox<>();
        List<String> tiposHardware = databaseService.getTiposHardware();
        tipoHardware.setItems(tiposHardware);
        tipoHardware.setPlaceholder("Tipo de hardware");
        tipoHardware.setSizeFull();

        NumberField noSerie = new NumberField();
        noSerie.setEnabled(false);
        noSerie.setRequired(true);
        noSerie.setPlaceholder("No. Serie");
        noSerie.setSizeFull();

        TextField modelo = new TextField();
        modelo.setEnabled(false);
        modelo.setRequired(true);
        modelo.setPlaceholder("Modelo");
        modelo.setSizeFull();

        NumberField placa = new NumberField();
        placa.setEnabled(false);
        placa.setRequired(true);
        placa.setPlaceholder("Placa");
        placa.setSizeFull();

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

            if (tipoSeleccionado != null) {
                int tipoId = Integer.parseInt(tipoSeleccionado);
                if (tipoId == 6 || tipoId == 7) {
                    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);
            } 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);
    }


    private void correctivoLayout(){
        Span Titulo = new Span("Reparación Realizada al Equipo: ");


        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.setVisible(false);
        etiquetaLayout.add(Titulo, model, hard);

    }


    private void signLayout() {
        VerticalLayout userSignLayout = new VerticalLayout();
        SignaturePad userSignPad = new SignaturePad();
        userSignPad.setBackgroundColor(0, 0, 0, 0);
        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();
        SignaturePad smtSignPad = new SignaturePad();
        smtSignPad.setHeight("200px");
        smtSignPad.setBackgroundColor(0, 0, 0, 0);
        smtSignPad.setPenColor("#000000");
        smtSignPad.getElement().getStyle().set("border", "1px solid black");
        Span smtSignSpan = new Span("S.M.T. Nombre");
        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();
        SignaturePad gciatiSignPad = new SignaturePad();
        gciatiSignPad.setBackgroundColor(0, 0, 0, 0);
        gciatiSignPad.setHeight("200px");
        gciatiSignPad.setPenColor("#000000");
        gciatiSignPad.getElement().getStyle().set("border", "1px solid black");
        Span gciatiSignSpan = new Span("L.I. Sandra E. Rodriguez Ramirez");
        Span tituloGerente = new Span("Gerencia de Tecnologias de la Información");
        gcialSignLayout.setSizeFull();
        gcialSignLayout.setSpacing(false);
        gcialSignLayout.setAlignItems(Alignment.CENTER);
        gcialSignLayout.add(gciatiSignPad, gciatiSignSpan, tituloGerente);



        firmasLayout.add(userSignLayout, smtSignLayout, gcialSignLayout);
        firmasLayout.setSizeFull();
        firmasLayout.setSpacing(false);
    }


    private void buttons() {
        HorizontalLayout buttonsLayout = new HorizontalLayout();
        Button btnGuardar = new Button("Guardar");
        btnGuardar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);

        btnGuardar.addClickListener(event -> {
            LocalDate fechaSeleccionada = fecha.getValue();
            String tipoMantId = tipoMantt.getValue();
            String departamentoId = area.getValue();
            String empleadoId = usuario.getValue();


            // AQUI SE MANEJA LA OPCION SELECIONADA EN LA FORMA DE MANTENIMIENTO (REMOTA o MANUAL)
            String formaSeleccionada = formaGroup.getValue();
            String formaMantt = null;

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


            // VALIDACION PARA QUE TODOS LOS CAMPOS OBLIGATORIOS SEAN LLENADOS
            if (fechaSeleccionada == null || tipoMantId == null || departamentoId == null || empleadoId == null || formaMantt == null) {
                Notification.show("Por favor, completa todos los campos requeridos", 4000, Notification.Position.MIDDLE);
                return;
            }

            int isInserted = databaseService.insertarMantenimiento(fechaSeleccionada, tipoMantId, departamentoId, empleadoId, formaMantt);

            // AQUI SE MANEJA LA INSERCION DE LOS DETALLES DE HARDWARE (TIPO DE HARDWARE, NO. DE SERIE, MODELO, PLACA)
            if (isInserted > 0) {

                int mantenimientoId = databaseService.getUltimoMantenimientoId();

                for (HorizontalLayout layout : hardwareLayouts) {
                    ComboBox<String> tipoHardware = (ComboBox<String>) layout.getComponentAt(0);
                    NumberField noSerie = (NumberField) layout.getComponentAt(1);
                    TextField modelo = (TextField) layout.getComponentAt(2);
                    NumberField placa = (NumberField) layout.getComponentAt(3);

                    int numSerieInt = noSerie.getValue() != null ? noSerie.getValue().intValue() : 0;
                    int placaInt = placa.getValue() != null ? placa.getValue().intValue() : 0;

                    // Validaciones antes de insertar detalles del hardware
                    if (tipoHardware.getValue() == null || modelo.getValue() == null || numSerieInt <= 0 || placaInt <= 0) {
                        Notification.show("Por favor, completa todos los campos de hardware", 4000, Notification.Position.MIDDLE);
                        return;
                    }

                    boolean isHardwareInserted = databaseService.insertarHardware(
                            tipoHardware.getValue(),
                            numSerieInt,
                            modelo.getValue(),
                            placaInt,
                            mantenimientoId
                    );
                    tipoHardware.clear();
                    modelo.clear();
                    placa.clear();
                    noSerie.clear();

                    if (!isHardwareInserted) {
                        Notification.show("Error al insertar detalles del hardware", 4000, Notification.Position.MIDDLE);
                        return;
                    }
                }


                // AQUI MANEJO LA INSERCION DE LOS DATOS DE LOS CHECKBOXES DE ACTUALIZACIONES DE SEGURIDAD!!!
                for (String actualizacionSelecionada : actualizaciones.getSelectedItems()) {
                    boolean isActualizacionInserted = databaseService.insertActualizacionSeg(actualizacionSelecionada, null, mantenimientoId);

                    if (!isActualizacionInserted) {
                        Notification.show("Error al insertar actualizacion de seguridad", 4000, Notification.Position.MIDDLE);
                        return;
                    }
                }

                if (masActualizacionesGroup.getValue().equals("Si")) {
                    String otrasActu = txtCuales.getValue();
                    String actualizacion = "Otras";
                    if (otrasActu != null && !otrasActu.trim().isEmpty()){
                        boolean isOtrasActualizaciones = databaseService.insertActualizacionSeg(actualizacion, otrasActu, mantenimientoId);

                        if (!isOtrasActualizaciones) {
                            Notification.show("Error al insertar otras actualizaciones de seguridad", 4000, Notification.Position.MIDDLE);
                            return;
                        }
                    }
                }


                // NOTIFICACION DE GUARDADO EXITOSO Y LIMPIEZA DE LOS CAMPOS!!!
                Notification.show("!!Mantenimiento guardado exitosamente!!", 4000, Notification.Position.MIDDLE);
                fecha.clear();
                tipoMantt.clear();
                area.clear();
                usuario.clear();
                formaGroup.clear();
                actualizaciones.clear();
                masActualizacionesGroup.clear();
                txtCuales.clear();
            } else {
                Notification.show("Error al guardar el mantenimeinto", 4000, Notification.Position.MIDDLE);
            }
        });

        buttonsLayout.setSizeFull();
        buttonsLayout.add(btnGuardar);
        botonesLayout.add(buttonsLayout);
    }


    @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("tipo").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);
            }
        }

        if ("PREVENTIVO".equalsIgnoreCase(tipoParam)) {
            tipoMantt.setValue("PREVENTIVO");
            tipoMantt.setReadOnly(true);
        }
    }
}
