package com.xy.xyaicpzs.util;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * JWT工具类，用于生成和验证JWT令牌
 */
@Component
public class JwtUtil {
    
    private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);
    
    private static final String COZE_APP_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" +
            "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7ZkUY3DNf0wf0\n" +
            "K4MX9oytqYl2HFfZ8O5qZvN/MaLcyojzios97DZba9kj0ZBkhQNAZe5IZkBZ1Vud\n" +
            "sQu3sxXHW1YEazDqMDEm8x8QspCXniiNUb9RX3kk+vxIczqXhn/xxAIcR1jnq2Pr\n" +
            "Pt0j8kKr9FjhS1xuKEzBhU2YGJfMzN/ARqr7Q9zw5ONYjU8s6ejkUw240m/TvyMl\n" +
            "eSBNkqLfWM8o7CMPCcvAnvGw7n7lpxQ8EQV4J5rfjl02cW5wZHLEtOEGlcQsx1KF\n" +
            "gukcRkpGi6M7ifAENtqUrqZXghq7BlVRDDk3gXLP++fyOklL57eyhdKaY/bIlsXn\n" +
            "N9WQc/YJAgMBAAECggEAEvH8Y06DrRjXEYLCno4Q28+rc3LbGM/oMn6U+FNqzRp2\n" +
            "rPRhLlHujuCA08OwbtEZqo2DgPNBZzOQLwmCj0A+H+jmcczqZYqYtYDXr6b1wjY9\n" +
            "kEfm6RGXXDs5fROVJVN2JNl1gyldXhJwKAyza5pmzh6GS8SEJCjT1a6l0Q4PbqdN\n" +
            "XIKJzwXKZO0LCqlA3mQV5liEDe5XQM3ygkdYgLFvl+lUHws9TfCxpvKgn87b3OmT\n" +
            "9k9bbWN1TOfP64Fhdwho2hoH0G7jiYjvm1fUuMxX0cYjIAmcuwokj9l/aTBBzc8+\n" +
            "XT1zGxZ1ewSd0Xuc9+Xn+lKCScgSkbpzMZcQ5Eka3wKBgQDgrXIpI59V1U5jYiNn\n" +
            "WX0G+8/UyraNxzv3rl+cJX43bvAN9KYgCq6qnJBdFDPF3Z9jEIU3LE06fz1gxrN4\n" +
            "NbdM2GpnBQJ/wkMM5EG+0Zec01n5PZdES6NWbA5AZlRmsAxE71L2OOwbj0gVnyAj\n" +
            "w5f9m44YaL2ZWpLbY93XKmEWzwKBgQDVhmbqdDjEl7xxt2H7xvJjCoSPLGruMfIH\n" +
            "94o7xAIYCyjnNc4aTyQawo+cfzq+wjtRbZEvz4S6CtfrNfJHlgrLEF1V4WaaKHcN\n" +
            "V43IdC18H4/8F502D4SZCwvhdmXdYjOcBbGZD3w5HZOBuH4RYcspplsj4Ot+w2Lz\n" +
            "YQy8kHXbpwKBgHYZleWcDPggTLke7/82YesW2FNBTx5NeO8joKxCZQscbGDZla1I\n" +
            "EDIsZBIZOXGrokl/eJbc2aeDFK9XIyVwDu7830lRr9OaOIaBQTHdmDVeP3As+ON0\n" +
            "YuJdoEwnvfvQVFKz/kbg+vMtqLV81HcYLD+p0dJw1CDVJFbgMs8UPr6vAoGBAK+2\n" +
            "MXzgdVK6dzWxLi3OMurz3dAgQkKP0VdjCltSWlLE5D0YVunplJF86Edln8cY+U1x\n" +
            "99c7U0Lx52tE8oKcY3dlmRkyKofTotzU3vVFPaT2KDvQhuvU604x++3my77ZsBTF\n" +
            "zrdhOd2ajCdk1kGhk1lL75Zf4gtn6EbV53BJBOPjAoGASVU6chk0zAEg7c9xOjCd\n" +
            "uFlGeNqfiTJGL6aHHaaJN3EhCeWc36l4NGJ/JwWCm0ETydzYAtcUaj2biUAlEm0Q\n" +
            "s1Vgl2ulxkpw32IclM0oND1VdJfwZRzcl4OO9jyF+993icaY+dAtZ9U37Jk9QazY\n" +
            "L+Cmvmq59YO4yS9+WeBEGV8=\n" +
            "-----END PRIVATE KEY-----";
    
    private static final String COZE_APP_ID = "1102723433113";
    private static final String COZE_APP_FINGERPRINT = "WNHPUWKXL_PDNeynptov7GsiwW1eqgPP-2OfCIFlEc0";
    private static final String COZE_API_ENDPOINT = "api.coze.cn";
    
    /**
     * 生成JWT令牌
     * 
     * @param expireSeconds 过期时间（秒）
     * @param sessionName 会话名称（可选）
     * @param deviceId 设备ID（可选）
     * @return JWT令牌字符串
     */
    public String generateToken(int expireSeconds, String sessionName, String deviceId) {
        try {
            // 当前时间戳（秒）
            long currentTimeSeconds = Instant.now().getEpochSecond();
            
            // 构建Header
            Map<String, Object> headers = new HashMap<>();
            headers.put("alg", "RS256"); // 固定为RS256
            headers.put("typ", "JWT"); // 固定为JWT
            headers.put("kid", COZE_APP_FINGERPRINT); // OAuth应用的公钥指纹
            
            // 构建Payload
            Map<String, Object> claims = new HashMap<>();
            claims.put("iss", COZE_APP_ID); // OAuth应用的ID
            claims.put("aud", COZE_API_ENDPOINT); // 扣子API的Endpoint
            claims.put("iat", currentTimeSeconds); // JWT开始生效的时间
            claims.put("exp", currentTimeSeconds + expireSeconds); // JWT过期的时间
            claims.put("jti", UUID.randomUUID().toString()); // 随机字符串，防止重放攻击
            
            // 可选参数
            if (sessionName != null && !sessionName.isEmpty()) {
                claims.put("session_name", sessionName);
            }
            
            // 如果提供了设备ID，则添加设备信息
            if (deviceId != null && !deviceId.isEmpty()) {
                Map<String, Object> sessionContext = new HashMap<>();
                Map<String, Object> deviceInfo = new HashMap<>();
                deviceInfo.put("device_id", deviceId);
                sessionContext.put("device_info", deviceInfo);
                claims.put("session_context", sessionContext);
            }
            
            // 从私钥字符串中获取PrivateKey对象
            PrivateKey privateKey = getPrivateKeyFromString(COZE_APP_PRIVATE_KEY);
            
            // 生成JWT
            return Jwts.builder()
                    .setHeader(headers)
                    .setClaims(claims)
                    .signWith(privateKey, SignatureAlgorithm.RS256)
                    .compact();
        } catch (Exception e) {
            logger.error("JWT生成失败", e);
            throw new RuntimeException("JWT生成失败: " + e.getMessage());
        }
    }
    
    /**
     * 从字符串中获取PrivateKey对象
     * 
     * @param privateKeyStr 私钥字符串（PEM格式）
     * @return PrivateKey对象
     */
    private PrivateKey getPrivateKeyFromString(String privateKeyStr) throws Exception {
        // 去除PEM格式的头尾和换行符
        String privateKeyPEM = privateKeyStr
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s", "");
        
        // Base64解码
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyPEM);
        
        // 生成PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        
        // 获取KeyFactory实例
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        
        // 生成PrivateKey对象
        return keyFactory.generatePrivate(keySpec);
    }
} 