Imports System.Collections.Specialized
Imports System.ComponentModel
Imports System.IO
Imports System.Net
Imports System.Text
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Web.Script.Serialization

Public Class FrmMenuPrincipal

    Public conexionLocalOk As Boolean = False
    Public conexionMaestraOk As Boolean = False
    Dim cancellationTokenSource As New CancellationTokenSource()
    Dim cancellationToken As CancellationToken
    Public Event Notificaciones_evento(mensaje As String)

    Dim ultimoRegistro As New UltimoIngreso()

    Public Sub New()
        InitializeComponent()
        cancellationToken = cancellationTokenSource.Token
    End Sub

    Private Sub FrmMenuPrincipal_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        IniciarTareas()

        If Conexion.ValidarConexion(conexionLocal) Then
            UpdateEnrollUsersData()
        Else
            MsgBox("Conexión local invalida, sin usar el capta huella por favor ingrese cadena de conexión local en parámetros.")
            actualizarBdMaestra = False
        End If

        BackgroundWorker1.RunWorkerAsync()

    End Sub

    Private Sub BtnCategoria_Click(sender As Object, e As EventArgs) Handles BtnEntrada.Click,
                                                                             BtnSalida.Click

        If TypeOf sender IsNot DevComponents.DotNetBar.ButtonX Then Exit Sub

        Dim btn As DevComponents.DotNetBar.ButtonX = TryCast(sender, DevComponents.DotNetBar.ButtonX)
        barraBtnEntrada.Visible = btn.Name.Equals(BtnEntrada.Name)
        'barraBtnSalidaInter.Visible = btn.Name.Equals(BtnSalidaInter.Name)
        'barraBtnEntradaInter.Visible = btn.Name.Equals(BtnEntradaInter.Name)
        barraBtnSalida.Visible = btn.Name.Equals(BtnSalida.Name)
        LblAyuda.Select()
    End Sub

    Friend Sub AbrirFrmParametros()
        Dim frm0 As New FrmParametros(Me)
        For Each frm1 As Form In Application.OpenForms
            If frm1.Name = frm0.Name Then
                frm1.Show()
                frm1.Activate()
                Dim screenSize As Size = Screen.PrimaryScreen.WorkingArea.Size
                frm1.Location = New Point(screenSize.Width / 2 - frm1.Width / 2, screenSize.Height / 2 - frm1.Height / 2)
                Exit Sub
            End If
        Next

        frm0.Show()
        frm0.Activate()
    End Sub

    Protected Overrides Sub Finalize()
        cancellationTokenSource.Cancel()
        MyBase.Finalize()
    End Sub

    Sub OnComplete(ByVal Control As Object, ByVal FeatureSet As DPFP.FeatureSet, ByRef EventHandlerStatus As DPFP.Gui.EventHandlerStatus) Handles VerificationControl.OnComplete
        If IsNothing(EnrollUsersData) Then EventHandlerStatus = DPFP.Gui.EventHandlerStatus.Failure : Exit Sub
        Beep()
        Dim ver As New DPFP.Verification.Verification()
        Dim res As New DPFP.Verification.Verification.Result()

        Dim founded As Boolean = False
        For Each user As DeviceUserData In EnrollUsersData
            For Each template As DPFP.Template In user.Templates    '   Compare feature set with all stored templates:
                If Not template Is Nothing Then                     '   Get template from storage.
                    ver.Verify(FeatureSet, template, res)           '   Compare feature set with particular template.
                    user.IsFeatureSetMatched = res.Verified         '   Check the result of the comparison
                    user.FalseAcceptRate = res.FARAchieved          '   Determine the current False Accept Rate
                    If res.Verified Then
                        If ultimoRegistro.IdUsuario <> user.IdUser OrElse TipoMovimiento() <> ultimoRegistro.TipoMovimiento Then
                            contadorImagen = 0 : PBImagen.Image = My.Resources.huellaBien
                            EventHandlerStatus = DPFP.Gui.EventHandlerStatus.Success

                            ' ToDo: Realizar el registro del usuario aquí ↓                     
                            Registrar(user.IdUser, TipoAutenticacion.HUELLA, TipoMovimiento())
                            NotificarUltimoRegistro()
                            founded = True
                            Exit For ' success
                        Else
                            EventHandlerStatus = DPFP.Gui.EventHandlerStatus.Failure
                            contadorImagen = 0 : PBImagen.Image = My.Resources.huellaMala
                            NotificarUltimoRegistro(True)
                            founded = True
                            Exit For ' success
                        End If

                        user.Update()
                    End If
                End If
            Next
            If founded = True Then Exit For
        Next

        If Not res.Verified Then
            EventHandlerStatus = DPFP.Gui.EventHandlerStatus.Failure
            contadorImagen = 0 : PBImagen.Image = My.Resources.huellaMala
        End If
    End Sub

    Private Sub NotificarUltimoRegistro(Optional ByVal repetido As Boolean = False)
        Try
            Dim conexion As New Conexion(conexionLocal)
            Dim registros As New ClsRegistrosListar(conexion)
            Dim dataTable = registros.Listar(Nothing)

            If Not IsNothing(dataTable) AndAlso dataTable.Rows.Count > 0 Then
                Dim dataRow = dataTable.Rows(0)

                If repetido = False Then
                    lblUltimoRegistro.Text = $"ÚLTIMO REGISTRO: {dataRow("nombreUsuario")} {dataRow("apellidoUsuario").ToString().Replace("N/A", "")} - {dataRow("descripcionTipoMovimiento")} -> {dataRow("fechaRegistro")}"
                    lblUltimoRegistro.BackColor = System.Drawing.Color.FromArgb(255, 101, 221, 185)
                    lblUltimoRegistro.ForeColor = Color.White
                Else
                    If Not lblUltimoRegistro.Text.StartsWith("REGISTRO YA INGRESADO ->") Then lblUltimoRegistro.Text = "REGISTRO YA INGRESADO ->" + lblUltimoRegistro.Text
                    lblUltimoRegistro.BackColor = Color.Red
                    lblUltimoRegistro.ForeColor = Color.White
                End If

                ultimoRegistro.IdUsuario = dataRow("idUsuario")
                ultimoRegistro.TipoMovimiento = dataRow("idTipoMovimiento")
            End If
        Catch ex As Exception
            Console.WriteLine(ex.Message)
        End Try
    End Sub

    Private Function EnviarEmail(idUsuario As Integer, tipoAutenticacion As TipoAutenticacion, tipoMovimiento As TipoMovimiento, registro As Date) As Boolean
        Dim result As Boolean
        Try
            Dim connexion As New Conexion(conexionLocal)
            Dim sql = $"SELECT 
U.nombre, 
U.apellidos, 
U.mailPersonal,
U.mailCorporativo,
U.idEmpresa,
E.idContrato
FROM Usuarios U
LEFT OUTER JOIN Empresas E ON U.idEmpresa = E.id  
WHERE U.id = {idUsuario}"

            Dim datatable = connexion.ObtenerDataTable(sql, New List(Of SqlClient.SqlParameter))

            If datatable.Rows(0).Item("mailPersonal") <> "" And datatable.Rows(0).Item("mailCorporativo") <> "" Then
                Dim requestData As New Dictionary(Of String, Object)()
                requestData.Add("IdContrato", datatable.Rows(0).Item("idContrato").ToString())
                requestData.Add("IdEmpresa", datatable.Rows(0).Item("idEmpresa").ToString())
                requestData.Add("Nombre", datatable.Rows(0).Item("nombre").ToString())
                requestData.Add("Apellido", datatable.Rows(0).Item("apellidos").ToString())
                requestData.Add("MailParticular", datatable.Rows(0).Item("mailPersonal").ToString())
                requestData.Add("MailEmpresa", datatable.Rows(0).Item("mailCorporativo").ToString())
                requestData.Add("Tipo", tipoMovimiento.ToString())
                requestData.Add("Registro", registro.ToString("dd-MM-yyyy HH:mm"))
                requestData.Add("Dispositivo", "RELOJ CONTROL")
                requestData.Add("Autenticacion", tipoAutenticacion.ToString())
                requestData.Add("Lugar", "NO APLICA")

                Dim jsonSerializer As New JavaScriptSerializer()
                Dim requestDataJson As String = jsonSerializer.Serialize(requestData)

                Dim jwtToken As String = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJvYnVzIiwic3ViIjoiMSIsInN1Yl9uYW1lIjoicHJpeHVzX2FkbWluIiwiZXhwIjoxNzA4NzQxMjA3LCJhdWQiOlsiaHR0cHM6Ly9hcGkxLnByaXh1c2VycC5jbC8iLCJodHRwczovL2ZhY3R1cmEucHJpeHVzZXJwLmNsLyIsImh0dHBzOi8vYXBpMi5wcml4dXNlcnAuY2wiLCJodHRwczovL2FwaTMucHJpeHVzZXJwLmNsIiwiaHR0cHM6Ly9hcGk0LnByaXh1c2VycC5jbCIsImh0dHBzOi8vYXBpNS5wcml4dXNlcnAuY2wiLCJodHRwczovL2FwaTYucHJpeHVzZXJwLmNsIiwiaHR0cHM6Ly9hcGk3LnByaXh1c2VycC5jbCJdLCJzY29wZSI6WyJhbGwiXSwiaWR1c3IiOjEyNywidHVzciI6IkNOVEUiLCJjbnR1c3IiOltdLCJlbXB1c3IiOlt7ImlkZW1wIjoxLCJubGVnIjoiNzYzNzc5MTAiLCJybGVnIjp0cnVlLCJpZGNudCI6MTAwMCwibW9kcyI6W3sibW9kIjoiVkVOIiwicGVyZiI6IjF8QURNfDEiLCJhY3QiOnRydWV9LHsibW9kIjoiSU5WIiwicGVyZiI6IjF8QURNfDEiLCJhY3QiOnRydWV9LHsibW9kIjoiRklOIiwicGVyZiI6IjF8QURNfDEiLCJhY3QiOnRydWV9LHsibW9kIjoiUFJPIiwicGVyZiI6IjF8QURNfDEiLCJhY3QiOnRydWV9LHsibW9kIjoiUkVNIiwicGVyZiI6IjF8QURNfDEiLCJhY3QiOnRydWV9LHsibW9kIjoiQ09OIiwicGVyZiI6IjF8QURNfDEiLCJhY3QiOnRydWV9LHsibW9kIjoiUklOIiwicGVyZiI6IjF8QURNfDEiLCJhY3QiOnRydWV9LHsibW9kIjoiVE9NQSIsInBlcmYiOiIxfEFETXwxIiwiYWN0Ijp0cnVlfV19XX0.mhcHGRIZYDWEYShCdXeUksxzO1p-DAzIT7vrQiEhua6LpBtnMJ6ZNj0CPzzdOALO-1oBCH148TGPvs1D4xJ0CQ"

                Dim request As HttpWebRequest = DirectCast(WebRequest.Create("https://api4.prixuserp.cl/prixus/relojcontrol/email/enviarregistro"), HttpWebRequest)
                request.Method = "POST"
                request.ContentType = "application/json"
                request.Headers.Add("Authorization", "Bearer " & jwtToken)

                Using requestStream As Stream = request.GetRequestStream()
                    Dim requestDataBytes As Byte() = Encoding.UTF8.GetBytes(requestDataJson)
                    requestStream.Write(requestDataBytes, 0, requestDataBytes.Length)
                End Using

                Try
                    Using response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
                        Using responseStream As Stream = response.GetResponseStream()
                            If responseStream IsNot Nothing Then
                                Using reader As New StreamReader(responseStream)
                                    Dim responseString As String = reader.ReadToEnd()

                                    ' Validar el código de estado HTTP
                                    Dim statusCode As HttpStatusCode = response.StatusCode
                                    If statusCode = HttpStatusCode.OK Then
                                        result = True
                                    Else
                                        result = False
                                    End If
                                End Using
                            End If
                        End Using
                    End Using
                Catch ex As WebException
                    If ex.Response IsNot Nothing Then
                        Dim response As HttpWebResponse = DirectCast(ex.Response, HttpWebResponse)
                        result = False
                    End If
                End Try
            Else
                result = False
            End If

        Catch ex As Exception
            result = False
            MsgBox(ex.Message)
        End Try

        Return result
    End Function

    Private Sub Registrar(idUser As Integer, tipoAutenticacion As TipoAutenticacion, tipoMovimiento As TipoMovimiento)
        Try
            Dim conexion As New Conexion(conexionLocal)
            Dim registro As New ClsRegistrosCrear(conexion)

            Dim argumentos As New RegistrosCrearArgumentos With {
        .IdUsuario = idUser,
        .Autenticacion = tipoAutenticacion,
        .TipoMovimiento = tipoMovimiento,
        .Export = False,
        .FechaExport = Nothing,
        .FechaRegistro = DateTime.Now,
        .Email = False,
        .FechaEmail = Nothing
        }
            registro.Crear(argumentos)

            If EnviarEmail(idUser, tipoAutenticacion, tipoMovimiento, argumentos.FechaRegistro) Then
                Dim idRegistro = ObtenerIdRegistro()
                If idRegistro > 0 Then
                    If Not ActualizarEstadoEmail(True, argumentos.FechaRegistro, idRegistro) Then
                        MessageBox.Show("Error al actualizar envío de email en la BBDD.")
                    End If
                End If
            End If
        Catch ex As Exception
            MessageBox.Show("Error al realizar el registro. Por favor, comunique al admininstrador.")
        End Try
    End Sub

    Private Function ObtenerIdRegistro() As Integer
        Dim connexion As New Conexion(conexionLocal)
        Dim sql As String = "SELECT ISNULL(MAX(id), 0) AS id FROM Registros"

        Dim idRegistro As Integer = connexion.ObtenerValor(sql)

        Return idRegistro
    End Function

    Private Function ActualizarEstadoEmail(email As Boolean, fechaEmail As Date, idRegistro As Integer) As Boolean
        Dim result As Boolean = False
        Try
            Dim connexion As New Conexion(conexionLocal)
            Dim sql As String = $"UPDATE Registros SET email = '{email}', fechaEmail = '{fechaEmail}' WHERE id = {idRegistro}"

            If connexion.EjecutarSQL(sql) Then
                result = True
            Else
                result = False
            End If

        Catch ex As Exception
            result = False
        End Try

        Return result
    End Function

    Private Function TipoMovimiento() As TipoMovimiento
        Dim resultado As TipoMovimiento = TipoMovimiento.ENTRADA
        Select Case True
            Case barraBtnEntrada.Visible
                resultado = TipoMovimiento.ENTRADA
            'Case barraBtnEntradaInter.Visible
            '    resultado = TipoMovimiento.ENTRADA_INTERMEDIA_1
            Case barraBtnSalida.Visible
                resultado = TipoMovimiento.SALIDA
                'Case barraBtnSalidaInter.Visible
                '    resultado = TipoMovimiento.SALIDA_INTERMEDIA_1
        End Select

        Return resultado
    End Function

    'Tareas:
#Region "TAREAS"

    Public Sub IniciarTareas()
        RefreshTimeTask.Start()
        RevisarConexionLocal.Start()
        RevisarConexionMaestra.Start()
    End Sub

    Dim contadorImagen As Integer = -1

    Dim RefreshTimeTask As New Task(Sub()
                                        Try
                                            While Not cancellationToken.IsCancellationRequested
                                                Me.Invoke(Sub()
                                                              LblHora.Text = Now.ToString("HH:mm tt")
                                                              LblFecha.Text = Now.ToString("dddd, dd-MM-yyyy").UpperCaseFirstChar
                                                          End Sub)
                                                If contadorImagen >= 0 Then
                                                    contadorImagen += 1
                                                    If contadorImagen >= 3 Then
                                                        contadorImagen = -1
                                                        Me.Invoke(Sub()
                                                                      If Not IsNothing(PBImagen) Then PBImagen.Image = My.Resources.huella
                                                                  End Sub)
                                                    End If
                                                End If
                                                Thread.Sleep(1000)
                                            End While
                                        Catch ex As Exception
                                            Console.WriteLine("RefreshTimeTask(100): " + ex.Message)
                                        End Try
                                    End Sub, cancellationToken)

    Dim RevisarConexionLocal As New Task(Sub()
                                             While Not cancellationToken.IsCancellationRequested
                                                 Try
                                                     conexionLocalOk = Conexion.ValidarConexion(conexionLocal)
                                                     If conexionLocalOk Then
                                                         Me.Invoke(Sub()
                                                                       If Not IsNothing(PictureBoxCnxLocal) Then PictureBoxCnxLocal.Image = My.Resources.circuloAzul24
                                                                   End Sub)
                                                     Else
                                                         Me.Invoke(Sub()
                                                                       If Not IsNothing(PictureBoxCnxLocal) Then PictureBoxCnxLocal.Image = My.Resources.circuloRojo24
                                                                   End Sub)
                                                     End If
                                                 Catch ex As Exception
                                                 End Try
                                                 Thread.Sleep(3000)
                                             End While
                                         End Sub, cancellationToken)

    Dim RevisarConexionMaestra As New Task(Sub()
                                               While Not cancellationToken.IsCancellationRequested
                                                   Try
                                                       conexionMaestraOk = Conexion.ValidarConexion(conexionMaestra)
                                                       If conexionMaestraOk Then
                                                           Me.Invoke(Sub()
                                                                         If Not IsNothing(PictureBoxCnxMaestra) Then PictureBoxCnxMaestra.Image = My.Resources.circuloAzul24
                                                                     End Sub)
                                                       Else
                                                           Me.Invoke(Sub()
                                                                         If Not IsNothing(PictureBoxCnxMaestra) Then PictureBoxCnxMaestra.Image = My.Resources.circuloRojo24
                                                                     End Sub)
                                                       End If
                                                   Catch ex As Exception
                                                   End Try
                                                   Thread.Sleep(3000)
                                               End While
                                           End Sub, cancellationToken)
#End Region



    Private Sub BtnIngresoMenuSecundario_Click(sender As Object, e As EventArgs) Handles BtnIngresoMenuSecundario.Click
        Dim frm0 As New FrmClaveAdmin(Me)
        For Each frm1 As Form In Application.OpenForms
            If frm1.Name = frm0.Name Then
                frm1.Show()
                frm1.Activate()
                Dim screenSize As Size = Screen.PrimaryScreen.WorkingArea.Size
                frm1.Location = New Point(screenSize.Width / 2 - frm1.Width / 2, screenSize.Height / 2 - frm1.Height / 2)
                Exit Sub
            End If
        Next

        frm0.Show()
        frm0.Activate()
    End Sub

    Friend Sub AbrirMenuSecundario()
        VerificationControl.Active = False
        Dim frm0 As New FrmMenuSecundario(Me)
        For Each frm1 As Form In Application.OpenForms
            If frm1.Name = frm0.Name Then
                frm1.Show()
                frm1.Activate()
                frm1.WindowState = FormWindowState.Maximized
                Exit Sub
            End If
        Next

        frm0.Show()
        frm0.Activate()
        frm0.WindowState = FormWindowState.Maximized
    End Sub
    Friend Sub AbrirFrmUsuarios()
        VerificationControl.Active = False

        Dim frm0 As New FrmUsuariosListar()
        For Each frm1 As Form In Application.OpenForms
            If frm1.Name = frm0.Name Then
                frm1.Show()
                frm1.Activate()
                frm1.WindowState = FormWindowState.Maximized
                Exit Sub
            End If
        Next

        frm0.Show()
        frm0.Activate()
        frm0.WindowState = FormWindowState.Maximized
    End Sub

    Friend Sub AbrirFrmRegistros()
        VerificationControl.Active = False

        Dim frm0 As New FrmRegistrosListar()
        For Each frm1 As Form In Application.OpenForms
            If frm1.Name = frm0.Name Then
                frm1.Show()
                frm1.Activate()
                frm1.WindowState = FormWindowState.Maximized
                Exit Sub
            End If
        Next

        frm0.Show()
        frm0.Activate()
        frm0.WindowState = FormWindowState.Maximized
    End Sub

    Private Sub FrmMenuPrincipal_Activated(sender As Object, e As EventArgs) Handles MyBase.Activated
        Dim formularios0 As New List(Of String) From {FrmUsuariosListar.Name, "FrmMenuSecundario", "FrmClaveAdmin", "FrmParametros", FrmRegistrosListar.Name}

        Dim formularios1 As New List(Of Form)

        For Each elemento As Form In Application.OpenForms
            If formularios0.Contains(elemento.Name) Then
                formularios1.Add(elemento)
            End If
        Next

        formularios1.ForEach(Sub(x) x.Close())
        VerificationControl.Active = True
    End Sub

    Private Sub FrmMenuPrincipal_Deactivate(sender As Object, e As EventArgs) Handles Me.Deactivate
        VerificationControl.Active = False
    End Sub

    Private Sub LinkMarcarClave_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkMarcarClave.LinkClicked
        Dim credenciales = New FrmLogin().ShowDialog
        Dim conexion As New Conexion(conexionLocal)
        Dim autenticador As New ClsUsuariosAutenticar(conexion)

        If Not (credenciales.DatosOk AndAlso autenticador.Autenticar(credenciales)) Then GoTo [ERROR]

        Dim idUsuario = New ClsUsuariosObtenerId(conexion).ObtenerIdUsuario(credenciales.Usuario)

        If Not (Not IsNothing(idUsuario) AndAlso IsNumeric(idUsuario)) Then GoTo [ERROR]

        contadorImagen = 0 : PBImagen.Image = My.Resources.huellaBien

        Registrar(idUsuario, TipoAutenticacion.CONTRASEÑA, TipoMovimiento())
        NotificarUltimoRegistro()
        Exit Sub

[ERROR]:
        Beep() : contadorImagen = 0 : PBImagen.Image = My.Resources.huellaMala
    End Sub

    Dim CloseWorker As Boolean = False

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        While (Not CloseWorker)


            If actualizarBdMaestra = True Then
                Try
                    If conexionMaestraOk = False Then Throw New Exception("Transferencia de datos interrumpida antes de consultar fecha en BD maestra por error en conexión.")

                    Dim MaestraDataSource = My.Settings.ConexionMaestraDataSource
                    Dim MaestraInitialCatalog As String = ""
                    Dim MaestraUser = My.Settings.ConexionMaestraUsuario
                    Dim MaestraPass = My.Settings.ConexionMaestraPassword

                    Dim conexionEmpresaOk As Boolean = False
                    Dim localConexion As New Conexion(conexionLocal)
                    '
                    'Obtener Empresas de BD Local
                    Dim dbEmpresasListar As New ActualizadorEmpresaListar(localConexion)

                    Dim dtEmpresas = dbEmpresasListar.LeerEmpresa()
                    '
                    ' Validar respuesta.
                    If IsNothing(dtEmpresas) Then Throw New Exception("Respuesta base datos local Empresas igual a nothing.")
                    If dtEmpresas.Rows.Count < 1 Then Throw New Exception("Respuesta base datos local sin Empresas.")

                    For Each emp As DataRow In dtEmpresas.Rows
                        Dim conexionEmpresa As String = CrearCadenaConexion(MaestraDataSource, $"PRIXUS_{emp.Item("numeroLegal")}", MaestraUser, MaestraPass)

                        conexionEmpresaOk = Conexion.ValidarConexion(conexionEmpresa)

                        RaiseEvent Notificaciones_evento($" 
Comenzando transferencia de datos a BD Maestra.
CnxBdLocal: {conexionLocal}{vbNewLine}
CnxBdMaestra: {conexionEmpresa}") '<===== RAISE EVENT
                        '
                        ' Consultar ultima fecha de registro.
                        Dim dbMaestraUltimoRegisro As New ActualizadorDestinoUltimoRegistro

                        If conexionEmpresaOk = False Then Throw New Exception("Transferencia de datos interrumpida antes de consultar fecha en BD Empresa por error en conexión.")

                        RaiseEvent Notificaciones_evento("Consultando fecha de ultimo registro en BdMaestra.") '<===== RAISE EVENT
                        Dim maestraUltimoRegistro = dbMaestraUltimoRegisro.UltimoRegistro(conexionEmpresa)
                        '
                        ' Validar respuesta.
                        RaiseEvent Notificaciones_evento($"Validando resultado de ultima fecha. {maestraUltimoRegistro}.") '<===== RAISE EVENT
                        If IsNothing(maestraUltimoRegistro) Then Throw New Exception("Resultado de consulta fecha BD maestra ultimo registro igual a nothing.")

                        If Not IsDate(maestraUltimoRegistro) Then Throw New Exception("Resultado de consulta fecha BD maestra ultimo registro no es tipo fecha.")

                        If maestraUltimoRegistro.ToString.Equals("01-01-1900 00:00:00") Then Throw New Exception("Resultado de consulta fecha BD igual a 01-01-1900 00:00:00")
                        '
                        ' Marcar y leer datos a insertar en BD Maestra.
                        RaiseEvent Notificaciones_evento($"Consultado y marcando datos inferiores o igual a {maestraUltimoRegistro}.") '<===== RAISE EVENT
                        Dim conn As New Conexion(conexionLocal)
                        Dim dbLocalRegistros As New ActualizadorRegistrosMarcarYLeer(conn)

                        Dim localRegistros = dbLocalRegistros.MarcarYLeer(maestraUltimoRegistro)
                        '
                        ' Validar respuesta.
                        If IsNothing(localRegistros) Then Throw New Exception("Respuesta base datos local registros a insertar igual a nothing.")
                        If localRegistros.Rows.Count < 1 Then Throw New Exception("Respuesta base datos local sin registros nuevos a insertar.")
                        '
                        ' Cambiar nombre de la tabla y forzar tipo en la columna fecha.
                        localRegistros.TableName = "Registros"
                        localRegistros.Columns("fechaRegistro").DateTimeMode = DataSetDateTime.Unspecified
                        '
                        ' Convertir DataTable a XML.
                        Dim xmlString As String
                        Using ms As New MemoryStream
                            localRegistros.WriteXml(ms)
                            ms.Position = 0
                            xmlString = New StreamReader(ms).ReadToEnd()
                        End Using
                        '
                        ' Validar XML.
                        If IsNothing(xmlString) Then Throw New Exception("XML a insertar en BD maestra igual a nothing.")
                        RaiseEvent Notificaciones_evento($"XML a insertar => {vbNewLine}{xmlString}") '<===== RAISE EVENT

                        Dim bdMaestraInsertardor As New ActualizadorDestinoInsertarRegistros()

                        Dim resultadoInsersionDatos = bdMaestraInsertardor.InsertarRegistros(conexionEmpresa, xmlString)

                        If Not resultadoInsersionDatos Then Throw New Exception("Error al insertar los datos en base de datos maestra.")

                        RaiseEvent Notificaciones_evento($"Se han insertado los datos en BD maestra correctamente")
                    Next

                Catch ex As Exception
                    RaiseEvent Notificaciones_evento($"Error. {ex.Message}.")
                End Try
            End If

            Dim connexion As New Conexion(conexionLocal)

            Dim sql As String = $"SELECT idUsuario, autenticacion, tipoMovimiento, fechaRegistro FROM Registros WHERE email = 'False' AND DAY(GETDATE()) = DAY(fechaRegistro) AND MONTH(GETDATE()) = MONTH(fechaRegistro) AND YEAR(GETDATE()) = YEAR(fechaRegistro)"

            Dim dataTable = connexion.ObtenerDataTable(sql, New List(Of SqlClient.SqlParameter))
            If dataTable.Rows.Count > 0 Then
                For Each row As DataRow In dataTable.Rows
                    Dim idUsuario As Integer = CInt(row.Item("idUsuario"))
                    Dim autenticacion As TipoAutenticacion = CInt(row.Item("autenticacion"))
                    Dim tipoMovimiento As TipoMovimiento = CInt(row.Item("tipoMovimiento"))
                    Dim fechaRegistro As Date = CDate(row.Item("fechaRegistro"))
                    If EnviarEmail(idUsuario, autenticacion, tipoMovimiento, fechaRegistro) Then
                        Dim idRegistro = ObtenerIdRegistro()
                        If idRegistro > 0 Then
                            ActualizarEstadoEmail(True, fechaRegistro, idRegistro)
                        End If
                    End If
                Next
            End If

            Thread.Sleep(tiempoEspera)
        End While
    End Sub

    Private Function ConexionTest() As Boolean
        Try
            Dim request As HttpWebRequest = DirectCast(WebRequest.Create("http://www.google.com"), HttpWebRequest)
            request.Timeout = 5000  ' Establece un tiempo de espera para la solicitud

            Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)

            If response.StatusCode = HttpStatusCode.OK Then
                response.Close()
                Return True
            Else
                response.Close()
                Return False
            End If
        Catch ex As WebException
            Return False
        End Try
    End Function

    Private Sub FrmMenuPrincipal_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        CloseWorker = True
        cancellationTokenSource.Cancel()
    End Sub
End Class