using System;
using System.Security.Cryptography;
using System.Text;

namespace KeycloakDemo
{
    /// <summary>
    /// PKCE (Proof Key for Code Exchange) 辅助类
    /// 用于生成 code_verifier 和 code_challenge
    /// </summary>
    public class PkceHelper
    {
        /// <summary>
        /// code_verifier - PKCE 私钥，保存在内存中，用于换取 Token
        /// </summary>
        public string CodeVerifier { get; private set; }

        /// <summary>
        /// code_challenge - PKCE 公钥，发送给 Keycloak
        /// </summary>
        public string CodeChallenge { get; private set; }

        /// <summary>
        /// code_challenge_method - 固定为 S256
        /// </summary>
        public string CodeChallengeMethod => "S256";

        /// <summary>
        /// 生成 PKCE 密钥对
        /// </summary>
        public static PkceHelper Generate()
        {
            var helper = new PkceHelper();
            
            // 生成 32 字节随机数，并进行 Base64URL 编码
            // 结果是 43 字符的 code_verifier
            var randomBytes = new byte[32];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(randomBytes);
            }
            helper.CodeVerifier = Base64UrlEncode(randomBytes);

            // 计算 SHA256 哈希，并进行 Base64URL 编码
            using (var sha256 = SHA256.Create())
            {
                var hash = sha256.ComputeHash(Encoding.ASCII.GetBytes(helper.CodeVerifier));
                helper.CodeChallenge = Base64UrlEncode(hash);
            }

            return helper;
        }

        /// <summary>
        /// Base64URL 编码（符合 RFC 4648）
        /// </summary>
        private static string Base64UrlEncode(byte[] bytes)
        {
            return Convert.ToBase64String(bytes)
                .TrimEnd('=')           // 移除填充
                .Replace('+', '-')      // + 替换为 -
                .Replace('/', '_');     // / 替换为 _
        }
    }
}
