package cmd_test

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
	"source.quilibrium.com/quilibrium/monorepo/client/cmd"
)

var peerPrivKeyStr = "b14b843edf61a58870d3f96fe7dc8c6d0479af10aa16c45b102ddae75b278e8ef302edca36c71c1b4beb60e88088826c4da71ab0b5bf60cc92fc35078fa499f8a4accd51776ecc1fb520fdb20408133366077dadf4ff8a337fb42a19ff846e3609516a3f61c92ea4b9c2298a64b8bfae3780"
var provingPrivKeyStr = "690a5f08a2b3a0b787a8301c5fded376f7a070f5d89f66bf537d67fa1ed71a2b22ce166733b7d73ccf10a20ef0f04f163aae13883ff8270f93fed723c513e24e7f93d317b3257731887411bf820e169a0180c0cbf625efa67ff54cc22f1d97a2bd3f721705eeb4c2bf022f793954a798f700"

func TestCrossMintRoundtrip(t *testing.T) {
	peerPrivKey, err := hex.DecodeString(peerPrivKeyStr)
	if err != nil {
		t.Fatal(err)
	}
	provingPrivKey, err := hex.DecodeString(provingPrivKeyStr)
	if err != nil {
		t.Fatal(err)
	}
	payloadBytes := make([]byte, 32)
	n, err := rand.Read(payloadBytes)
	if err != nil {
		t.Fatal(err)
	}
	if n != 32 {
		t.Fatal("not enough bytes read")
	}
	payload := hex.EncodeToString(payloadBytes)
	args := &cmd.CrossMintArgs{
		Payload:    payload,
		PeerKey:    peerPrivKey,
		ProvingKey: provingPrivKey,
	}
	result, err := cmd.CrossMint(args)
	if err != nil {
		t.Fatal(err)
	}
	verified, err := cmd.VerifyCrossMint(payload, result)
	assert.True(t, verified, "cross mint verification failed")
	// Switch the public keys to induce failure
	tmp := result.PeerPublicKey
	result.PeerPublicKey = result.ProverPublicKey
	result.ProverPublicKey = tmp
	verified, err = cmd.VerifyCrossMint(payload, result)
	assert.False(t, verified, "cross mint verification should have failed")
}

func TestCrossMint0xHex(t *testing.T) {
	peerPrivKey, err := hex.DecodeString(peerPrivKeyStr)
	if err != nil {
		t.Fatal(err)
	}
	provingPrivKey, err := hex.DecodeString(provingPrivKeyStr)
	if err != nil {
		t.Fatal(err)
	}

	payload := "0x1234"
	args := &cmd.CrossMintArgs{
		Payload:    payload,
		PeerKey:    peerPrivKey,
		ProvingKey: provingPrivKey,
	}
	result, err := cmd.CrossMint(args)
	if err != nil {
		t.Fatal(err)
	}
	verified, err := cmd.VerifyCrossMint(payload, result)
	assert.True(t, verified, "cross mint verification failed")
}

func TestCrossMintFixture(t *testing.T) {
	// Generated by running the `cross-mint` on the config of a newly started node with payload "1234"
	rawJson := `{
	  "peerPublicKey": "LLP/9tYlqIsV8AgTkyIpK9zjN+OfXNmYMDhmDeEagCMAhjfpPPWDyWDq9w6uMl9hGyDKYB10EV0A",
	  "peerSignature": "2ybumA9Vu5rnr5nYPcjehGo/PK6uNl4iVa0WXkEGms5ChqPFgOJX6Z5eng8U6VSHy85zbeZBukiANE3j2EBxrk4TAf4Z+5uuNMCQ6DasKpkgsxuIOGWKhOcBal2CDicinuMqafU3YOrXH9cck/OkjywA",
	  "proverPublicKey": "CAk3inpisW2Bpcar/z5/3dwjRSgFMRbhYhtCWdQThZZqDvOWFGgoMXLyKHw3B4+yEsmYIVaQZ/iA",
	  "proverSignature": "NZb7D2xNbCLlYGMUN1BiwBJL9Z6LbdRiMT1FpltBVpRNuoUNmncN++TWgJD6ngIv+VxEnWB0fhcAfAvrIlwNL0z8Ppur8mGMwedzJIm3pB22nAjUTDvNOvvczZWNbPZPyXcWco8SIC/aVaNmvsg//SgA"
	}`
	// load RawJson into a CrossMintResult
	result := &cmd.CrossMintResult{}
	err := json.Unmarshal([]byte(rawJson), result)
	if err != nil {
		t.Fatal(err)
	}
	ok, err := cmd.VerifyCrossMint("1234", result)
	if err != nil {
		t.Fatal(err)
	}
	assert.True(t, ok, "cross mint verification failed")

	bad, err := cmd.VerifyCrossMint("2234", result)
	if err != nil {
		t.Fatal(err)
	}
	assert.False(t, bad, "cross mint verification succeeded when it should have failed")
}
