using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
using Fantasy.Entitas.Interface;
using Microsoft.IdentityModel.Tokens;
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.

namespace NB.Gate;

public sealed class GateJWTComponentAwakeSystem : AwakeSystem<GateJWTComponent>
{
    protected override void Awake(GateJWTComponent self)
    {
        self.Awake();
    }
}

public static class GateJWTComponentSystem
{
    public static void Awake(this GateJWTComponent self)
    {
        var rsa = RSA.Create();
        rsa.ImportRSAPublicKey(Convert.FromBase64String(self.PublicKeyPem), out _);
        self.SigningCredentials = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256);
        // 创建 TokenValidationParameters 对象，用于配置验证参数
        self.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateLifetime = false, // 禁止令牌验证时间是否过期
            ValidateIssuer = true, // 验证发行者
            ValidateAudience = true, // 验证受众
            ValidateIssuerSigningKey = true, // 验证签名密钥
            ValidIssuer = "NoBug", // 有效的发行者
            ValidAudience = "NoBug", // 有效的受众
            IssuerSigningKey = new RsaSecurityKey(rsa) // RSA公钥作为签名密钥
        };
    }

    public static bool ValidateToken(this GateJWTComponent self, string token, out JwtPayload payload)
    {
        payload = null;

        try
        {
            var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
            jwtSecurityTokenHandler.ValidateToken(token, self.TokenValidationParameters, out _);
            payload = jwtSecurityTokenHandler.ReadJwtToken(token).Payload;
            return true;
        }
        catch (SecurityTokenInvalidAudienceException)
        {
            Console.WriteLine("验证受众失败！");
            return false;
        }
        catch (SecurityTokenInvalidIssuerException)
        {
            Console.WriteLine("验证发行者失败！");
            return false;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }
}