package packs

import (
	"context"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	domainschema "github.com/nexuscrm/kernel/pkg/schema"
	"github.com/nexuscrm/shared/pkg/constants"
)

func TestReconcileManagedRelationshipSemanticsDoesNotInsertForMasterDetailField(t *testing.T) {
	// Master-detail fields already derive IsSharingParent=true and
	// CascadeDelete=true from field metadata, so no overlay row is needed.
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock: %v", err)
	}
	defer db.Close()

	truePtr := func(v bool) *bool { return &v }
	mock.ExpectQuery("SELECT COUNT\\(\\*\\)\\s+FROM _System_Relationship").
		WithArgs("contact", "account", "accountid").
		WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))

	err = ReconcileManagedRelationshipSemanticsWithDefs(context.Background(), db, []domainschema.ManagedRelationshipSemantics{
		{
			ChildObjectAPIName:  "Contact",
			ParentObjectAPIName: "Account",
			FieldAPIName:        "AccountId",
			IsSharingParent:     truePtr(true),
		},
	}, []domainschema.TableDefinition{
		{
			TableName: "Contact",
			Columns: []domainschema.ColumnDefinition{
				{
					Name:             "AccountId",
					LogicalType:      string(constants.FieldTypeMasterDetail),
					ReferenceTo:      []string{"Account"},
					RelationshipName: "Account",
					IsMasterDetail:   true,
				},
			},
		},
	})
	if err != nil {
		t.Fatalf("ReconcileManagedRelationshipSemanticsWithDefs = %v, want nil", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations: %v", err)
	}
}

func TestReconcileManagedRelationshipSemanticsInsertsOverlayForReferenceFieldWithSharingParent(t *testing.T) {
	// Plain reference fields that the managed definition marks as
	// IsSharingParent=true require an overlay row so the resolver can
	// upgrade the field-derived edge. This is the DashboardComponent.DashboardId
	// pattern: the backing field is a plain reference, but the substrate
	// contract requires IsSharingParent=true and CascadeDelete=true.
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock: %v", err)
	}
	defer db.Close()

	truePtr := func(v bool) *bool { return &v }
	mock.ExpectQuery("SELECT COUNT\\(\\*\\)\\s+FROM _System_Relationship").
		WithArgs("dashboardcomponent", "dashboard", "dashboardid").
		WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))

	mock.ExpectExec("INSERT INTO `_System_Relationship`").
		WillReturnResult(sqlmock.NewResult(1, 1))

	err = ReconcileManagedRelationshipSemanticsWithDefs(context.Background(), db, []domainschema.ManagedRelationshipSemantics{
		{
			ChildObjectAPIName:  "DashboardComponent",
			ParentObjectAPIName: "Dashboard",
			FieldAPIName:        "DashboardId",
			IsSharingParent:     truePtr(true),
			CascadeDelete:       truePtr(true),
		},
	}, []domainschema.TableDefinition{
		{
			TableName: "DashboardComponent",
			Columns: []domainschema.ColumnDefinition{
				{
					Name:             "DashboardId",
					LogicalType:      string(constants.FieldTypeReference),
					ReferenceTo:      []string{"Dashboard"},
					RelationshipName: "Dashboard",
				},
			},
		},
	})
	if err != nil {
		t.Fatalf("ReconcileManagedRelationshipSemanticsWithDefs = %v, want nil", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations: %v", err)
	}
}
