using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Threading.Tasks;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
using System.Collections.Generic;
using System.Text;

namespace TEAMModelOS.SDK.Extension
{
    public static class JwtAuthExtension
    {
        public static string CreateAuthToken(string issuer, string id,string name,string picture, string salt, string schoolID = "", string[] roles = null, string[] permissions = null, int expire = 1)
        {
            // 設定要加入到 JWT Token 中的聲明資訊(Claims)  
            var payload = new JwtPayload {
                { JwtRegisteredClaimNames.Iss, issuer }, //發行者
                { JwtRegisteredClaimNames.Sub, id }, // 用戶ID                  
                { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼，如果有的話
                { JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()},  // 到期的時間，必須為數字
                { "name",name}, // 用戶的顯示名稱
                { "picture",picture}, // 用戶頭像
                { "roles",roles}, // 登入者的角色，角色類型 (Admin、Teacher、Student) 
                { "permissions",permissions} //登入者的權限請求
            };

            // 建立一組對稱式加密的金鑰，主要用於 JWT 簽章之用
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
            // HmacSha256 有要求必須要大於 128 bits，所以 salt 不能太短，至少要 16 字元以上
            // https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater
            var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
            var header = new JwtHeader(signingCredentials);
            var secToken = new JwtSecurityToken(header, payload);
            // 產出所需要的 JWT securityToken 物件，並取得序列化後的 Token 結果(字串格式)
            var tokenHandler = new JwtSecurityTokenHandler();
            //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
            var serializeToken = tokenHandler.WriteToken(secToken);

            return serializeToken;
        }
        public static string CreateApiToken(string issuer, string id,  string salt,string  name,List<int> auth , string schoolID = "", int expire = 1)
        {
           
            // 設定要加入到 JWT Token 中的聲明資訊(Claims)  
            var payload = new JwtPayload {
                { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
                { JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
                { JwtRegisteredClaimNames.Aud, "" }, // aud: 接收jwt的一方
                { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼，如果有的話
                {JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString() },
                { "name",name}, // 用戶的顯示名稱
                //{ JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()},  // 到期的時間，必須為數字
                //{ "name",name}, // 用戶的顯示名稱
                //{ "picture",picture}, // 用戶頭像
                { "auth",auth}, // 登入者的角色，角色類型 (Admin、Teacher、Student) 
               // { "permissions",permissions} //登入者的權限請求
            };

            // 建立一組對稱式加密的金鑰，主要用於 JWT 簽章之用
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
            // HmacSha256 有要求必須要大於 128 bits，所以 salt 不能太短，至少要 16 字元以上
            // https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater
            var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
            var header = new JwtHeader(signingCredentials);
            var secToken = new JwtSecurityToken(header, payload);
            // 產出所需要的 JWT securityToken 物件，並取得序列化後的 Token 結果(字串格式)
            var tokenHandler = new JwtSecurityTokenHandler();
            //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
            var serializeToken = tokenHandler.WriteToken(secToken);

            return serializeToken;
        }
        public static bool ValidateApiToken(string token, string salt)
        {
            try
            {
                var handler = new JwtSecurityTokenHandler();
                var validationParameters = new TokenValidationParameters
                {
                    RequireExpirationTime = true,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
                    //ValidateLifetime = false,
                    //LifetimeValidator = LifetimeValidator,
                    ClockSkew = TimeSpan.Zero
                };
                ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
                return true;
            }
            catch (Exception)
            {
                //Trace.WriteLine(ex.Message);
                return false;
            }
        }
        public static bool ValidateAuthToken(string token, string salt)
        {
            try
            {
                var handler = new JwtSecurityTokenHandler();
                var validationParameters = new TokenValidationParameters
                {
                    RequireExpirationTime = true,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
                    ValidateLifetime = false,
                    //LifetimeValidator = LifetimeValidator,
                    ClockSkew = TimeSpan.Zero
                };
                ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
                return true;
            }
            catch (Exception)
            {
                //Trace.WriteLine(ex.Message);
                return false;
            }
        }
    }
}
