using PostFundManagement.Domain.Abstractions; using PostFundManagement.Domain.Errors; using PostFundManagement.Application.Extensions; namespace PostFundManagement.Application.Services.Shared; public sealed partial class HashService(IHashids hasher) : IService { public static bool IsMd5Hash(string? value) => !string.IsNullOrWhiteSpace(value) && Patterns.Md5Regex.IsMatch(value); public static bool IsSha256Hash(string? value) => !string.IsNullOrWhiteSpace(value) && Patterns.Sha256Regex.IsMatch(value); public static string? StringToSha256Hash(string? input) => string.IsNullOrEmpty(input) ? null : Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(input))); public static string? StreamToSha256Hash(Stream stream) => stream is null ? null : Convert.ToHexString(SHA256.HashData(stream)); public static string? BytesToSha256Hash(byte[] bytes) => bytes is null ? null : Convert.ToHexString(SHA256.HashData(bytes)); public static Result ToMd5Hash(string input) { if (string.IsNullOrEmpty(input)) return Result.Fail(ValidationError.Create("Input content cannot be null or empty for MD5 processing.")); byte[] bytes = MD5.HashData(Encoding.UTF8.GetBytes(input)); return Result.Ok(Convert.ToHexString(bytes).ToLowerInvariant()); } public Result HashEncodeHex(string input) => Result.FailIf(string.IsNullOrWhiteSpace(input) || !Patterns.HexHashRegex.IsMatch(input), ValidationError.Create("Input must be a valid hexadecimal string.")) .ToResult(hasher.EncodeHex(input)); public Result HashEncodeIntId(int id) => Result.FailIf(id < 0, ValidationError.Create("Id cannot be negative.")) .ToResult(hasher.Encode(id)); public Result HashEncodeLongId(long id) => Result.FailIf(id < 0, ValidationError.Create("Id cannot be negative.")) .ToResult(hasher.EncodeLong(id)); public Result DecodeIntIdHash(string hash) { if (string.IsNullOrWhiteSpace(hash)) return Result.Fail(ValidationError.Create("Invalid token layout.")); int[] decoded = hasher.Decode(hash); return Result.FailIf(decoded.Length <= 0, ValidationError.Create("Invalid or modified Int hash token.")) .ToResult(decoded[0]); } public Result DecodeLongIdHash(string hash) { if (string.IsNullOrWhiteSpace(hash)) return Result.Fail(ValidationError.Create("Invalid token layout.")); long[] decoded = hasher.DecodeLong(hash); return Result.FailIf(decoded.Length <= 0, ValidationError.Create("Invalid or modified Long hash token.")) .ToResult(decoded[0]); } public async Task> DecodeHexHash(string hex) => await Result.Try((Func>>)(async () => { string decoded = hasher.DecodeHex(hex); return Result.FailIf(string.IsNullOrEmpty(decoded), ValidationError.Create("Invalid or corrupted hex hash.")) .ToResult(decoded); })); }