package gateway

import (
	"crypto/aes"
	"encoding/base64"
	"strings"
	"testing"
)

func TestAESEncrypt(t *testing.T) {
	tests := []struct {
		name      string
		data      []byte
		appSecret string
		wantErr   bool
	}{
		{
			name:      "正常加密",
			data:      []byte(`{"params":{"cardNo":"898608070422D0010269"}}`),
			appSecret: "BZeQttaZQt0i73moF",
			wantErr:   false,
		},
		{
			name:      "空数据加密",
			data:      []byte(""),
			appSecret: "BZeQttaZQt0i73moF",
			wantErr:   false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			encrypted, err := aesEncrypt(tt.data, tt.appSecret)
			if (err != nil) != tt.wantErr {
				t.Errorf("aesEncrypt() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !tt.wantErr && encrypted == "" {
				t.Error("aesEncrypt() 返回空字符串")
			}
			// 验证 Base64 格式
			if !tt.wantErr {
				_, err := base64.StdEncoding.DecodeString(encrypted)
				if err != nil {
					t.Errorf("aesEncrypt() 返回的不是有效的 Base64: %v", err)
				}
			}
		})
	}
}

func TestGenerateSign(t *testing.T) {
	appID := "60bgt1X8i7AvXqkd"
	encryptedData := "test_encrypted_data"
	timestamp := int64(1704067200)
	appSecret := "BZeQttaZQt0i73moF"

	sign := generateSign(appID, encryptedData, timestamp, appSecret)

	// 验证签名格式（32 位大写十六进制）
	if len(sign) != 32 {
		t.Errorf("签名长度错误: got %d, want 32", len(sign))
	}

	if sign != strings.ToUpper(sign) {
		t.Error("签名应为大写")
	}

	// 验证签名可重现
	sign2 := generateSign(appID, encryptedData, timestamp, appSecret)
	if sign != sign2 {
		t.Error("相同参数应生成相同签名")
	}
}

func TestNewECBEncrypterPanic(t *testing.T) {
	defer func() {
		if recover() == nil {
			t.Fatal("newECBEncrypter 期望触发 panic，但未触发")
		}
	}()

	newECBEncrypter(nil)
}

func TestECBEncrypterCryptBlocksPanic(t *testing.T) {
	block, err := aes.NewCipher(make([]byte, aesBlockSize))
	if err != nil {
		t.Fatalf("创建 AES cipher 失败: %v", err)
	}

	encrypter := newECBEncrypter(block)
	defer func() {
		if recover() == nil {
			t.Fatal("CryptBlocks 期望触发 panic，但未触发")
		}
	}()

	// 传入非完整块长度，触发 panic
	src := []byte("short")
	dst := make([]byte, len(src))
	encrypter.CryptBlocks(dst, src)
}
