package appidentitykeydeclarationv1

import (
	"bytes"
	"testing"
)

func TestCanonicalBehaviorRoundTrip(t *testing.T) {
	raw, err := CanonicalBehaviorBytes(Behavior{SchemaVersion: BehaviorSchemaVersion})
	if err != nil {
		t.Fatal(err)
	}
	if string(raw) != `{"schema_version":"nexuscrm.app-identity-key-declaration/v1"}` {
		t.Fatalf("canonical behavior = %s", raw)
	}
	parsed, err := ParseCanonicalBehavior(raw)
	if err != nil {
		t.Fatal(err)
	}
	reproduced, err := CanonicalBehaviorBytes(parsed)
	if err != nil || !bytes.Equal(reproduced, raw) {
		t.Fatalf("reproduced behavior = %q, %v", reproduced, err)
	}
}

func TestParseCanonicalBehaviorRejectsOpenOrNonCanonicalInput(t *testing.T) {
	canonical, err := CanonicalBehaviorBytes(Behavior{SchemaVersion: BehaviorSchemaVersion})
	if err != nil {
		t.Fatal(err)
	}
	duplicate := []byte(`{"schema_version":"nexuscrm.app-identity-key-declaration/v1","schema_version":"nexuscrm.app-identity-key-declaration/v1"}`)
	escaped := []byte(`{"schema_version":"nexuscrm.app-identity-key-declaration\/v1"}`)
	for name, raw := range map[string][]byte{
		"leading whitespace":  append([]byte(" "), canonical...),
		"trailing whitespace": append(append([]byte(nil), canonical...), '\n'),
		"trailing JSON":       append(append([]byte(nil), canonical...), []byte(` true`)...),
		"duplicate":           duplicate,
		"escaped ASCII":       escaped,
		"unknown":             []byte(`{"schema_version":"nexuscrm.app-identity-key-declaration/v1","z":"x"}`),
		"missing":             []byte(`{}`),
		"null":                []byte(`{"schema_version":null}`),
		"non-string":          []byte(`{"schema_version":1}`),
		"array":               []byte(`[]`),
		"invalid UTF-8":       append(append([]byte(nil), canonical...), 0xff),
	} {
		t.Run(name, func(t *testing.T) {
			if _, err := ParseCanonicalBehavior(raw); err == nil {
				t.Fatalf("ParseCanonicalBehavior(%q) succeeded", raw)
			}
		})
	}
}

func TestCanonicalBehaviorRejectsWrongSchema(t *testing.T) {
	if _, err := CanonicalBehaviorBytes(Behavior{SchemaVersion: "v1"}); err == nil {
		t.Fatal("CanonicalBehaviorBytes accepted unsupported schema")
	}
}
