package bootstrap

import (
	"context"
	"regexp"
	"testing"

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

func TestReconcileManagedRelationshipSemantics_UpdatesExistingManagedRows(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	isSharingParent := true
	cascadeDelete := false
	defs := []domainschema.ManagedRelationshipSemantics{
		{
			ChildObjectAPIName:  "Contact",
			ParentObjectAPIName: "Account",
			FieldAPIName:        "AccountId",
			IsSharingParent:     &isSharingParent,
			CascadeDelete:       &cascadeDelete,
		},
	}
	tableDefs := []domainschema.TableDefinition{
		{
			TableName: "Contact",
			Columns: []domainschema.ColumnDefinition{
				{Name: "AccountId", LogicalType: string(constants.FieldTypeReference), RelationshipName: "Account", ReferenceTo: []string{"Account"}},
			},
		},
	}

	mock.ExpectQuery("SELECT COUNT\\(\\*\\)\\s+FROM _System_Relationship").
		WithArgs("contact", "account", "accountid").
		WillReturnRows(sqlmock.NewRows([]string{"COUNT(*)"}).AddRow(1))
	mock.ExpectExec(regexp.QuoteMeta("UPDATE _System_Relationship")).
		WithArgs(true, false, "contact", "account", "accountid", true, false).
		WillReturnResult(sqlmock.NewResult(0, 1))

	if err := reconcileManagedRelationshipSemantics(context.Background(), db, defs, tableDefs); err != nil {
		t.Fatalf("reconcileManagedRelationshipSemantics: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("ExpectationsWereMet: %v", err)
	}
}

func TestReconcileManagedRelationshipSemantics_InsertsMissingManagedRows(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	isSharingParent := true
	defs := []domainschema.ManagedRelationshipSemantics{
		{
			ChildObjectAPIName:  "Quote",
			ParentObjectAPIName: "Opportunity",
			FieldAPIName:        "OpportunityId",
			IsSharingParent:     &isSharingParent,
		},
	}
	tableDefs := []domainschema.TableDefinition{
		{
			TableName: "Quote",
			Columns: []domainschema.ColumnDefinition{
				{Name: "OpportunityId", LogicalType: string(constants.FieldTypeReference), RelationshipName: "Opportunity", ReferenceTo: []string{"Opportunity"}},
			},
		},
	}

	mock.ExpectQuery("SELECT COUNT\\(\\*\\)\\s+FROM _System_Relationship").
		WithArgs("quote", "opportunity", "opportunityid").
		WillReturnRows(sqlmock.NewRows([]string{"COUNT(*)"}).AddRow(0))
	mock.ExpectExec(regexp.QuoteMeta("INSERT INTO `_System_Relationship`")).
		WithArgs(sqlmock.AnyArg(), "Quote", "Opportunity", "OpportunityId", "Opportunity", string(constants.FieldTypeReference), "Opportunity", "[]", true).
		WillReturnResult(sqlmock.NewResult(1, 1))

	if err := reconcileManagedRelationshipSemantics(context.Background(), db, defs, tableDefs); err != nil {
		t.Fatalf("reconcileManagedRelationshipSemantics: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("ExpectationsWereMet: %v", err)
	}
}
