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

namespace FutureMailAPI.Helpers
{
    public interface IPasswordHelper
    {
        string HashPassword(string password);
        bool VerifyPassword(string password, string hash);
        bool VerifyPassword(string password, string hash, string salt);
        string HashPassword(string password, string salt);
        string GenerateSalt();
    }
    
    public class PasswordHelper : IPasswordHelper
    {
        public string HashPassword(string password)
        {
            // 生成随机盐值
            byte[] salt;
            new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);
            
            // 使用PBKDF2算法生成哈希
            var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000);
            byte[] hash = pbkdf2.GetBytes(20);
            
            // 组合盐值和哈希值
            byte[] hashBytes = new byte[36];
            Array.Copy(salt, 0, hashBytes, 0, 16);
            Array.Copy(hash, 0, hashBytes, 16, 20);
            
            // 转换为Base64字符串
            return Convert.ToBase64String(hashBytes);
        }
        
        public string GenerateSalt()
        {
            // 生成随机盐值
            byte[] salt;
            new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);
            
            // 转换为Base64字符串
            return Convert.ToBase64String(salt);
        }
        
        public string HashPassword(string password, string salt)
        {
            // 将Base64盐值转换为字节数组
            byte[] saltBytes = Convert.FromBase64String(salt);
            
            // 使用PBKDF2算法生成哈希
            var pbkdf2 = new Rfc2898DeriveBytes(password, saltBytes, 10000);
            byte[] hash = pbkdf2.GetBytes(20);
            
            // 转换为Base64字符串
            return Convert.ToBase64String(hash);
        }
        
        public bool VerifyPassword(string password, string hash)
        {
            try
            {
                // 检查哈希长度，判断是完整哈希（36字节）还是纯哈希（20字节）
                byte[] hashBytes = Convert.FromBase64String(hash);
                
                if (hashBytes.Length == 36)
                {
                    // 完整哈希格式：盐值(16字节) + 哈希值(20字节)
                    byte[] salt = new byte[16];
                    Array.Copy(hashBytes, 0, salt, 0, 16);
                    
                    // 使用相同的盐值计算密码的哈希
                    var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000);
                    byte[] computedHash = pbkdf2.GetBytes(20);
                    
                    // 比较两个哈希值
                    for (int i = 0; i < 20; i++)
                    {
                        if (hashBytes[i + 16] != computedHash[i])
                            return false;
                    }
                    
                    return true;
                }
                else if (hashBytes.Length == 20)
                {
                    // 纯哈希格式：只有哈希值(20字节)
                    // 这种情况下，我们需要从数据库中获取盐值
                    // 但由于VerifyPassword方法没有盐值参数，我们无法验证这种格式
                    // 返回false表示验证失败
                    return false;
                }
                else
                {
                    // 未知的哈希格式
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }
        
        public bool VerifyPassword(string password, string hash, string salt)
        {
            try
            {
                // 使用提供的盐值计算密码的哈希
                var computedHash = HashPassword(password, salt);
                return hash == computedHash;
            }
            catch
            {
                return false;
            }
        }
    }
}