package catalogsnapshot

import (
	"github.com/nexuscrm/shared/pkg/models"
	v1 "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/layoutauthoringv1"
	v2 "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/layoutauthoringv2"
	historysemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
	"testing"
)

func TestHistoryLayoutReferencesResolveOnlyTheRealParent(t *testing.T) {
	projection := v2.HistoryRelatedListProjection{ObjectID: "Changes", Columns: map[string]historysemantic.HistoryColumn{
		"Key": historysemantic.HistoryColumnID, "IssueRef": historysemantic.HistoryColumnParentID,
		"Attribute": historysemantic.HistoryColumnField, "Before": historysemantic.HistoryColumnOldValue,
		"After": historysemantic.HistoryColumnNewValue, "ValueType": historysemantic.HistoryColumnDataType,
		"At": historysemantic.HistoryColumnCreatedDate, "Actor": historysemantic.HistoryColumnCreatedByID,
	}}
	objects := []*models.ObjectMetadata{{ID: "issue-incarnation", APIName: "Issue"}}
	document := v1.LayoutDocument{ObjectID: "Issue", RelatedLists: []v1.RelatedList{{ObjectID: "Changes", LookupFieldID: "IssueRef", FieldIDs: []string{"Attribute", "Before", "After", "At", "Actor"}}}}
	references, err := ResolveLayoutAuthoringReferencesFromObjects(objects, document, nil, false, projection)
	if err != nil {
		t.Fatal(err)
	}
	if len(references) != 1 || references[0].ObjectID != "issue-incarnation" || references[0].FieldID != "" {
		t.Fatalf("invented history schema incarnation: %#v", references)
	}
	tests := []struct {
		name    string
		edit    func(*v1.LayoutDocument)
		objects []*models.ObjectMetadata
	}{
		{name: "undeclared object"},
		{name: "unknown column", edit: func(d *v1.LayoutDocument) { d.RelatedLists[0].FieldIDs = []string{"Secret"} }},
		{name: "read-only prefill", edit: func(d *v1.LayoutDocument) {
			d.RelatedLists[0].PrefillMappings = []v1.PrefillMapping{{SourceFieldID: "Id", TargetFieldID: "Before"}}
		}},
		{name: "non-parent lookup", edit: func(d *v1.LayoutDocument) { d.RelatedLists[0].LookupFieldID = "Actor" }},
		{name: "unknown alias", edit: func(d *v1.LayoutDocument) { d.RelatedLists[0].ObjectID = "Unknown" }},
		{name: "physical collision", objects: append(append([]*models.ObjectMetadata{}, objects...), &models.ObjectMetadata{ID: "changes-incarnation", APIName: "Changes"})},
		{name: "missing parent", objects: []*models.ObjectMetadata{}},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			copy := document
			copy.RelatedLists = append([]v1.RelatedList{}, document.RelatedLists...)
			if test.edit != nil {
				test.edit(&copy)
			}
			current := objects
			if test.objects != nil {
				current = test.objects
			}
			projections := []v2.HistoryRelatedListProjection{projection}
			if test.name == "undeclared object" {
				projections = nil
			}
			if _, err := ResolveLayoutAuthoringReferencesFromObjects(current, copy, nil, false, projections...); err == nil {
				t.Fatal("accepted invalid history reference")
			}
		})
	}
}
