/*
* Copyright (c) Akveo 2019. All Rights Reserved.
* Licensed under the Personal / Commercial License.
* See LICENSE_PERSONAL / LICENSE_COMMERCIAL in the project root for license information on type of purchased license.
*/

using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security.DataHandler.Encoder;
using System;
using System.Configuration;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace Common.WebApi
{
    public static class JwtManager
    {
        private static readonly byte[] Secret;
        private static readonly string Issuer;
        private static readonly string Audience;
        private static readonly int ExpirationTime;

        static JwtManager() {
            Issuer = ConfigurationManager.AppSettings["issuer"];
            Audience = ConfigurationManager.AppSettings["audience"];
            Secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["secret"]);
            ExpirationTime = Int32.Parse(ConfigurationManager.AppSettings["expire"]);
        }

        public static string GenerateToken(ClaimsIdentity claims)
        {
            var issued = DateTime.UtcNow;
            var expires = DateTime.UtcNow.AddMinutes(ExpirationTime);
            var signingKey = new SigningCredentials(new SymmetricSecurityKey(Secret), SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(Issuer, Audience, claims.Claims, issued, expires, signingKey);
            var handler = new JwtSecurityTokenHandler();

            var jwt = handler.WriteToken(token);

            return jwt;
        }

        public static ClaimsPrincipal GetPrincipal(string token)
        {
            try
            {
                var tokenHandler = new JwtSecurityTokenHandler();

                if (!(tokenHandler.ReadToken(token) is JwtSecurityToken jwtToken))
                    return null;

                var validationParameters = new TokenValidationParameters
                {
                    RequireExpirationTime = true,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    IssuerSigningKey = new SymmetricSecurityKey(Secret)
                };

                var principal = tokenHandler.ValidateToken(token, validationParameters, out var securityToken);

                return principal;
            }

            catch (Exception)
            {
                return null;
            }
        }
    }
}