using System.Security.Cryptography;
using System.Text;

namespace Eis.Infrastructure.Authentication;

internal sealed class PasswordCompatibilityService
{
    private const int Iterations = 120_000;
    private const int HashLength = 32;

    public string Hash(string password)
    {
        var salt = Convert.ToHexStringLower(RandomNumberGenerator.GetBytes(16));
        var hash = Derive(password, salt);
        return $"{salt}:{Convert.ToHexStringLower(hash)}";
    }

    public bool Verify(string password, string? stored)
    {
        var parts = (stored ?? string.Empty).Split(':', 2);
        if (parts.Length != 2 || parts[0].Length == 0 || parts[1].Length != HashLength * 2)
        {
            return false;
        }

        try
        {
            var expected = Convert.FromHexString(parts[1]);
            var actual = Derive(password, parts[0]);
            return CryptographicOperations.FixedTimeEquals(actual, expected);
        }
        catch (FormatException)
        {
            return false;
        }
    }

    private static byte[] Derive(string password, string salt) => Rfc2898DeriveBytes.Pbkdf2(
        Encoding.UTF8.GetBytes(password),
        Encoding.UTF8.GetBytes(salt),
        Iterations,
        HashAlgorithmName.SHA256,
        HashLength);
}
