package sm2

import (
	"fmt"
	"testing"
	"time"
	"voucher/internal/pkg/cmb/sm2/model"
	"voucher/internal/pkg/cmb/sm2/sdk"
	"voucher/internal/pkg/cmb/sm2/util"
)

var (
	pubHexKey = "04a702106cf530dc981e44cd515b394747cfd6bb059247696b188b25281ea4278fe7c6e34a83680110eec71becd31f5db14abc671e5d8e67ce7ca3c6b3adc86674"
	priHexKey = "9450c673cf801164435b9c164ac1404e87997245bc6f323fde22015875a03f6e"
	enStr     = "BI2O20YuamIpOpXH/RJDtB9gWIpNZPjFbTpbvX45lG8mcma7Cab1yRpE3rcM33oJ8xJ3mbbIvXf/1N507i97eXYQSbLzOBcl/8PyaB4dQ/Ub7QQncN+Npuif4Qp6s11tobdTVOFlz9S9i0VC"
)

func BenchmarkSm2_Encrypt(b *testing.B) {
	for j := 0; j < 1000; j++ {
		for i := 0; i < 300; i++ {
			go func() {
				_, err := NewSm2().
					SetHexPublicKey(pubHexKey).
					SetStringData(`{"name":"zhangxx","phoneNo":"137xxxxxxxx"}`).
					SetSdk(sdk.NewCmbLifeSdk()).
					SetCipherType(model.C1C3C2).
					Encrypt().
					ToBase64String()
				if err != nil {
					//("sm2 encrypt error:", err)
					return
				}
			}()
		}
		time.Sleep(1 * time.Second)
	}

	select {}
}

func BenchmarkSm2_Decrypt(b *testing.B) {
	s, err := util.HexToSignature("abd5a608aad610840bd387263c81f8813e7ab4b121cd69f0d69ac4736cc29978d44c47d9bbf497c712e067c320d3e6b8ef70063da284cc957440e36733f0ff81")
	if err != nil {
		//fmt.Println("hex to signature error: %v", err)
	}

	_, err = NewSm2().
		SetUid([]byte("opv22s05zaezfccc")).
		SetSignature(model.Signature(s)).
		SetHexPublicKey("04c443e81459725ae9979ce44ce8c0e1a45fdf6e884c2fc1e615db02909698b7fdd81fab5404060e2ab849b9e1529397ee4c45ae0d768aebf48d943f953320f78e").
		SetStringData("apiCode=conductor.cashier.queryTransStatus&appId=bolz18v22s05zaezfccc&timestamp=2022070417330581653&version=1.0.0").
		Verify().
		ToBool()
	if err != nil {
		fmt.Println("sm2 verify error:", err)
		return
	}

	//t.Log("sm2 verify result:", verify)
}

func TestSm2_Encrypt(t *testing.T) {
	encrypt, err := NewSm2().
		SetHexPublicKey(pubHexKey).
		SetStringData(`{"name":"zhangxx","phoneNo":"137xxxxxxxx"}`).
		SetSdk(sdk.NewCmbLifeSdk()).
		SetCipherType(model.C1C3C2).
		Encrypt().
		ToBase64String()
	if err != nil {
		t.Error("sm2 encrypt error:", err)
		return
	}
	t.Log("sm2 encrypt result:", encrypt)
}

func TestSm2_Decrypt(t *testing.T) {
	decrypt, err := NewSm2().
		SetHexPrivateKey(priHexKey).
		SetBase64StringData(enStr).
		SetSdk(sdk.NewCmbLifeSdk()).
		SetCipherType(model.C1C3C2).
		Decrypt().
		ToString()
	if err != nil {
		t.Error("sm2 decrypt error:", err)
		return
	}
	t.Log("sm2 decrypt result:", decrypt)
}

func TestSm2_EncryptDecrypt(t *testing.T) {
	n := NewSm2().
		SetHexPublicKey(pubHexKey).
		SetHexPrivateKey(priHexKey).
		SetSdk(sdk.NewCmbLifeSdk()).
		SetCipherType(model.C1C3C2)

	encrypt, err := n.SetStringData(`{"name":"zhangxx","phoneNo":"137xxxxxxxx"}`).Encrypt().ToBase64String()
	if err != nil {
		t.Error("sm2 encrypt error:", err)
		return
	}
	t.Log("sm2 encrypt result:", encrypt)

	decrypt, err := n.SetBase64StringData(encrypt).Decrypt().ToString()
	if err != nil {
		t.Error("sm2 decrypt error:", err)
		return
	}
	t.Log("sm2 decrypt result:", decrypt)
}

func TestSm2_Sign(t *testing.T) {
	sign, err := NewSm2().
		SetUid([]byte("opv22s05zaezfccc")).
		SetHexPrivateKey("beb1c3ed9064052fabe745dac1d71592d16cb0a19abb82e25d9e52799fa85eda").
		SetStringData("a=1").
		Sign().
		ToHexString()
	if err != nil {
		t.Error("sm2 sign error:", err)
		return
	}
	t.Log("sm2 sign result:", sign)
}

func TestSm2_Verify(t *testing.T) {
	s, err := util.HexToSignature("abd5a608aad610840bd387263c81f8813e7ab4b121cd69f0d69ac4736cc29978d44c47d9bbf497c712e067c320d3e6b8ef70063da284cc957440e36733f0ff81")
	if err != nil {
		t.Fatalf("hex to signature error: %v", err)
	}

	verify, err := NewSm2().
		SetUid([]byte("opv22s05zaezfccc")).
		SetSignature(model.Signature(s)).
		SetHexPublicKey("04c443e81459725ae9979ce44ce8c0e1a45fdf6e884c2fc1e615db02909698b7fdd81fab5404060e2ab849b9e1529397ee4c45ae0d768aebf48d943f953320f78e").
		SetStringData("apiCode=conductor.cashier.queryTransStatus&appId=bolz18v22s05zaezfccc&timestamp=2022070417330581653&version=1.0.0").
		Verify().
		ToBool()
	if err != nil {
		t.Error("sm2 verify error:", err)
		return
	}
	t.Log("sm2 verify result:", verify)
}
