using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using SkyArtShop.Models;

namespace SkyArtShop.Services;

public class PostgreAuthService
{
	private readonly PostgreSQLService _pgService;

	public PostgreAuthService(PostgreSQLService pgService)
	{
		_pgService = pgService;
	}

	public string HashPassword(string password)
	{
		using RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
		byte[] array = new byte[16];
		randomNumberGenerator.GetBytes(array);
		using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, array, 10000, HashAlgorithmName.SHA256);
		byte[] bytes = rfc2898DeriveBytes.GetBytes(32);
		byte[] array2 = new byte[48];
		Array.Copy(array, 0, array2, 0, 16);
		Array.Copy(bytes, 0, array2, 16, 32);
		return Convert.ToBase64String(array2);
	}

	public bool VerifyPassword(string password, string hashedPassword)
	{
		try
		{
			if (hashedPassword.Contains(':'))
			{
				string[] array = hashedPassword.Split(':');
				if (array.Length != 3)
				{
					return false;
				}
				int iterations = int.Parse(array[0]);
				byte[] salt = Convert.FromBase64String(array[1]);
				byte[] array2 = Convert.FromBase64String(array[2]);
				byte[] array3 = Rfc2898DeriveBytes.Pbkdf2(Encoding.UTF8.GetBytes(password), salt, iterations, HashAlgorithmName.SHA256, array2.Length);
				return CryptographicOperations.FixedTimeEquals(array2, array3);
			}
			byte[] array4 = Convert.FromBase64String(hashedPassword);
			byte[] array5 = new byte[16];
			Array.Copy(array4, 0, array5, 0, 16);
			using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, array5, 10000, HashAlgorithmName.SHA256);
			byte[] bytes = rfc2898DeriveBytes.GetBytes(32);
			for (int i = 0; i < 32; i++)
			{
				if (array4[i + 16] != bytes[i])
				{
					return false;
				}
			}
			return true;
		}
		catch
		{
			return false;
		}
	}

	public async Task<AdminUser?> AuthenticateAsync(string email, string password)
	{
		AdminUser user = await _pgService.GetUserByEmailAsync(email);
		if (user == null || !VerifyPassword(password, user.PasswordHash))
		{
			return null;
		}
		await _pgService.UpdateUserLastLoginAsync(user.Id, DateTime.UtcNow);
		user.LastLogin = DateTime.UtcNow;
		return user;
	}

	public ClaimsPrincipal CreateClaimsPrincipal(AdminUser user)
	{
		List<Claim> list = new List<Claim>
		{
			new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", user.Id),
			new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", user.Email),
			new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", user.Name),
			new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", user.Role)
		};
		foreach (string permission in user.Permissions)
		{
			list.Add(new Claim("Permission", permission));
		}
		ClaimsIdentity identity = new ClaimsIdentity(list, "Cookies");
		return new ClaimsPrincipal(identity);
	}

	public async Task<AdminUser?> GetUserByEmailAsync(string email)
	{
		return await _pgService.GetUserByEmailAsync(email);
	}

	public async Task<AdminUser> CreateUserAsync(string email, string password, string name, string role = "Admin")
	{
		AdminUser user = new AdminUser
		{
			Id = Guid.NewGuid().ToString(),
			Email = email,
			PasswordHash = HashPassword(password),
			Name = name,
			Role = role,
			IsActive = true,
			CreatedAt = DateTime.UtcNow,
			Permissions = new List<string>()
		};
		await _pgService.CreateAdminUserAsync(user);
		return user;
	}
}
