package flowcommandv1

import (
	"bytes"
	"testing"
)

func TestPayloadCanonicalRoundTrip(t *testing.T) {
	payload := Payload{
		DefinitionRef:     "flow.neutral",
		DefinitionVersion: "flow-version-7",
		CanonicalInputs:   []byte(`{"record":{"id":"001"},"retry":false}`),
	}
	raw, err := Encode(payload)
	if err != nil {
		t.Fatalf("Encode: %v", err)
	}
	want := []byte(
		`{"canonicalInputs":{"record":{"id":"001"},"retry":false},"definitionRef":"flow.neutral","definitionVersion":"flow-version-7"}`,
	)
	if !bytes.Equal(raw, want) {
		t.Fatalf("payload = %s, want %s", raw, want)
	}
	decoded, err := Decode(raw)
	if err != nil {
		t.Fatalf("Decode: %v", err)
	}
	if decoded.DefinitionRef != payload.DefinitionRef ||
		decoded.DefinitionVersion != payload.DefinitionVersion ||
		!bytes.Equal(decoded.CanonicalInputs, payload.CanonicalInputs) {
		t.Fatalf("decoded = %#v, want %#v", decoded, payload)
	}
}

func TestPayloadCanonicalArrayInputsRoundTrip(t *testing.T) {
	payload := Payload{
		DefinitionRef:     "flow.neutral",
		DefinitionVersion: "flow-version-7",
		CanonicalInputs:   []byte(`[{"id":"001"},{"id":"002"}]`),
	}
	raw, err := Encode(payload)
	if err != nil {
		t.Fatalf("Encode: %v", err)
	}
	decoded, err := Decode(raw)
	if err != nil {
		t.Fatalf("Decode: %v", err)
	}
	if !bytes.Equal(decoded.CanonicalInputs, payload.CanonicalInputs) {
		t.Fatalf(
			"decoded CanonicalInputs = %s, want %s",
			decoded.CanonicalInputs,
			payload.CanonicalInputs,
		)
	}
}

func TestPayloadFailsClosed(t *testing.T) {
	for name, raw := range map[string][]byte{
		"non canonical":   []byte(`{"definitionRef":"flow","definitionVersion":"v1","canonicalInputs":{"b":1,"a":2}}`),
		"unknown field":   []byte(`{"canonicalInputs":{},"definitionRef":"flow","definitionVersion":"v1","extra":true}`),
		"duplicate field": []byte(`{"canonicalInputs":{},"definitionRef":"flow","definitionRef":"other","definitionVersion":"v1"}`),
		"scalar inputs":   []byte(`{"canonicalInputs":1,"definitionRef":"flow","definitionVersion":"v1"}`),
		"blank ref":       []byte(`{"canonicalInputs":{},"definitionRef":"","definitionVersion":"v1"}`),
		"case variant":    []byte(`{"CanonicalInputs":{},"DefinitionRef":"flow","DefinitionVersion":"v1"}`),
		"trailing":        []byte(`{"canonicalInputs":{},"definitionRef":"flow","definitionVersion":"v1"} {}`),
	} {
		t.Run(name, func(t *testing.T) {
			if _, err := Decode(raw); err == nil {
				t.Fatal("Decode succeeded")
			}
		})
	}
}
