package sm2

import (
	"bytes"
	"encoding/hex"

	"xdx.jelly/xgcl/internal/tags"
)

func init() {
	// 如果编译时指定了 -tags "gmt0028"，则执行算法正确性检测。
	if tags.Gmt0028 {
		if !(Auditor{}).Correctness() {
			panic("SM2 Correctness check failed")
		}
	}
}

// Auditor 算法正确性检测
type Auditor struct{}

func (a Auditor) Correctness() bool {
	return a.CheckSign() && a.CheckEnc() && a.CheckKeyExchange()
}

func (a Auditor) CheckSign() bool {
	var signData = struct {
		e   string
		d   string
		pk  string
		sig string
		k   string
	}{
		"F0B43E94BA45ACCAACE692ED534382EB17E6AB5A19CE7B31F4486FDFC0D28640",
		"3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8",
		"09F9DF311E5421A150DD7D161E4BC5C672179FAD1833FC076BB08FF356F35020CCEA490CE26775A52DC6EA718CC1AA600AED05FBF35E084A6632F6072DA9AD13",
		"f5a03b0648d2c4630eeac513e1bb81a15944da3827d5b74143ac7eaceee720b3b1b6aa29df212fd8763182bc0d421ca1bb9038fd1f7f42d4840b69c485bbc1aa",
		"59276E27D506861A16680F3AD9C02DCCEF3CC1FA3CDBE4CE6D54B80DEAC1BC21",
	}

	b, err := hex.DecodeString(signData.d)
	if err != nil {
		return false
	}
	d := NewPrivateKey()
	d.SetBytes(b)

	pk := NewPublicKey()
	b, err = hex.DecodeString(signData.pk)
	if err != nil {
		return false
	}
	pk.SetBytes(b)

	e, err := hex.DecodeString(signData.e)
	if err != nil {
		return false
	}
	k, err := hex.DecodeString(signData.k)
	if err != nil {
		return false
	}
	var sig *Signature
	if sig, err = Sign(e, k, d); err != nil {
		return false
	}

	if b, err = hex.DecodeString(signData.sig); err != nil || bytes.Compare(sig.Bytes(), b) != 0 {
		return false
	}
	return Verify(e, pk, sig)
}

func (a Auditor) CheckEnc() bool {
	var encData = struct {
		d      string
		pk     string
		k      string
		cipher string
		msg    string
	}{
		"81987CC90CF5057C2DCAA75D1FDDCA84B24862F0CAD73C7F67349AE699B92983",
		"A2C0BFFCC4B36A6064F88600C7171A67B293A03E9BBFA3C28EA2DD496D1A6EC701D29EA7C8D2AB9DC85CAA7F9E24A730CAEA8FF3670FAFD6B28D10F9531ECF50",
		"26D6163FA18603EE2F3DE8936544D5DF1255A2DBEBA63AFC0D833EC449D2CB45",
		"BF6CFCB8E6295DC22777376F8385C5D6AADD5E430D11E004246D6BEBF99EC5249CB9AB2F9AF688C77A1BDF9F3B0816A4EAB7F5DA22E5DACDC1C8F6E45499874E1FC32E35744161AA0FFA6C70FC811D3B66D4CACDA3C0996B54768C603C6B24E0C85CDDE8AD71A258B89DDB42DA900BCF4F18AB52D7841134CAC581D3CF7F58F7",
		"C353C68EF05C4B342B377DA055D909FB1FAA4255662F3BAB8DDB3535E40BC93B",
	}

	b, err := hex.DecodeString(encData.d)
	if err != nil {
		return false
	}
	d := NewPrivateKey()
	d.SetBytes(b)

	pk := NewPublicKey()
	b, err = hex.DecodeString(encData.pk)
	if err != nil {
		return false
	}
	pk.SetBytes(b)

	msg, err := hex.DecodeString(encData.msg)
	if err != nil {
		return false
	}
	k, err := hex.DecodeString(encData.k)
	if err != nil {
		return false
	}
	var cipher *Cipher
	b, err = hex.DecodeString(encData.cipher)
	if err != nil {
		return false
	}
	if cipher, err = Encrypt(pk, msg, k); err != nil || bytes.Compare(b, cipher.Bytes()) != 0 {
		return false
	}

	if b, err = Decrypt(d, cipher); err != nil || bytes.Compare(b, msg) != 0 {
		return false
	}
	return true
}

func (a Auditor) CheckKeyExchange() bool {
	var keyExchangeData = struct {
		// d      string
		// pk     string
		// k      string
		// cipher string
		// msg    string
	}{
		// "81987CC90CF5057C2DCAA75D1FDDCA84B24862F0CAD73C7F67349AE699B92983",
		// "A2C0BFFCC4B36A6064F88600C7171A67B293A03E9BBFA3C28EA2DD496D1A6EC701D29EA7C8D2AB9DC85CAA7F9E24A730CAEA8FF3670FAFD6B28D10F9531ECF50",
		// "26D6163FA18603EE2F3DE8936544D5DF1255A2DBEBA63AFC0D833EC449D2CB45",
		// "BF6CFCB8E6295DC22777376F8385C5D6AADD5E430D11E004246D6BEBF99EC5249CB9AB2F9AF688C77A1BDF9F3B0816A4EAB7F5DA22E5DACDC1C8F6E45499874E1FC32E35744161AA0FFA6C70FC811D3B66D4CACDA3C0996B54768C603C6B24E0C85CDDE8AD71A258B89DDB42DA900BCF4F18AB52D7841134CAC581D3CF7F58F7",
		// "C353C68EF05C4B342B377DA055D909FB1FAA4255662F3BAB8DDB3535E40BC93B",
	}

	_ = keyExchangeData
	return true
}
