package utils

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"errors"
	"fmt"

	"golang.org/x/crypto/bcrypt"
)

const (
	privateKeyText = "MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A=="
)

// privateKeyText: Base64编码的PKCS#8格式RSA私钥字符串
// text: Base64编码的密文字符串
func DecryptByPrivateKey(text string) (string, error) {
	// 1. Base64解码私钥文本
	privateKeyBytes, err := base64.StdEncoding.DecodeString(privateKeyText)
	if err != nil {
		return "", fmt.Errorf("私钥Base64解码失败: %w", err)
	}

	// 2. 解析PKCS#8格式的私钥（对应Java的PKCS8EncodedKeySpec）
	key, err := x509.ParsePKCS8PrivateKey(privateKeyBytes)
	if err != nil {
		return "", fmt.Errorf("解析PKCS#8私钥失败: %w", err)
	}

	// 3. 断言为RSA私钥
	privateKey, ok := key.(*rsa.PrivateKey)
	if !ok {
		return "", errors.New("私钥类型不是RSA")
	}

	// 4. Base64解密密文
	cipherText, err := base64.StdEncoding.DecodeString(text)
	if err != nil {
		return "", fmt.Errorf("密文Base64解码失败: %w", err)
	}

	// 5. RSA解密（Java默认是RSA/ECB/PKCS1Padding，对应Go的PKCS1v15填充）
	plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText)
	if err != nil {
		return "", fmt.Errorf("RSA解密失败: %w", err)
	}

	// 6. 转换为字符串返回
	return string(plainText), nil
}

// EncodePassword 等价于Java的passwordEncoder.encode()，返回哈希后的密码字符串
func EncodePassword(rawPassword string) (string, error) {
	// 生成盐值（cost取值4-31，值越高加密越慢越安全，默认10，与Java BCryptPasswordEncoder一致）
	salt, err := bcrypt.GenerateFromPassword([]byte(rawPassword), bcrypt.DefaultCost)
	if err != nil {
		return "", fmt.Errorf("encode password failed: %w", err)
	}
	return string(salt), nil
}

// VerifyPassword 等价于Java的passwordEncoder.matches()，验证密码是否匹配
func VerifyPassword(rawPassword, encodedPassword string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(encodedPassword), []byte(rawPassword))
	return err == nil
}
