using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using ZhiZhun.AuthenticationCenter.User;

namespace ZhiZhun.AuthenticationCenter.Utility
{
    /// <summary>
    /// 对称可逆加密
    /// </summary>
    public class JWTHSService : IJWTService
    {
        private static Dictionary<string, UserBasicInfo> TokenCache = new Dictionary<string, UserBasicInfo>();

        #region Option注入
        private readonly JWTTokenOptions _JWTTokenOptions;
        public JWTHSService(IOptionsMonitor<JWTTokenOptions> jwtTokenOptions)
        {
            this._JWTTokenOptions = jwtTokenOptions.CurrentValue;
        }
        #endregion

        public string GetToken(UserBasicInfo userModel)
        {
            return this.IssueToken(userModel);
        }

        /// <summary>
        /// 刷新token的有效期问题上端校验
        /// </summary>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        public string GetTokenByRefresh(string refreshToken)
        {
            if (TokenCache.ContainsKey(refreshToken))
            {
                string token = this.IssueToken(TokenCache[refreshToken], 60);
                return token;
            }
            else
            {
                return "";
            }
        }

        /// <summary>
        /// 2个token  就是有效期不一样
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public Tuple<string, string> GetTokenWithRefresh(UserBasicInfo userInfo)
        {
            string token = this.IssueToken(userInfo, 60);//1分钟
            string refreshToken = this.IssueToken(userInfo, 60 * 60 * 24);//24小时
            TokenCache.Add(refreshToken, userInfo);

            return Tuple.Create(token, refreshToken);
        }

        /**
            * Claims (Payload)
               Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段，下面节选一些字段:
               iss: The issuer of the token，token 是给谁的
               sub: The subject of the token，token 主题
               exp: Expiration Time。 token 过期时间，Unix 时间戳格式
               iat: Issued At。 token 创建时间， Unix 时间戳格式
               jti: JWT ID。针对当前 token 的唯一标识
               除了规定的字段外，可以包含其他任何 JSON 兼容的字段。
            * */
        private string IssueToken(UserBasicInfo user, int second = 600)
        {
            var claims = new[]
            {
                new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim("id", user.Id.ToString()),
                new Claim("name", user.UserName),
                new Claim("realName", user.RealName),
                new Claim("reviewerCode",user.ReviewerCode),
                new Claim("userTypeEnumName",user.UserTypeEnum.ToString()),
                new Claim("userTypeEnumInt",((int)user.UserTypeEnum).ToString()),
                new Claim("userTypeShortName",user.UserTypeShortName),
                new Claim("isAdmin",(user.UserTypeEnum==UserType.SuperAdmin).ToString())
            };
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this._JWTTokenOptions.SecurityKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

           
            var token = new JwtSecurityToken(
                issuer: this._JWTTokenOptions.Issuer,
                audience: this._JWTTokenOptions.Audience,
                claims: claims,
                expires: DateTime.Now.AddSeconds(second),//10分钟有效期
                notBefore: null,//立即生效  DateTime.Now.AddMilliseconds(30),//30s后有效
                signingCredentials: creds);
            string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
            return returnToken;
        }
    }
}
