using System.Security.Cryptography;
using System.Text;
using AyCode.Core.Consts;
using AyCode.Core.Extensions;
using AyCode.Utils.Extensions;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;

namespace AyCode.Core.Helpers
{
    public class PasswordHasher
    {
        public static string HashPassword(string? password, string? dynamicSalt = null)
        {
            if (string.IsNullOrWhiteSpace(password)) throw new ArgumentNullException(nameof(password));

            // Generate a random salt
            var salt = new byte[16];
            using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(salt);

            // Hash the password with the salt
            var hashedPassword = GenerateHashedPassword(password, salt, dynamicSalt);

            // Combine the salt and hashed password
            var combinedHash = $"$bcrypt$v=1$salt={Convert.ToBase64String(salt)}$hash={hashedPassword}";

            return combinedHash;
        }

        public static bool VerifyPassword(string? password, string hashedPassword, string? dynamicSalt = null)
        {
            if (string.IsNullOrWhiteSpace(password)) return false;

            // Extract the salt and hashed password from the combined hash
            var parts = hashedPassword.Split('$');
            
            if (parts.Length != 5) return false;

            var salt = Convert.FromBase64String(parts[3].Replace("salt=", string.Empty));
            var storedHash = parts[4].Replace("hash=", string.Empty);

            return storedHash == GenerateHashedPassword(password, salt, dynamicSalt);
        }

        private static string GenerateHashedPassword(string password, byte[] salt, string? dynamicSalt)
            => Convert.ToBase64String(KeyDerivation.Pbkdf2(
                password: password,
                salt: GenerateFinallySalt(salt, dynamicSalt),
                prf: KeyDerivationPrf.HMACSHA512,
                iterationCount: 10000,
                numBytesRequested: 32));

        //SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J.
        public static string GenerateDynamicSalt(Guid userId)
            => userId.ToString("N").ToLower().Reverse().MixCharacters(AcConst.ProjectSalt);

        //SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J.
        private static byte[] GenerateFinallySalt(byte[] salt, string? dynamicSalt)
            => SHA256.HashData(string.IsNullOrWhiteSpace(dynamicSalt) ? salt : Encoding.ASCII.GetBytes(Convert.ToBase64String(salt).Reverse().MixCharacters(dynamicSalt))).Take(16).ToArray();

    }
}


