{"id":"9v6zvp6MPK","url":"https://pastebin.ca/9v6zvp6MPK","raw_url":"https://raw.anybin.ca/9v6zvp6MPK","visibility":"public","access":"public","created_at":1790725981816,"expires_at":1791330781816,"fetch_limit":null,"fetches_used":0,"reads_remaining":null,"size_bytes":34766,"syntax_hint":null,"title":null,"filename":null,"change_note":null,"cipher":null,"cipher_meta":null,"parent_id":null,"root_id":"9v6zvp6MPK","version":1,"owner_id":null,"recipient_id":null,"body":"Imports System.Data.SQLite\n\nPublic Class Form1\n\n    ' Contador global de IDs\n    Private ultimoId As Integer = 0\n    Private Sub LimpiarCampos()\n        TxtArea.Text = \"\"\n        TxtCantidad.Text = \"\"\n        MaskInicio.Text = \"\"\n        LabelVencimiento.Text = \"\"\n    End Sub\n    Private Sub AplicarTemaOscuro()\n        For Each fila As DataGridViewRow In dgvCalendario.Rows\n            fila.DefaultCellStyle.BackColor = Color.Black\n            fila.DefaultCellStyle.ForeColor = Color.White\n        Next\n\n        ' Opcional: también puedes aplicar a los encabezados\n        dgvCalendario.ColumnHeadersDefaultCellStyle.BackColor = Color.Black\n        dgvCalendario.ColumnHeadersDefaultCellStyle.ForeColor = Color.White\n    End Sub\n\n    Private Function MostrarMensaje(texto As String) As DialogResult\n        Dim frm As New Form2()\n        frm.LabelMensaje.Text = texto\n        frm.BtnCancelar.Visible = False ' Para avisos simples\n        Return frm.ShowDialog()\n    End Function\n    Private Sub MaskInicio_Leave(sender As Object, e As EventArgs) Handles MaskInicio.Leave\n        Dim fechaInicio As Date\n\n        If DateTime.TryParseExact(MaskInicio.Text,\n                              \"dd-MM-yyyy\",\n                              Globalization.CultureInfo.InvariantCulture,\n                              Globalization.DateTimeStyles.None,\n                              fechaInicio) Then\n\n            ' Calculamos vencimiento: +1 año\n            Dim fechaVencimiento As Date = fechaInicio.AddYears(1)\n\n            ' Mostramos en el Label\n            LabelVencimiento.Text = fechaVencimiento.ToString(\"dd-MM-yyyy\")\n        Else\n            LabelVencimiento.Text = \"\"\n        End If\n    End Sub\n    Private Function MostrarMensaje(texto As String, Optional esConfirmacion As Boolean = False) As DialogResult\n        Dim frm As New Form2()\n        frm.LabelMensaje.Text = texto\n\n        If esConfirmacion Then\n            ' Mostrar con botones Aceptar/Cancelar\n            Return frm.ShowDialog()\n        Else\n            ' Solo mostrar aviso con botón Aceptar\n            frm.BtnCancelar.Visible = False\n            Return frm.ShowDialog()\n        End If\n    End Function\n    Private Function CalcularEstado(fechaVenc As Date) As String\n        Dim diasRestantes As Integer = (fechaVenc.Date - Date.Today).Days\n        If diasRestantes <= 0 Then\n            Return \"Vencido\"\n        ElseIf diasRestantes <= 14 Then\n            Return \"Próximo a vencer\"\n        ElseIf diasRestantes <= 21 Then\n            Return \"Próximo a vencer\"\n        Else\n            Return \"Vigente\"\n        End If\n    End Function\n\n    Private Sub ActualizarEstados()\n        For Each fila As DataGridViewRow In dgvCalendario.Rows\n            If fila.Cells(\"FechaVencimiento\").Value IsNot Nothing Then\n                Dim fv As Date\n                If Date.TryParse(fila.Cells(\"FechaVencimiento\").Value.ToString(), fv) Then\n                    fila.Cells(\"Estado\").Value = CalcularEstado(fv)\n                End If\n            End If\n        Next\n    End Sub\n    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load\n        Me.KeyPreview = True\n\n        ' Cargar meses en el ComboBox\n        CmbMeses.Items.Clear()\n        CmbMeses.Items.Add(\"Seleccionar un Mes\")\n        CmbMeses.Items.AddRange(New String() {\n        \"01 - Enero\", \"02 - Febrero\", \"03 - Marzo\",\n        \"04 - Abril\", \"05 - Mayo\", \"06 - Junio\",\n        \"07 - Julio\", \"08 - Agosto\", \"09 - Septiembre\",\n        \"10 - Octubre\", \"11 - Noviembre\", \"12 - Diciembre\"})\n        CmbMeses.SelectedIndex = 0\n\n        ' Configuración inicial del DataGridView\n        With dgvCalendario\n            .ReadOnly = True\n            .AllowUserToAddRows = False\n            .AllowUserToDeleteRows = False\n            .AllowUserToResizeColumns = False\n            .AllowUserToResizeRows = False\n            .SelectionMode = DataGridViewSelectionMode.CellSelect\n            .RowHeadersVisible = False\n            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill\n            .ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing\n            .ColumnHeadersHeight = 35\n            .EnableHeadersVisualStyles = False\n            .ColumnHeadersDefaultCellStyle.BackColor = Color.DarkSlateGray\n            .ColumnHeadersDefaultCellStyle.ForeColor = Color.White\n            .ColumnHeadersDefaultCellStyle.Font = New Font(\"Segoe UI\", 9, FontStyle.Bold)\n            .ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter\n            .ColumnHeadersDefaultCellStyle.WrapMode = DataGridViewTriState.True\n            .BackgroundColor = Color.Black\n            .GridColor = Color.Silver\n            .RowsDefaultCellStyle.BackColor = Color.Black\n            .RowsDefaultCellStyle.ForeColor = Color.White\n            .AlternatingRowsDefaultCellStyle.BackColor = Color.Black\n            .AlternatingRowsDefaultCellStyle.ForeColor = Color.White\n            .DefaultCellStyle.SelectionBackColor = Color.DarkRed\n            .DefaultCellStyle.SelectionForeColor = Color.White\n            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter\n            .RowTemplate.Height = 30\n        End With\n\n        CrearTablaSiNoExiste()\n\n        ' 🔹 Recargar datos y aplicar lógica completa\n        CargarDatos()\n        ActualizarEstados()\n        ActualizarResumen()\n\n        ' Configuración inicial del MaskedTextBox\n        MaskInicio.Text = \"\"\n        MaskInicio.BackColor = Color.Black\n        MaskInicio.ForeColor = Color.White\n    End Sub\n    Private Sub BtnConsultar_Click(sender As Object, e As EventArgs) Handles BtnConsultar.Click\n        If CmbMeses.SelectedIndex = -1 OrElse CmbMeses.Text = \"Seleccionar un Mes\" Then\n            MostrarMensaje(\"Debe seleccionar un mes antes de consultar.\")\n            Return\n        End If\n\n        ' Extraer el número de mes desde el texto (ej: \"05 - Mayo\" → \"05\")\n        Dim mesSeleccionado As String = CmbMeses.Text.Substring(0, 2)\n\n        Using conn As New SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n            conn.Open()\n            Dim sql As String = \"SELECT Id, Area, Cantidad, FechaInicio, FechaVencimiento, Estado \n                             FROM Extintores \n                             WHERE strftime('%m', FechaVencimiento) = @Mes\n                             ORDER BY FechaVencimiento ASC\"\n            Using cmd As New SQLiteCommand(sql, conn)\n                cmd.Parameters.AddWithValue(\"@Mes\", mesSeleccionado)\n                Dim da As New SQLiteDataAdapter(cmd)\n                Dim dt As New DataTable()\n                da.Fill(dt)\n                dgvCalendario.DataSource = dt\n            End Using\n        End Using\n\n        ' Recalcular estado en tiempo real según la fecha de vencimiento\n        For Each fila As DataGridViewRow In dgvCalendario.Rows\n            If fila.Cells(\"FechaVencimiento\").Value IsNot Nothing Then\n                Dim fv As Date\n                If Date.TryParse(fila.Cells(\"FechaVencimiento\").Value.ToString(), fv) Then\n                    Dim diasRestantes As Integer = (fv.Date - Date.Today).Days\n                    Dim estado As String\n\n                    If diasRestantes <= 0 Then\n                        estado = \"Vencido\"\n                    ElseIf diasRestantes <= 14 Then\n                        estado = \"Próximo a vencer\"\n                    ElseIf diasRestantes <= 21 Then\n                        estado = \"Próximo a vencer\"\n                    Else\n                        estado = \"Vigente\"\n                    End If\n\n                    fila.Cells(\"Estado\").Value = estado\n                End If\n            End If\n\n            ' Formatear fechas en dd-MM-yyyy\n            If fila.Cells(\"FechaInicio\").Value IsNot Nothing Then\n                Dim fi As Date\n                If Date.TryParse(fila.Cells(\"FechaInicio\").Value.ToString(), fi) Then\n                    fila.Cells(\"FechaInicio\").Value = fi.ToString(\"dd-MM-yyyy\")\n                End If\n            End If\n            If fila.Cells(\"FechaVencimiento\").Value IsNot Nothing Then\n                Dim fv As Date\n                If Date.TryParse(fila.Cells(\"FechaVencimiento\").Value.ToString(), fv) Then\n                    fila.Cells(\"FechaVencimiento\").Value = fv.ToString(\"dd-MM-yyyy\")\n                End If\n            End If\n        Next\n        ResetearComboMeses()\n    End Sub\n\n    Private Sub ResetearComboMeses()\n        CmbMeses.SelectedIndex = -1\n        CmbMeses.Text = \"Seleccionar un Mes\"\n    End Sub\n\n    Private Sub BtnEliminar_Click(sender As Object, e As EventArgs) Handles BtnEliminar.Click\n        If dgvCalendario.CurrentRow IsNot Nothing Then\n            Dim id As Integer = Convert.ToInt32(dgvCalendario.CurrentRow.Cells(\"Id\").Value)\n\n            ' Preguntar confirmación en Form2\n            Dim frmConfirmar As New Form2()\n            frmConfirmar.LabelMensaje.Text = \"¿Está seguro de eliminar el extintor seleccionado?\"\n            frmConfirmar.BtnAceptar.Text = \"Aceptar\"\n            frmConfirmar.BtnCancelar.Text = \"Cancelar\"\n\n            ' Configurar eventos para BCEvoButton\n            AddHandler frmConfirmar.BtnAceptar.Click, Sub()\n                                                          frmConfirmar.Tag = \"OK\"\n                                                          frmConfirmar.Close()\n                                                      End Sub\n            AddHandler frmConfirmar.BtnCancelar.Click, Sub()\n                                                           frmConfirmar.Tag = \"Cancel\"\n                                                           frmConfirmar.Close()\n                                                       End Sub\n\n            frmConfirmar.ShowDialog()\n\n            If frmConfirmar.Tag IsNot Nothing AndAlso frmConfirmar.Tag.ToString() = \"OK\" Then\n                ' Borrar en la base de datos\n                Using conn As New SQLite.SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n                    conn.Open()\n                    Dim sql As String = \"DELETE FROM Extintores WHERE Id=@Id\"\n                    Using cmd As New SQLite.SQLiteCommand(sql, conn)\n                        cmd.Parameters.AddWithValue(\"@Id\", id)\n                        cmd.ExecuteNonQuery()\n                    End Using\n                End Using\n\n                ' Recargar datos en vez de remover manualmente\n                CargarDatos()\n\n                ' Aviso de confirmación\n                Dim aviso As New Form2()\n                aviso.LabelMensaje.Text = \"Registro eliminado correctamente.\"\n                aviso.ShowDialog()\n            ElseIf frmConfirmar.Tag IsNot Nothing AndAlso frmConfirmar.Tag.ToString() = \"Cancel\" Then\n                ' Aviso de cancelación\n                Dim aviso As New Form2()\n                aviso.LabelMensaje.Text = \"Eliminación cancelada por el usuario.\"\n                aviso.ShowDialog()\n            End If\n        Else\n            Dim aviso As New Form2()\n            aviso.LabelMensaje.Text = \"Seleccione una fila para eliminar.\"\n            aviso.ShowDialog()\n        End If\n\n        ActualizarEstados()\n        ActualizarResumen()\n\n    End Sub\n\n\n    Private Sub BtnTodos_Click(sender As Object, e As EventArgs) Handles BtnTodos.Click\n        CargarDatos()\n        ActualizarEstados()\n    End Sub\n\n    Private Sub BtnEditar_Click(sender As Object, e As EventArgs) Handles BtnEditar.Click\n        If dgvCalendario.CurrentRow IsNot Nothing Then\n            Dim fila As DataGridViewRow = dgvCalendario.CurrentRow\n            Dim formEdit As New FormEditar()\n\n            ' Pasar valores actuales\n            formEdit.TxtArea.Text = fila.Cells(\"Area\").Value.ToString()\n            formEdit.TxtCantidad.Text = fila.Cells(\"Cantidad\").Value.ToString()\n            formEdit.MaskInicio.Text = fila.Cells(\"FechaInicio\").Value.ToString()\n\n            ' Preguntar confirmación en Form2 antes de editar\n            Dim frmConfirmar As New Form2()\n            frmConfirmar.LabelMensaje.Text = \"¿Está seguro de editar el extintor seleccionado?\"\n            frmConfirmar.BtnAceptar.Text = \"Aceptar\"\n            frmConfirmar.BtnCancelar.Text = \"Cancelar\"\n\n            AddHandler frmConfirmar.BtnAceptar.Click, Sub()\n                                                          frmConfirmar.Tag = \"OK\"\n                                                          frmConfirmar.Close()\n                                                      End Sub\n            AddHandler frmConfirmar.BtnCancelar.Click, Sub()\n                                                           frmConfirmar.Tag = \"Cancel\"\n                                                           frmConfirmar.Close()\n                                                       End Sub\n\n            frmConfirmar.ShowDialog()\n\n            If frmConfirmar.Tag IsNot Nothing AndAlso frmConfirmar.Tag.ToString() = \"OK\" Then\n                ' Mostrar formulario de edición\n                If formEdit.ShowDialog() = DialogResult.OK Then\n                    ' Actualizar valores en la grilla\n                    fila.Cells(\"Area\").Value = formEdit.TxtArea.Text\n                    fila.Cells(\"Cantidad\").Value = formEdit.TxtCantidad.Text\n                    fila.Cells(\"FechaInicio\").Value = formEdit.MaskInicio.Text\n                    fila.Cells(\"FechaVencimiento\").Value = formEdit.FechaVencimientoCalculada\n\n                    ' Recalcular estado\n                    Dim fechaVenc As Date = Date.Parse(fila.Cells(\"FechaVencimiento\").Value.ToString())\n                    fila.Cells(\"Estado\").Value = CalcularEstado(fechaVenc)\n\n                    ' Guardar en la base de datos (UPDATE)\n                    Dim id As Integer = Convert.ToInt32(fila.Cells(\"Id\").Value)\n                    Using conn As New SQLite.SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n                        conn.Open()\n                        Dim sql As String = \"UPDATE Extintores \n                                         SET Area=@Area, Cantidad=@Cantidad, FechaInicio=@FechaInicio, \n                                             FechaVencimiento=@FechaVencimiento, Estado=@Estado \n                                         WHERE Id=@Id\"\n                        Using cmd As New SQLite.SQLiteCommand(sql, conn)\n                            cmd.Parameters.AddWithValue(\"@Area\", formEdit.TxtArea.Text)\n                            cmd.Parameters.AddWithValue(\"@Cantidad\", Convert.ToInt32(formEdit.TxtCantidad.Text))\n                            cmd.Parameters.AddWithValue(\"@FechaInicio\", Date.Parse(formEdit.MaskInicio.Text).ToString(\"yyyy-MM-dd\"))\n                            cmd.Parameters.AddWithValue(\"@FechaVencimiento\", Date.Parse(formEdit.FechaVencimientoCalculada).ToString(\"yyyy-MM-dd\"))\n                            cmd.Parameters.AddWithValue(\"@Estado\", fila.Cells(\"Estado\").Value.ToString())\n                            cmd.Parameters.AddWithValue(\"@Id\", id)\n                            cmd.ExecuteNonQuery()\n                        End Using\n                    End Using\n\n                    ' Aviso de confirmación\n                    Dim aviso As New Form2()\n                    aviso.LabelMensaje.Text = \"Registro editado correctamente.\"\n                    aviso.ShowDialog()\n                End If\n            ElseIf frmConfirmar.Tag IsNot Nothing AndAlso frmConfirmar.Tag.ToString() = \"Cancel\" Then\n                ' Aviso de cancelación\n                Dim aviso As New Form2()\n                aviso.LabelMensaje.Text = \"Edición cancelada por el usuario.\"\n                aviso.ShowDialog()\n            End If\n        Else\n            ' Aviso de confirmación\n            Dim aviso As New Form2()\n            aviso.LabelMensaje.Text = \"Registro editado correctamente.\"\n            aviso.ShowDialog()\n        End If\n\n        ' 🔹 Recargar datos ordenados y refrescar estados\n        CargarDatos()\n        ActualizarEstados()\n        ActualizarResumen()\n\n\n    End Sub\n    Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown\n        If e.KeyCode = Keys.Escape Then\n            dgvCalendario.ClearSelection()\n            dgvCalendario.CurrentCell = Nothing\n            For Each fila As DataGridViewRow In dgvCalendario.Rows\n                fila.DefaultCellStyle.BackColor = Color.Black\n                fila.DefaultCellStyle.ForeColor = Color.White\n            Next\n        End If\n    End Sub\n\n    ' --- TimerAviso ---\n    Private avisadosHoy As New HashSet(Of Integer)\n    Private fechaUltimoAviso As Date = Date.Today\n\n    Private Sub TimerAviso_Tick(sender As Object, e As EventArgs) Handles TimerAviso.Tick\n        Dim horaActual As Integer = DateTime.Now.Hour\n\n        ' Reiniciar lista de avisados cada día\n        If fechaUltimoAviso <> Date.Today Then\n            avisadosHoy.Clear()\n            fechaUltimoAviso = Date.Today\n        End If\n\n        ' Solo entre 8 y 17 horas\n        If horaActual >= 8 AndAlso horaActual <= 22 Then\n            Using conn As New SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n                conn.Open()\n                ' Buscar extintores que vencen en los próximos 21 días o ya vencidos\n                Dim cmd As New SQLiteCommand(\"SELECT Id, Area, FechaVencimiento \n                                          FROM Extintores \n                                          WHERE date(FechaVencimiento) <= date('now', '+21 days') \n                                          ORDER BY FechaVencimiento ASC\", conn)\n                Dim reader As SQLiteDataReader = cmd.ExecuteReader()\n\n                Dim listaAvisos As New Text.StringBuilder()\n\n                While reader.Read()\n                    Dim id As Integer = Convert.ToInt32(reader(\"Id\"))\n                    Dim area As String = reader(\"Area\").ToString()\n                    Dim fechaVenc As Date = Date.Parse(reader(\"FechaVencimiento\").ToString())\n                    Dim diasRestantes As Integer = (fechaVenc.Date - Date.Today).Days\n\n                    ' Solo incluir si no fue avisado hoy\n                    If Not avisadosHoy.Contains(id) Then\n                        If diasRestantes < 0 Then\n                            listaAvisos.AppendLine(\"• Extintor en área \" & area &\n                                               \" venció el \" & fechaVenc.ToString(\"dd-MM-yyyy\") &\n                                               \" (vencido hace \" & Math.Abs(diasRestantes) & \" días)\")\n                        Else\n                            listaAvisos.AppendLine(\"• Extintor en área \" & area &\n                                               \" vence el \" & fechaVenc.ToString(\"dd-MM-yyyy\") &\n                                               \" (faltan \" & diasRestantes & \" días)\")\n                        End If\n                        avisadosHoy.Add(id)\n                    End If\n                End While\n                reader.Close()\n\n                ' Mostrar un solo aviso si hay registros\n                If listaAvisos.Length > 0 Then\n                    Dim frmAviso As New Form2()\n                    frmAviso.LabelMensaje.Text = \"Extintores próximos a vencer:\" & vbCrLf & vbCrLf & listaAvisos.ToString()\n                    frmAviso.ShowDialog()\n                End If\n            End Using\n        End If\n    End Sub\n    Private Sub ActualizarResumen()\n        Dim sqlResumen As String = \"SELECT Estado, COUNT(*) AS Cantidad FROM Extintores GROUP BY Estado\"\n        Dim totalGeneral As Integer = 0\n\n        Using conn As New SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n            conn.Open()\n\n            Using cmdTotal As New SQLiteCommand(\"SELECT COUNT(*) FROM Extintores\", conn)\n                totalGeneral = Convert.ToInt32(cmdTotal.ExecuteScalar())\n            End Using\n\n            Using cmd As New SQLiteCommand(sqlResumen, conn)\n                Using reader As SQLiteDataReader = cmd.ExecuteReader()\n                    While reader.Read()\n                        Dim estado As String = reader(\"Estado\").ToString()\n                        Dim cantidad As Integer = Convert.ToInt32(reader(\"Cantidad\"))\n                        Select Case estado\n                            Case \"Vigente\"\n                                lblVigente.Text = \"Vigentes: \" & cantidad\n                            Case \"Próximo a vencer\"\n                                lblProximo.Text = \"Próximos: \" & cantidad\n                            Case \"Vencido\"\n                                lblVencido.Text = \"Vencidos: \" & cantidad\n                        End Select\n                    End While\n                End Using\n            End Using\n        End Using\n\n        lblTotal.Text = \"Total: \" & totalGeneral\n    End Sub\n    Private Sub CrearTablaSiNoExiste()\n        Using conn As New SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n            conn.Open()\n            Dim sql As String = \"CREATE TABLE IF NOT EXISTS Extintores (\" &\n                            \"Id INTEGER PRIMARY KEY AUTOINCREMENT,\" &\n                            \"Area TEXT,\" &\n                            \"Cantidad INTEGER,\" &\n                            \"FechaInicio TEXT,\" &\n                            \"FechaVencimiento TEXT,\" &\n                            \"Estado TEXT)\"\n            Dim cmd As New SQLiteCommand(sql, conn)\n            cmd.ExecuteNonQuery()\n        End Using\n    End Sub\n    Private Sub CargarDatos()\n        Using conn As New SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n            conn.Open()\n            Dim sql As String = \"SELECT Id, Area, Cantidad, FechaInicio, FechaVencimiento, Estado \nFROM Extintores \nORDER BY FechaVencimiento ASC;\n\"\n            Using cmd As New SQLiteCommand(sql, conn)\n                Dim da As New SQLiteDataAdapter(cmd)\n                Dim dt As New DataTable()\n                da.Fill(dt)\n                dgvCalendario.DataSource = dt\n            End Using\n        End Using\n\n        ' Quitar flecha negra de ordenamiento\n        For Each col As DataGridViewColumn In dgvCalendario.Columns\n            col.SortMode = DataGridViewColumnSortMode.NotSortable\n            col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter\n        Next\n\n        ' Encabezados en dos líneas\n        dgvCalendario.Columns(\"FechaVencimiento\").HeaderText = \"Fecha\" & vbCrLf & \"Vencimiento\"\n        dgvCalendario.Columns(\"FechaInicio\").HeaderText = \"Fecha\" & vbCrLf & \"Inicio\"\n        dgvCalendario.Columns(\"Cantidad\").HeaderText = \"Cantidad Extintor\"\n        ' Formato de fechas\n        For Each fila As DataGridViewRow In dgvCalendario.Rows\n            If fila.Cells(\"FechaInicio\").Value IsNot Nothing Then\n                Dim fi As Date\n                If Date.TryParse(fila.Cells(\"FechaInicio\").Value.ToString(), fi) Then\n                    fila.Cells(\"FechaInicio\").Value = fi.ToString(\"dd-MM-yyyy\")\n                End If\n            End If\n\n            If fila.Cells(\"FechaVencimiento\").Value IsNot Nothing Then\n                Dim fv As Date\n                If Date.TryParse(fila.Cells(\"FechaVencimiento\").Value.ToString(), fv) Then\n                    fila.Cells(\"FechaVencimiento\").Value = fv.ToString(\"dd-MM-yyyy\")\n                End If\n            End If\n        Next\n\n        ' 🔹 Fijar ancho de columnas (ajusta valores según tu preferencia)\n        If dgvCalendario.Columns.Contains(\"Id\") Then\n            dgvCalendario.Columns(\"Id\").Width = 50\n        End If\n        If dgvCalendario.Columns.Contains(\"Area\") Then\n            dgvCalendario.Columns(\"Area\").Width = 120\n        End If\n        If dgvCalendario.Columns.Contains(\"Cantidad\") Then\n            dgvCalendario.Columns(\"Cantidad\").Width = 90\n        End If\n        If dgvCalendario.Columns.Contains(\"FechaInicio\") Then\n            dgvCalendario.Columns(\"FechaInicio\").Width = 110\n        End If\n        If dgvCalendario.Columns.Contains(\"FechaVencimiento\") Then\n            dgvCalendario.Columns(\"FechaVencimiento\").Width = 120\n        End If\n        If dgvCalendario.Columns.Contains(\"Estado\") Then\n            dgvCalendario.Columns(\"Estado\").Width = 120\n        End If\n    End Sub\n    Private Sub ResetearIds(tabla As String)\n        Try\n            Using conn As New SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n                conn.Open()\n\n                ' Verificar si la tabla tiene registros\n                Dim sqlCount As String = $\"SELECT COUNT(*) FROM {tabla}\"\n                Using cmdCount As New SQLiteCommand(sqlCount, conn)\n                    Dim totalRegistros As Integer = Convert.ToInt32(cmdCount.ExecuteScalar())\n\n                    If totalRegistros > 0 Then\n                        ' Mostrar aviso en Form2\n                        Dim frmMsg As New Form2()\n                        frmMsg.LabelMensaje.Text = \"⚠️ No se puede resetear el ID mientras existan registros. Elimine todos los datos primero.\"\n                        frmMsg.ShowDialog()\n                        Exit Sub\n                    End If\n                End Using\n\n                ' Si está vacía, resetear el autoincremento\n                Dim sqlReset As String = \"DELETE FROM sqlite_sequence WHERE name=@tabla;\"\n                Using cmdReset As New SQLiteCommand(sqlReset, conn)\n                    cmdReset.Parameters.AddWithValue(\"@tabla\", tabla)\n                    cmdReset.ExecuteNonQuery()\n                End Using\n            End Using\n\n            ' Mostrar mensaje en Form2\n            Dim frmMsgOk As New Form2()\n            frmMsgOk.LabelMensaje.Text = \"✅ El contador de IDs de la tabla '\" & tabla & \"' fue reseteado correctamente. El próximo registro comenzará desde 1.\"\n            frmMsgOk.ShowDialog()\n\n        Catch ex As Exception\n            ' Mostrar error en Form2\n            Dim frmMsgErr As New Form2()\n            frmMsgErr.LabelMensaje.Text = \"Error al resetear IDs: \" & ex.Message\n            frmMsgErr.ShowDialog()\n        End Try\n    End Sub\n    Private Sub BtnResetear_Click(sender As Object, e As EventArgs) Handles BtnResetear.Click\n        ResetearIds(\"Extintores\")\n    End Sub\n    Private Sub DgvCalendario_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles dgvCalendario.CellFormatting\n        If dgvCalendario.Columns(e.ColumnIndex).Name = \"FechaVencimiento\" AndAlso e.Value IsNot Nothing Then\n            Dim fechaVenc As Date = Date.Parse(e.Value.ToString())\n            Dim diasRestantes As Integer = (fechaVenc.Date - DateTime.Today).Days\n\n            If diasRestantes <= 0 Then\n                ' Vencido → rojo\n                e.CellStyle.BackColor = Color.DarkRed\n                e.CellStyle.ForeColor = Color.White\n                e.CellStyle.SelectionBackColor = Color.DarkRed\n                e.CellStyle.SelectionForeColor = Color.White\n\n            ElseIf diasRestantes <= 21 Then\n                ' Próximo a vencer → amarillo\n                e.CellStyle.BackColor = Color.Yellow\n                e.CellStyle.ForeColor = Color.Black\n                e.CellStyle.SelectionBackColor = Color.Goldenrod\n                e.CellStyle.SelectionForeColor = Color.Black\n\n            ElseIf diasRestantes <= 21 Then\n                ' Próximo a vencer → tema oscuro normal (negro)\n                e.CellStyle.BackColor = Color.Black\n                e.CellStyle.ForeColor = Color.White\n                e.CellStyle.SelectionBackColor = Color.Black\n                e.CellStyle.SelectionForeColor = Color.White\n\n            Else\n                ' Vigente → tema oscuro normal\n                e.CellStyle.BackColor = Color.Black\n                e.CellStyle.ForeColor = Color.White\n                e.CellStyle.SelectionBackColor = Color.Black\n                e.CellStyle.SelectionForeColor = Color.White\n            End If\n        End If\n    End Sub\n\n    ' --- ToolTip dinámico en Estado y FechaVencimiento ---\n    Private Sub dgvCalendario_CellToolTipTextNeeded(sender As Object, e As DataGridViewCellToolTipTextNeededEventArgs) Handles dgvCalendario.CellToolTipTextNeeded\n        If e.RowIndex >= 0 AndAlso e.ColumnIndex >= 0 Then\n            Dim colName As String = dgvCalendario.Columns(e.ColumnIndex).Name\n            If colName = \"Estado\" OrElse colName = \"FechaVencimiento\" Then\n                Dim fila As DataGridViewRow = dgvCalendario.Rows(e.RowIndex)\n                If fila.Cells(\"FechaVencimiento\").Value IsNot Nothing Then\n                    Dim fv As Date\n                    If Date.TryParse(fila.Cells(\"FechaVencimiento\").Value.ToString(), fv) Then\n                        Dim diasRestantes As Integer = (fv - Date.Today).Days\n                        If diasRestantes < 0 Then\n                            e.ToolTipText = $\"Vencido hace {Math.Abs(diasRestantes)} días\"\n                        ElseIf diasRestantes <= 14 Then\n                            e.ToolTipText = $\"Faltan {diasRestantes} días (Próximo a vencer - amarillo)\"\n                        ElseIf diasRestantes <= 21 Then\n                            e.ToolTipText = $\"Faltan {diasRestantes} días (Próximo a vencer)\"\n                        Else\n                            e.ToolTipText = $\"Faltan {diasRestantes} días (Vigente)\"\n                        End If\n                    End If\n                End If\n            End If\n        End If\n    End Sub\n\n    ' --- Botón Agregar (nuevo o edición) ---\n    Private Sub BtnAgregar_Click(sender As Object, e As EventArgs) Handles BtnAgregar.Click\n        ' Validar campos obligatorios\n        If String.IsNullOrWhiteSpace(TxtArea.Text) OrElse String.IsNullOrWhiteSpace(TxtCantidad.Text) Then\n            MostrarMensaje(\"Debe ingresar Área y Cantidad.\")\n            Return\n        End If\n\n        ' Validar fecha de inicio\n        Dim fechaInicio As Date\n        If Not DateTime.TryParseExact(MaskInicio.Text, \"dd-MM-yyyy\",\n                Globalization.CultureInfo.InvariantCulture,\n                Globalization.DateTimeStyles.None,\n                fechaInicio) Then\n            MostrarMensaje(\"Ingrese una fecha válida en formato dd-MM-yyyy.\")\n            Return\n        End If\n\n        ' Calcular vencimiento (+1 año)\n        Dim fechaVencimiento As Date = fechaInicio.AddYears(1)\n        LabelVencimiento.Text = fechaVencimiento.ToString(\"dd-MM-yyyy\")\n\n        ' Calcular estado\n        Dim diasRestantes As Integer = (fechaVencimiento.Date - Date.Today).Days\n        Dim estado As String\n        If diasRestantes <= 0 Then\n            estado = \"Vencido\"\n        ElseIf diasRestantes <= 14 Then\n            estado = \"Próximo a vencer\"\n        ElseIf diasRestantes <= 21 Then\n            estado = \"Próximo a vencer\"\n        Else\n            estado = \"Vigente\"\n        End If\n\n        ' Guardar en SQLite\n        Using conn As New SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n            conn.Open()\n            If BtnAgregar.Tag IsNot Nothing Then\n                ' Modo edición\n                Dim idEditar As Integer = CInt(BtnAgregar.Tag)\n                Dim sqlUpdate As String = \"UPDATE Extintores SET Area=@Area, Cantidad=@Cantidad, FechaInicio=@FechaInicio, FechaVencimiento=@FechaVencimiento, Estado=@Estado WHERE Id=@Id\"\n                Using cmd As New SQLiteCommand(sqlUpdate, conn)\n                    cmd.Parameters.AddWithValue(\"@Area\", TxtArea.Text)\n                    cmd.Parameters.AddWithValue(\"@Cantidad\", Convert.ToInt32(TxtCantidad.Text))\n                    cmd.Parameters.AddWithValue(\"@FechaInicio\", fechaInicio.ToString(\"yyyy-MM-dd\"))\n                    cmd.Parameters.AddWithValue(\"@FechaVencimiento\", fechaVencimiento.ToString(\"yyyy-MM-dd\"))\n                    cmd.Parameters.AddWithValue(\"@Estado\", estado)\n                    cmd.Parameters.AddWithValue(\"@Id\", idEditar)\n                    cmd.ExecuteNonQuery()\n                End Using\n                BtnAgregar.Tag = Nothing\n            Else\n                ' Nuevo registro\n                Dim sqlInsert As String = \"INSERT INTO Extintores (Area, Cantidad, FechaInicio, FechaVencimiento, Estado) VALUES (@Area, @Cantidad, @FechaInicio, @FechaVencimiento, @Estado)\"\n                Using cmd As New SQLiteCommand(sqlInsert, conn)\n                    cmd.Parameters.AddWithValue(\"@Area\", TxtArea.Text)\n                    cmd.Parameters.AddWithValue(\"@Cantidad\", Convert.ToInt32(TxtCantidad.Text))\n                    cmd.Parameters.AddWithValue(\"@FechaInicio\", fechaInicio.ToString(\"yyyy-MM-dd\"))\n                    cmd.Parameters.AddWithValue(\"@FechaVencimiento\", fechaVencimiento.ToString(\"yyyy-MM-dd\"))\n                    cmd.Parameters.AddWithValue(\"@Estado\", estado)\n                    cmd.ExecuteNonQuery()\n                End Using\n            End If\n        End Using\n\n        ' Recargar datos y actualizar resumen\n        CargarDatos()\n        ActualizarResumen()\n\n        LimpiarCampos()\n\n        ' Aviso\n        Dim aviso As New Form2()\n        aviso.LabelMensaje.Text = \"Registro guardado correctamente.\"\n        aviso.ShowDialog()\n    End Sub\n    Private Sub BtnDB_Click(sender As Object, e As EventArgs) Handles BtnDB.Click\n        ' Confirmación en Form2\n        Dim frmConfirmar As New Form2()\n        frmConfirmar.LabelMensaje.Text = \"¿Está seguro de eliminar TODOS los registros de la base de datos?\"\n        frmConfirmar.BtnAceptar.Text = \"Aceptar\"\n        frmConfirmar.BtnCancelar.Text = \"Cancelar\"\n\n        AddHandler frmConfirmar.BtnAceptar.Click, Sub()\n                                                      frmConfirmar.Tag = \"OK\"\n                                                      frmConfirmar.Close()\n                                                  End Sub\n        AddHandler frmConfirmar.BtnCancelar.Click, Sub()\n                                                       frmConfirmar.Tag = \"Cancel\"\n                                                       frmConfirmar.Close()\n                                                   End Sub\n\n        frmConfirmar.ShowDialog()\n\n        If frmConfirmar.Tag IsNot Nothing AndAlso frmConfirmar.Tag.ToString() = \"OK\" Then\n            Using conn As New SQLite.SQLiteConnection(\"Data Source=extintores.db;Version=3;\")\n                conn.Open()\n                ' 🔹 Eliminar todos los registros de la tabla\n                Dim sql As String = \"DELETE FROM Extintores\"\n                Using cmd As New SQLite.SQLiteCommand(sql, conn)\n                    cmd.ExecuteNonQuery()\n                End Using\n            End Using\n\n            ' Recargar grilla y resumen\n            CargarDatos()\n            ActualizarEstados()\n            ActualizarResumen()\n\n            ' Aviso\n            Dim aviso As New Form2()\n            aviso.LabelMensaje.Text = \"Todos los registros fueron eliminados.\"\n            aviso.ShowDialog()\n        Else\n            Dim aviso As New Form2()\n            aviso.LabelMensaje.Text = \"Eliminación cancelada por el usuario.\"\n            aviso.ShowDialog()\n        End If\n    End Sub\nEnd Class"}