using System.Security.Cryptography;

namespace Metin2Launcher.Transfer;

/// <summary>Streaming sha256 helpers.</summary>
public static class FileHasher
{
    private const int BufferSize = 1024 * 1024; // 1 MiB

    /// <summary>Computes the sha256 of a file as lowercase hex. Returns null if the file doesn't exist.</summary>
    public static string? HashFileOrNull(string path)
    {
        if (!File.Exists(path))
            return null;
        using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.SequentialScan);
        return HashStream(fs);
    }

    /// <summary>Computes the sha256 of a stream as lowercase hex.</summary>
    public static string HashStream(Stream stream)
    {
        using var sha = SHA256.Create();
        var buf = new byte[BufferSize];
        int n;
        while ((n = stream.Read(buf, 0, buf.Length)) > 0)
        {
            sha.TransformBlock(buf, 0, n, null, 0);
        }
        sha.TransformFinalBlock(Array.Empty<byte>(), 0, 0);
        return Convert.ToHexString(sha.Hash!).ToLowerInvariant();
    }

    /// <summary>Computes the sha256 of a byte span as lowercase hex.</summary>
    public static string HashBytes(ReadOnlySpan<byte> data)
        => Convert.ToHexString(SHA256.HashData(data)).ToLowerInvariant();
}
