using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text.Json;
using FoodsharingSiegen.Contracts.Entity;
using FoodsharingSiegen.Contracts.Helper;
using Microsoft.IdentityModel.Tokens;

namespace FoodsharingSiegen.Shared.Helper
{
    /// <summary>
    /// The auth helper class (a. beging, 04.04.2022)
    /// </summary>
    public static class AuthHelper
    {
        #region Public Method CreateToken

        /// <summary>
        /// Creates the token using the specified user id (a. beging, 04.04.2022)
        /// </summary>
        /// <returns>The string</returns>
        public static string CreateToken(User user)
        {
            var userClone = user.Clone();
            
            userClone.Password = "";
            var serializedUser = JsonSerializer.Serialize(userClone);
            
            var tokenHandler = new JwtSecurityTokenHandler();
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.UserData, serializedUser)
                }),
                Expires = DateTime.UtcNow.AddDays(30),
                Issuer = Issuer,
                Audience = Audience,
                SigningCredentials = new SigningCredentials(Cryptor.GetSigningKey(), SecurityAlgorithms.HmacSha256Signature)
            };
            
            var token = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(token);
        }

        #endregion
        
        #region Public Method ValidateToken

        /// <summary>
        /// Validates the token using the specified token (a. beging, 04.04.2022)
        /// </summary>
        /// <param name="token">The token</param>
        /// <param name="user"></param>
        /// <returns>A task containing the bool</returns>
        public static bool ValidateToken(string? token, out User? user)
        {
            user = null;

            try
            {
                var tokenHandler = new JwtSecurityTokenHandler();
               
                var result = tokenHandler.ValidateTokenAsync(token, new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = Cryptor.GetSigningKey(),

                    ValidateAudience = true,
                    ValidAudience = Audience,

                    ValidateIssuer = true,
                    ValidIssuer = Issuer
                }).Result;

                if (result.Claims.TryGetValue(ClaimTypes.UserData, out var jsonObj) && jsonObj != null)
                {
                    user = JsonSerializer.Deserialize<User>(jsonObj.ToString()!);
                    if (user != null) user.Password = string.Empty;
                }
                
                return result.IsValid;
            }
            catch (Exception)
            {
                return false;
            }
        }

        #endregion


        /// <summary>
        /// The audience
        /// </summary>
        private const string Audience = "FS-Siegen";

        /// <summary>
        /// The issuer
        /// </summary>
        private const string Issuer = "FS-Siegen";
    }
}