package identity

import (
	"encoding/json"
	"reflect"
	"strings"
	"testing"

	"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
)

func TestDeriveIDUsesExactCompactIdentityBytes(t *testing.T) {
	const wantID = "item:sha256:2f211c60b9bdcf3a6dd64086cc4c05df5b3357ae02cb462f7ef8988d9bd2fa4f"
	const wantIdentity = `["dnd.item_registry.identity.v1","silver key"]`

	encoded, err := json.Marshal([]string{Policy, ComparisonKey("Silver Key")})
	if err != nil || string(encoded) != wantIdentity {
		t.Fatalf("identity bytes = %q, %v; want %s", encoded, err, wantIdentity)
	}
	if Policy != "dnd.item_registry.identity.v1" || IdentityPolicy != Policy {
		t.Fatalf("identity policy = %q/%q", Policy, IdentityPolicy)
	}
	if got := DeriveID("  SILVER\u2003KEY "); got != wantID || !IsValidID(got) || got != IDFor("Silver Key") {
		t.Fatalf("DeriveID() = %q, want %q", got, wantID)
	}
	if DeriveID(" \u2003 ") != "" {
		t.Fatal("empty identity produced an ID")
	}
	for _, invalid := range []string{"", "item:sha256:", "item:sha256:ABC", "item:sha256:" + strings.Repeat("0", 63), "item:sha256:" + strings.Repeat("0", 65)} {
		if IsValidID(invalid) {
			t.Fatalf("IsValidID(%q) = true, want false", invalid)
		}
	}
}

func TestValidateRegistryReportsDeterministicIdentityProblemsWithoutMutation(t *testing.T) {
	items := []dnd.Item{
		{ID: DeriveID("Silver Key"), Name: "Silver Key"},
		{ID: DeriveID("Silver Key"), Name: " silver key "},
		{ID: "bad", Name: "Gold Key"},
		{ID: DeriveID("Silver Key"), Name: "Healer's Kit"},
		{ID: "", Name: " "},
	}
	before := append([]dnd.Item(nil), items...)
	issues := ValidateRegistry(items)
	if !reflect.DeepEqual(items, before) {
		t.Fatal("ValidateRegistry() mutated its input")
	}

	want := []IssueCode{
		IssueDuplicateCanonical,
		IssueDuplicateID,
		IssueInvalidID,
		IssueIDMismatch,
		IssueEmptyCanonicalName,
	}
	seen := make(map[IssueCode]bool)
	for _, issue := range issues {
		seen[issue.Code] = true
	}
	for _, code := range want {
		if !seen[code] {
			t.Errorf("ValidateRegistry() issues = %#v, missing %s", issues, code)
		}
	}
}
