using System;
using System.Text;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Signers;

public class TokenGenerator
{
    // 1. 获取当前时间的毫秒级时间戳 A
    public static long GetCurrentTimestamp()
    {
        return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
    }

    // 2. 拼接 B + A 得到 C
    public static string ConcatenateCodeAndTimestamp(string codeB, long timestampA)
    {
        return $"{codeB}{timestampA}";
    }

    // 3. 获取 C 的 UTF-8 字节数组 D
    public static byte[] GetUtf8Bytes(string input)
    {
        return Encoding.UTF8.GetBytes(input);
    }

    // 4. 将 Hex 或 Base64 字符串私钥转换为 ECPrivateKeyParameters
    public static ECPrivateKeyParameters ParsePrivateKey(string privateKeyStr)
    {
        // 假设私钥是 Hex 字符串（如 "ABCD1234..."）
        byte[] privateKeyBytes = HexToBytes(privateKeyStr); // 如果是 Base64，用 Convert.FromBase64String
        // SM2 曲线参数
        var curve = ECNamedCurveTable.GetByName("sm2p256v1");
        var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);

        // 创建私钥
        var privateKey = new ECPrivateKeyParameters(new BigInteger(1, privateKeyBytes), domainParams);
        return privateKey;
    }

    // 5. 使用 SM2 私钥签名 D 得到 E
    public static byte[] SignWithSm2(byte[] data, ECPrivateKeyParameters privateKey)
    {
        var signer = new SM2Signer();
        signer.Init(true, privateKey);
        signer.BlockUpdate(data, 0, data.Length);
        return signer.GenerateSignature();
    }

    // 6. 对 E 进行 Base64 编码得到 F
    public static string Base64Encode(byte[] data)
    {
        return Convert.ToBase64String(data);
    }

    // 7. 组装 Token: {B}.{A}.{F}
    public static string GenerateToken(string codeB, string privateKeyStr)
    {
        // 1. 获取时间戳 A
        long timestampA = GetCurrentTimestamp();

        // 2. 拼接 B + A 得到 C
        string c = ConcatenateCodeAndTimestamp(codeB, timestampA);

        // 3. 获取 UTF-8 字节数组 D
        byte[] d = GetUtf8Bytes(c);

        // 4. 解析私钥字符串
        ECPrivateKeyParameters privateKey = ParsePrivateKey(privateKeyStr);

        // 5. SM2 签名得到 E
        byte[] e = SignWithSm2(d, privateKey);

        // 6. Base64 编码得到 F
        string f = Base64Encode(e);

        // 7. 组装 Token
        return $"{codeB}.{timestampA}.{f}";
    }

    // 辅助方法：Hex 字符串转字节数组
    private static byte[] HexToBytes(string hex)
    {
        if (hex.Length % 2 != 0)
            throw new ArgumentException("Hex 字符串长度必须是偶数");

        byte[] bytes = new byte[hex.Length / 2];
        for (int i = 0; i < bytes.Length; i++)
        {
            bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
        }
        return bytes;
    }
}