package wechat

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha1"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
)

// DecryptedUserInfo 解密后的用户信息结构
type DecryptedUserInfo struct {
	OpenID    string    `json:"openId"`
	NickName  string    `json:"nickName"`
	Gender    int       `json:"gender"`
	City      string    `json:"city"`
	Province  string    `json:"province"`
	Country   string    `json:"country"`
	AvatarURL string    `json:"avatarUrl"`
	UnionID   string    `json:"unionId,omitempty"`
	Watermark Watermark `json:"watermark"`
}

// Watermark 数据水印
type Watermark struct {
	AppID     string `json:"appid"`
	Timestamp int64  `json:"timestamp"`
}

// DecryptData 解密微信小程序加密数据
// sessionKey: 会话密钥（从 code2session 接口获取）
// encryptedData: 加密数据（Base64 编码）
// iv: 初始向量（Base64 编码）
// 返回解密后的 JSON 字符串
func DecryptData(sessionKey, encryptedData, iv string) (string, error) {
	// 1. Base64 解码 session_key
	aesKey, err := base64.StdEncoding.DecodeString(sessionKey)
	if err != nil {
		return "", fmt.Errorf("session_key base64 解码失败: %v", err)
	}

	// 2. Base64 解码加密数据
	cipherText, err := base64.StdEncoding.DecodeString(encryptedData)
	if err != nil {
		return "", fmt.Errorf("encryptedData base64 解码失败: %v", err)
	}

	// 3. Base64 解码初始向量
	ivBytes, err := base64.StdEncoding.DecodeString(iv)
	if err != nil {
		return "", fmt.Errorf("iv base64 解码失败: %v", err)
	}

	// 4. 验证密钥长度（AES-128 需要 16 字节）
	if len(aesKey) != 16 {
		return "", fmt.Errorf("session_key 长度错误，期望 16 字节，实际 %d 字节", len(aesKey))
	}

	// 5. 验证 IV 长度（AES 块大小为 16 字节）
	if len(ivBytes) != 16 {
		return "", fmt.Errorf("iv 长度错误，期望 16 字节，实际 %d 字节", len(ivBytes))
	}

	// 6. 验证密文长度（必须是 AES 块大小的倍数）
	if len(cipherText)%aes.BlockSize != 0 {
		return "", fmt.Errorf("密文长度错误，必须是 %d 字节的倍数，实际 %d 字节", aes.BlockSize, len(cipherText))
	}

	// 7. 创建 AES 解密器
	block, err := aes.NewCipher(aesKey)
	if err != nil {
		return "", fmt.Errorf("创建 AES 解密器失败: %v", err)
	}

	// 8. 创建 CBC 模式解密器
	mode := cipher.NewCBCDecrypter(block, ivBytes)

	// 9. 解密数据
	decrypted := make([]byte, len(cipherText))
	mode.CryptBlocks(decrypted, cipherText)

	// 10. 去除 PKCS#7 填充
	decrypted, err = pkcs7Unpad(decrypted)
	if err != nil {
		return "", fmt.Errorf("去除填充失败: %v", err)
	}

	return string(decrypted), nil
}

// DecryptUserInfo 解密用户信息并返回结构化数据
func DecryptUserInfo(sessionKey, encryptedData, iv string) (*DecryptedUserInfo, error) {
	decryptedJSON, err := DecryptData(sessionKey, encryptedData, iv)
	if err != nil {
		return nil, err
	}

	var userInfo DecryptedUserInfo
	if err := json.Unmarshal([]byte(decryptedJSON), &userInfo); err != nil {
		return nil, fmt.Errorf("解析用户信息 JSON 失败: %v", err)
	}

	return &userInfo, nil
}

// VerifySignature 验证数据签名
// rawData: 原始数据
// signature: 签名
// sessionKey: 会话密钥
func VerifySignature(rawData, signature, sessionKey string) bool {
	// 计算签名：sha1(rawData + sessionKey)
	h := sha1.New()
	h.Write([]byte(rawData + sessionKey))
	expectedSignature := hex.EncodeToString(h.Sum(nil))

	return expectedSignature == signature
}

// pkcs7Unpad 去除 PKCS#7 填充
func pkcs7Unpad(data []byte) ([]byte, error) {
	if len(data) == 0 {
		return nil, fmt.Errorf("数据为空")
	}

	// 获取填充长度
	padding := int(data[len(data)-1])

	// 验证填充长度
	if padding > len(data) || padding == 0 {
		return nil, fmt.Errorf("无效的填充长度: %d", padding)
	}

	// 验证填充字节
	for i := len(data) - padding; i < len(data); i++ {
		if data[i] != byte(padding) {
			return nil, fmt.Errorf("无效的填充字节")
		}
	}

	return data[:len(data)-padding], nil
}
