using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using adas_core.Domain.Models.GroupedObservations;
using MongoDB.Bson;
namespace adas_core.Domain.Utils;
///
/// Provides a static container for cryptographic operations and utilities related to the Adas domain.
///
public static class CryptoAdas
{
private static readonly Regex PassRegex = new("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$");
///
/// Computes the MD5 hash of the specified input string and returns it as an uppercase hexadecimal string.
/// The hash bytes are iterated in reverse order before being formatted.
///
/// The string to hash. Its ASCII byte representation is used as the input to the MD5 algorithm.
/// The MD5 hash of formatted as an uppercase hexadecimal string.
public static string CreateMd5(string input)
{
using var md5 = MD5.Create();
var inputBytes = Encoding.ASCII.GetBytes(input);
var hashBytes = md5.ComputeHash(inputBytes);
var sb = new StringBuilder();
for (var i = hashBytes.Length - 1; i >= 0; i--) sb.Append(hashBytes[i].ToString("X2"));
var res = sb.ToString();
return res;
}
///
/// Creates a deterministic MD5 hash that uniquely identifies a grouped field configuration for a specific patient.
/// Falls back to a single-element list containing the group's name (or empty string) when the collection is null or empty.
///
/// The grouped field whose names, max, since, regularity, and results are included in the hash input.
/// The identifier of the patient whose data is being hashed.
/// An MD5 hash string representing the combined patient and grouped field data.
public static string CreateMd5GroupedObs(GroupedField gF, ObjectId patientId)
{
var names = CollectionsUtils.IfEmptyOrNull(gF.Names, [gF.Name ?? string.Empty]);
return CreateMd5(patientId +
string.Join("+", names.Select(c => c.ToString())) +
gF.Max +
gF.Since +
gF.Regularity +
string.Join("+", gF.Result.Select(c => c.ToString())));
}
///
/// Creates a BCrypt hash from the provided input string, typically used for securely storing passwords.
///
/// The plain text string to be hashed.
/// A BCrypt hashed representation of the input string.
public static string CreateBCrypt(string input)
{
return BCrypt.Net.BCrypt.HashPassword(input);
}
///
/// Verifies that the provided plain text password matches the stored BCrypt password hash.
///
/// The plain text password entered by the user during login.
/// The stored BCrypt hash to compare the password against.
/// true if the password matches the hash; otherwise, false.
public static bool VerifyPassword(string loginPass, string passwordHash)
{
return BCrypt.Net.BCrypt.Verify(loginPass, passwordHash);
}
///
/// Determines whether the specified password meets the strong password criteria defined by the password regex pattern.
///
/// The password string to evaluate against the strong password requirements.
/// true if the password matches the strong password pattern; otherwise, false.
public static bool IsStrongPassword(string password)
{
return PassRegex.IsMatch(password);
}
}