package sys_config_dict

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"kami/internal/model"
	"kami/utility/cache"

	"github.com/gogf/gf/v2/os/glog"
)

const (
	aesKeyLength = 32 // AES-256 密钥长度（字节）
	aesIVLength  = 16 // AES IV 长度（字节）

	// Redis 中存储 AES 密钥和 IV 的键名
	redisAESKeyName = "aes:encryption:key"
	redisAESIVName  = "aes:encryption:iv"
)

var (
	ErrRedisUnavailable = errors.New("redis service is unavailable")
	ErrAESKeyNotFound   = errors.New("AES key not found in Redis")
	ErrAESIVNotFound    = errors.New("AES IV not found in Redis")
)

// AESEncryptionParams AES 加密参数结构体
type AESEncryptionParams = model.AESEncryptionParams

// GenerateRandomBytes 生成随机字节数组
func generateRandomBytes(length int) ([]byte, error) {
	bytes := make([]byte, length)
	if _, err := rand.Read(bytes); err != nil {
		return nil, err
	}
	return bytes, nil
}

// InitAESKeyAndIV 初始化 AES 密钥和 IV，在应用启动时调用
func (d *sSysConfigDict) InitAESKeyAndIV(ctx context.Context) (err error) {
	cacheService := cache.NewCache()

	// 生成新的密钥
	keyBytes, err := generateRandomBytes(aesKeyLength)
	if err != nil {
		glog.Error(ctx, "生成 AES 密钥失败", err)
		return err
	}

	// 生成新的 IV
	ivBytes, err := generateRandomBytes(aesIVLength)
	if err != nil {
		glog.Error(ctx, "生成 AES IV 失败", err)
		return err
	}

	// 将密钥和 IV 转换为十六进制字符串存储
	keyHex := hex.EncodeToString(keyBytes)
	ivHex := hex.EncodeToString(ivBytes)

	// 存储到 Redis，使用 0 表示永不过期
	if err := cacheService.Set(ctx, redisAESKeyName, keyHex, 0); err != nil {
		glog.Error(ctx, "存储 AES 密钥到 Redis 失败", err)
		return err
	}

	if err := cacheService.Set(ctx, redisAESIVName, ivHex, 0); err != nil {
		glog.Error(ctx, "存储 AES IV 到 Redis 失败", err)
		return err
	}

	glog.Info(ctx, "AES 密钥和 IV 初始化完成")
	return nil
}

// GetAESKey 从 Redis 获取 AES 加密参数（密钥和初始化向量）
func (d *sSysConfigDict) GetAESKey(ctx context.Context) (params *model.AESEncryptionParams, err error) {
	cacheService := cache.NewCache()

	// 获取 AES 密钥
	keyValue, err := cacheService.Get(ctx, redisAESKeyName)
	if err != nil {
		return nil, err
	}

	if keyValue == nil || keyValue.IsNil() {
		return nil, ErrAESKeyNotFound
	}

	// 获取 AES IV
	ivValue, err := cacheService.Get(ctx, redisAESIVName)
	if err != nil {
		return nil, err
	}

	if ivValue == nil || ivValue.IsNil() {
		return nil, ErrAESIVNotFound
	}

	return &model.AESEncryptionParams{
		Key: keyValue.String(),
		IV:  ivValue.String(),
	}, nil
}

// GetAESKeyBytes 从 Redis 获取 AES 加密参数（密钥和初始化向量）
func (d *sSysConfigDict) GetAESKeyBytes(ctx context.Context) (params *model.AESEncryptionParamsBytes, err error) {
	cacheService := cache.NewCache()

	// 获取 AES 密钥
	keyValue, err := cacheService.Get(ctx, redisAESKeyName)
	if err != nil {
		return nil, err
	}

	if keyValue == nil || keyValue.IsNil() {
		return nil, ErrAESKeyNotFound
	}

	// 获取 AES IV
	ivValue, err := cacheService.Get(ctx, redisAESIVName)
	if err != nil {
		return nil, err
	}

	if ivValue == nil || ivValue.IsNil() {
		return nil, ErrAESIVNotFound
	}

	keyValueB, err := hex.DecodeString(keyValue.String())
	if err != nil {
		return nil, err
	}
	ivValueB, err := hex.DecodeString(ivValue.String())
	if err != nil {
		return nil, err
	}
	return &model.AESEncryptionParamsBytes{
		Key: keyValueB,
		IV:  ivValueB,
	}, nil
}
