package crypto

import (
	"crypto/aes"
	"crypto/md5"
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
)

// ECB模式是一种基本的加密模式，每个明文块独立加密
// 警告：ECB模式存在安全问题，仅用于需要确定性加密的场景，如数据库字段查询
// 不要用于加密大段文本或安全要求高的场景

// 验证密钥长度是否有效 (AES-128, AES-192, AES-256)
func validateAESKey(key []byte) error {
	switch len(key) {
	case 16, 24, 32:
		return nil
	default:
		return errors.New("AES密钥长度必须是16、24或32字节(对应AES-128、AES-192、AES-256)")
	}
}

// AesEcbEncrypt AES-ECB模式加密，返回Base64编码的密文
// 使用已有的ECB实现，但提供更易用的接口
func AesEcbEncrypt(plainText, key []byte) (string, error) {
	if err := validateAESKey(key); err != nil {
		return "", err
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	// 使用PKCS7填充
	plainText = PKCS7Padding(plainText, block.BlockSize())

	// 创建密文数组
	cipherText := make([]byte, len(plainText))

	// ECB模式加密，使用west_crypto.go中已有的实现
	mode := newECBEncrypter(block)
	mode.CryptBlocks(cipherText, plainText)

	// 返回Base64编码的密文
	return base64.StdEncoding.EncodeToString(cipherText), nil
}

// AesEcbDecrypt AES-ECB模式解密，输入Base64编码的密文
func AesEcbDecrypt(cipherTextBase64 string, key []byte) ([]byte, error) {
	if err := validateAESKey(key); err != nil {
		return nil, err
	}

	// Base64解码
	cipherText, err := base64.StdEncoding.DecodeString(cipherTextBase64)
	if err != nil {
		return nil, err
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 检查密文长度
	if len(cipherText)%block.BlockSize() != 0 {
		return nil, errors.New("密文长度必须是块大小的整数倍")
	}

	// 创建明文数组
	plainText := make([]byte, len(cipherText))

	// ECB模式解密，使用west_crypto.go中已有的实现
	mode := newECBDecrypter(block)
	mode.CryptBlocks(plainText, cipherText)

	// 去除PKCS7填充
	plainText, err = PKCS7UnPadding(plainText)
	if err != nil {
		return nil, err
	}

	return plainText, nil
}

// AesEcbEncryptHex AES-ECB模式加密，返回十六进制编码的密文
func AesEcbEncryptHex(plainText, key []byte) (string, error) {
	if err := validateAESKey(key); err != nil {
		return "", err
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	// 使用PKCS7填充
	plainText = PKCS7Padding(plainText, block.BlockSize())

	// 创建密文数组
	cipherText := make([]byte, len(plainText))

	// ECB模式加密
	mode := newECBEncrypter(block)
	mode.CryptBlocks(cipherText, plainText)

	// 返回十六进制编码的密文
	return hex.EncodeToString(cipherText), nil
}

// AesEcbDecryptHex AES-ECB模式解密，输入十六进制编码的密文
func AesEcbDecryptHex(cipherTextHex string, key []byte) ([]byte, error) {
	if err := validateAESKey(key); err != nil {
		return nil, err
	}

	// 十六进制解码
	cipherText, err := hex.DecodeString(cipherTextHex)
	if err != nil {
		return nil, err
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 检查密文长度
	if len(cipherText)%block.BlockSize() != 0 {
		return nil, errors.New("密文长度必须是块大小的整数倍")
	}

	// 创建明文数组
	plainText := make([]byte, len(cipherText))

	// ECB模式解密
	mode := newECBDecrypter(block)
	mode.CryptBlocks(plainText, cipherText)

	// 去除PKCS7填充
	plainText, err = PKCS7UnPadding(plainText)
	if err != nil {
		return nil, err
	}

	return plainText, nil
}

// 以下是专门用于处理手机号等敏感数据的实用函数

// EncryptMobile 使用AES-ECB加密手机号，返回Base64编码
// 该方法保证对相同手机号总是产生相同密文，便于数据库查询
func EncryptMobile(mobile string, secretKey string) (string, error) {
	key, decodeErr := hex.DecodeString(secretKey)
	if decodeErr != nil {
		return "", decodeErr
	}
	if mobile == "" {
		return "", errors.New("手机号不能为空")
	}
	return AesEcbEncrypt([]byte(mobile), key)
}

// DecryptMobile 解密手机号
func DecryptMobile(encryptedMobile string, secretKey string) (string, error) {
	key, decodeErr := hex.DecodeString(secretKey)
	if decodeErr != nil {
		return "", decodeErr
	}
	if encryptedMobile == "" {
		return "", errors.New("加密手机号不能为空")
	}

	bytes, err := AesEcbDecrypt(encryptedMobile, key)
	if err != nil {
		return "", fmt.Errorf("解密手机号失败: %v", err)
	}

	return string(bytes), nil
}

// EncryptMobileHex 使用AES-ECB加密手机号，返回十六进制编码(适用于URL参数)
func EncryptMobileHex(mobile string, key []byte) (string, error) {
	if mobile == "" {
		return "", errors.New("手机号不能为空")
	}
	return AesEcbEncryptHex([]byte(mobile), key)
}

// DecryptMobileHex 解密十六进制编码的手机号
func DecryptMobileHex(encryptedMobileHex string, key []byte) (string, error) {
	if encryptedMobileHex == "" {
		return "", errors.New("加密手机号不能为空")
	}

	bytes, err := AesEcbDecryptHex(encryptedMobileHex, key)
	if err != nil {
		return "", fmt.Errorf("解密手机号失败: %v", err)
	}

	return string(bytes), nil
}

// EncryptIDCard 使用AES-ECB加密身份证号
func EncryptIDCard(idCard string, key []byte) (string, error) {
	if idCard == "" {
		return "", errors.New("身份证号不能为空")
	}
	return AesEcbEncrypt([]byte(idCard), key)
}

// DecryptIDCard 解密身份证号
func DecryptIDCard(encryptedIDCard string, key []byte) (string, error) {
	if encryptedIDCard == "" {
		return "", errors.New("加密身份证号不能为空")
	}

	bytes, err := AesEcbDecrypt(encryptedIDCard, key)
	if err != nil {
		return "", fmt.Errorf("解密身份证号失败: %v", err)
	}

	return string(bytes), nil
}

// IsEncrypted 检查字符串是否为Base64编码的加密数据
func IsEncrypted(data string) bool {
	// 检查是否是有效的Base64编码
	_, err := base64.StdEncoding.DecodeString(data)
	return err == nil && len(data) >= 20 // 至少20个字符的Base64字符串
}

// GenerateAESKey 生成AES密钥
// keySize: 可选16, 24, 32字节(对应AES-128, AES-192, AES-256)
func GenerateAESKey(keySize int) ([]byte, error) {
	if keySize != 16 && keySize != 24 && keySize != 32 {
		return nil, errors.New("密钥长度必须是16、24或32字节")
	}

	key := make([]byte, keySize)
	_, err := rand.Read(key)
	if err != nil {
		return nil, err
	}

	return key, nil
}

// DeriveKeyFromPassword 基于密码派生固定长度的AES密钥
func DeriveKeyFromPassword(password string, keySize int) ([]byte, error) {
	if keySize != 16 && keySize != 24 && keySize != 32 {
		return nil, errors.New("密钥长度必须是16、24或32字节")
	}

	// 使用PBKDF2或简单的方法从密码派生密钥
	// 这里使用简单的MD5方法，实际生产环境应使用更安全的PBKDF2
	hash := md5.New()
	hash.Write([]byte(password))
	key := hash.Sum(nil) // 16字节

	// 如果需要24或32字节，继续哈希
	if keySize > 16 {
		hash.Reset()
		hash.Write(key)
		key = append(key, hash.Sum(nil)[:keySize-16]...)
	}

	return key, nil
}
