Imports System.Text.RegularExpressions

Public Class UrlDetector
    '// Lista de protocolos compatibles
    Private Shared ReadOnly Protocols As String = "https?|ftps?|sftp|file|mailto|data|rtsp|rtmp|mms|jdbc|telnet|ssh|ws|wss|svn|git|vnc|irc|sip|bitcoin|ethereum|magnet|news|nntp|ldap"

    '// Patrón de nombres de dominio
    Private Shared ReadOnly DomainPattern As String = "(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,6}"

    '// Patrón para direcciones IPv4
    Private Shared ReadOnly IPv4Pattern As String = "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"

    '// Patrón para direcciones IPv6
    Private Shared ReadOnly IPv6Pattern As String = "\[(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\]"

    '// Patrón para localhost
    Private Shared ReadOnly LocalhostPattern As String = "localhost"

    '// Número de puerto y ruta opcionales
    Private Shared ReadOnly PortAndPathPattern As String = "(?::\d{1,5})?(?:/\S*)?"

    '// Compilar los patrones regex para mejorar el rendimiento
    Private Shared ReadOnly UrlContainsRegex As New Regex(
        $"({Protocols})://(?:{DomainPattern}|{IPv4Pattern}|{IPv6Pattern}|{LocalhostPattern}){PortAndPathPattern}",
        RegexOptions.Compiled Or RegexOptions.IgnoreCase)

    Private Shared ReadOnly UrlIsRegex As New Regex(
        $"^({Protocols})://(?:{DomainPattern}|{IPv4Pattern}|{IPv6Pattern}|{LocalhostPattern}){PortAndPathPattern}$",
        RegexOptions.Compiled Or RegexOptions.IgnoreCase)

    ''' <summary>
    ''' Determina si el mensaje dado contiene una URL.
    ''' </summary>
    ''' <param name="message">El mensaje a verificar.</param>
    ''' <returns>True si el mensaje contiene una URL, en caso contrario False.</returns>
    Public Shared Function ContainsUrl(message As String) As Boolean
        If String.IsNullOrWhiteSpace(message) Then
            Return False
        End If

        Return UrlContainsRegex.IsMatch(message)
    End Function

    ''' <summary>
    ''' Determina si el mensaje dado es una URL.
    ''' </summary>
    ''' <param name="message">El mensaje a verificar.</param>
    ''' <returns>True si el mensaje contiene una URL, en caso contrario False.</returns>
    Public Shared Function IsUrl(message As String) As Boolean
        If String.IsNullOrWhiteSpace(message) Then
            Return False
        End If

        Return UrlIsRegex.IsMatch(message)
    End Function
End Class