package tenantoverlay

import (
	"context"
	"database/sql/driver"
	"regexp"
	"strings"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/nexuscrm/metadata"
)

type losslessPageLayoutConfigArgument struct{}

func (losslessPageLayoutConfigArgument) Match(value driver.Value) bool {
	raw, ok := value.(string)
	if !ok {
		return false
	}
	for _, exact := range []string{
		`"scale":12.50`,
		`"large":9007199254740993`,
		`"precise":0.123456789012345678901234567890`,
		`"objectApiName":"NewChild"`,
	} {
		if !strings.Contains(raw, exact) {
			return false
		}
	}
	return !strings.Contains(raw, `"objectApiName":"LegacyChild"`)
}

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

	const stored = `{"id":"layout-1","objectApiName":"Account","layoutName":"Default","relatedLists":[{"objectApiName":"LegacyChild","lookupField":"AccountId"}],"headerActions":[{"name":"Run","config":{"scale":12.50,"large":9007199254740993,"precise":0.123456789012345678901234567890}}]}`
	query := "SELECT `Id`, `Config`, COALESCE(`IsCustomized`, 0), COALESCE(`Source`, '') FROM `_System_PageLayout` WHERE `ObjectApiName` = ? AND (`IsDeleted` = 0 OR `IsDeleted` IS NULL)"
	mock.ExpectQuery(regexp.QuoteMeta(query)).
		WithArgs("Account").
		WillReturnRows(sqlmock.NewRows([]string{"Id", "Config", "IsCustomized", "Source"}).
			AddRow("layout-1", stored, false, "curated"))
	update := "UPDATE `_System_PageLayout` SET `Config` = ?, `LastModifiedDate` = ? WHERE `Id` = ?"
	mock.ExpectExec(regexp.QuoteMeta(update)).
		WithArgs(losslessPageLayoutConfigArgument{}, sqlmock.AnyArg(), "layout-1").
		WillReturnResult(sqlmock.NewResult(0, 1))

	err = applyRelatedListReplacementToLayouts(
		context.Background(),
		db,
		relatedListReplacement{
			LayoutObjectAPIName: "Account",
			MatchObjectAPIName:  "LegacyChild",
			MatchLookupField:    "AccountId",
			TargetRuleKey:       "account-new-children",
		},
		metadata.RelatedListRule{
			Key:             "account-new-children",
			ParentObjectAPI: "Account",
			ChildObjectAPI:  "NewChild",
			LookupField:     "AccountId",
			Label:           "New Children",
		},
		map[string][]string{"newchild": {"Name"}},
	)
	if err != nil {
		t.Fatalf("applyRelatedListReplacementToLayouts: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("SQL expectations: %v", err)
	}
}
