package catalogsnapshot

import (
	"bytes"
	"slices"
	"strings"
	"testing"

	"github.com/nexuscrm/shared/pkg/models"
)

func TestEffectiveMetadataRoundTripIsLosslessAndDeterministic(t *testing.T) {
	input := neutralCompileInput()
	input.Objects[0].Metadata.Fields[1].GeneratedForPolymorphicReference = "RelatedTo"
	direct := mustCompile(t, input)

	first, err := BuildEffectiveMetadata(input)
	if err != nil {
		t.Fatal(err)
	}
	reordered := neutralCompileInput()
	reordered.Objects[0].Metadata.Fields[1].GeneratedForPolymorphicReference = "RelatedTo"
	slices.Reverse(reordered.Objects)
	slices.Reverse(reordered.Relationships)
	slices.Reverse(reordered.Definitions)
	slices.Reverse(reordered.Projections)
	for i := range reordered.Objects {
		slices.Reverse(reordered.Objects[i].Metadata.Fields)
	}
	second, err := BuildEffectiveMetadata(reordered)
	if err != nil {
		t.Fatal(err)
	}
	if first.Digest() != second.Digest() || !bytes.Equal(first.Bytes(), second.Bytes()) {
		t.Fatal("equivalent effective metadata did not produce byte-identical canonical input")
	}

	opened, err := OpenEffectiveMetadata(first.Digest(), first.Bytes())
	if err != nil {
		t.Fatal(err)
	}
	compiled, err := CompileEffectiveMetadata(opened)
	if err != nil {
		t.Fatal(err)
	}
	if compiled.Digest() != direct.Digest() || !bytes.Equal(compiled.Bytes(), direct.Bytes()) {
		t.Fatal("effective metadata did not compile to the exact direct CatalogSnapshot")
	}

	snapshot := mustOpenSnapshot(t, compiled)
	viewArtifact, err := ProjectRuntimeMetadataView(snapshot, ProjectionKey{AppInstallationID: testInstallA, CapabilityID: testCapability})
	if err != nil {
		t.Fatal(err)
	}
	view := mustOpenView(t, viewArtifact)
	object, ok := view.Object("WorkItem")
	if !ok {
		t.Fatal("compiled Runtime view is missing WorkItem")
	}
	field := models.FindField(object, "Subject")
	if field == nil || field.PhysicalName != "subject_text" || field.GeneratedForPolymorphicReference != "RelatedTo" {
		t.Fatalf("lossless field facts = %#v", field)
	}
}

func TestEffectiveMetadataOpenFailsClosed(t *testing.T) {
	source, err := BuildEffectiveMetadata(neutralCompileInput())
	if err != nil {
		t.Fatal(err)
	}

	tests := []struct {
		name   string
		mutate func([]byte) (Digest, []byte)
	}{
		{
			name: "digest mismatch",
			mutate: func(data []byte) (Digest, []byte) {
				data[len(data)-1] ^= 1
				return source.Digest(), data
			},
		},
		{
			name: "unknown field",
			mutate: func(data []byte) (Digest, []byte) {
				data = bytes.Replace(data, []byte(`"orgId":`), []byte(`"unknown":true,"orgId":`), 1)
				return ComputeDigest(data), data
			},
		},
		{
			name: "duplicate JSON fact",
			mutate: func(data []byte) (Digest, []byte) {
				data = bytes.Replace(data, []byte(`"orgId":`), []byte(`"orgId":"shadow","orgId":`), 1)
				return ComputeDigest(data), data
			},
		},
		{
			name: "noncanonical whitespace",
			mutate: func(data []byte) (Digest, []byte) {
				data = append(data, '\n')
				return ComputeDigest(data), data
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			digest, data := tt.mutate(source.Bytes())
			if _, err := OpenEffectiveMetadata(digest, data); err == nil {
				t.Fatal("OpenEffectiveMetadata() error = nil")
			}
		})
	}
}

func TestEffectiveMetadataRejectsDuplicateFactsAndInvalidCriteria(t *testing.T) {
	t.Run("duplicate object", func(t *testing.T) {
		input := neutralCompileInput()
		input.Objects = append(input.Objects, input.Objects[0])
		if _, err := BuildEffectiveMetadata(input); err == nil {
			t.Fatal("BuildEffectiveMetadata() error = nil")
		}
	})
	t.Run("duplicate field", func(t *testing.T) {
		input := neutralCompileInput()
		input.Objects[0].Metadata.Fields = append(input.Objects[0].Metadata.Fields, input.Objects[0].Metadata.Fields[0])
		if _, err := BuildEffectiveMetadata(input); err == nil {
			t.Fatal("BuildEffectiveMetadata() error = nil")
		}
	})
	t.Run("valid criteria uses the Runtime neutral validator", func(t *testing.T) {
		input := neutralCompileInput()
		input.SharingRules[0].Metadata.Criteria = `[{"field":"Done","op":"=","value":false}]`
		if _, err := BuildEffectiveMetadata(input); err != nil {
			t.Fatalf("BuildEffectiveMetadata() error = %v", err)
		}
	})
	t.Run("invalid criteria cannot bypass validation", func(t *testing.T) {
		input := neutralCompileInput()
		input.SharingRules[0].Metadata.Criteria = `[{"field":"Missing","op":"=","value":false}]`
		_, err := BuildEffectiveMetadata(input)
		if err == nil || !strings.Contains(err.Error(), "unknown sharing rule JSON criteria field") {
			t.Fatalf("BuildEffectiveMetadata() error = %v", err)
		}
	})
}
