package metadata

import (
	"strings"
	"testing"

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

func unicodeLengthIntPtr(value int) *int {
	return &value
}

func TestValidateRecordStaticConstraintsMaxLengthCountsUnicodeCodePoints(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name      string
		fieldType constants.SchemaFieldType
		value     string
		wantError bool
	}{
		{name: "string accepts 255 CJK code points", fieldType: constants.FieldTypeString, value: strings.Repeat("测", 255)},
		{name: "textarea accepts 255 CJK code points", fieldType: constants.FieldTypeTextarea, value: strings.Repeat("测", 255)},
		{name: "string accepts 255 supplementary code points", fieldType: constants.FieldTypeString, value: strings.Repeat("🚀", 255)},
		{name: "string preserves the ASCII boundary", fieldType: constants.FieldTypeString, value: strings.Repeat("a", 255)},
		{name: "string rejects 256 CJK code points", fieldType: constants.FieldTypeString, value: strings.Repeat("测", 256), wantError: true},
	}

	for _, test := range tests {
		test := test
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()

			schema := &models.ObjectMetadata{
				APIName: "Task",
				Fields: []models.FieldMetadata{
					{
						APIName:   "Note",
						Type:      test.fieldType,
						MaxLength: unicodeLengthIntPtr(255),
					},
				},
			}

			err := NewValidationService(nil).ValidateRecordStaticConstraints(
				models.SObject{"Note": test.value},
				schema,
			)
			if test.wantError {
				if err == nil || !strings.Contains(err.Error(), "is too long") {
					t.Fatalf("ValidateRecordStaticConstraints() error = %v, want is too long", err)
				}
				return
			}
			if err != nil {
				t.Fatalf("ValidateRecordStaticConstraints() error = %v, want nil", err)
			}
		})
	}
}

func TestValidateRecordStaticConstraintsMinLengthCountsUnicodeCodePoints(t *testing.T) {
	t.Parallel()

	schema := &models.ObjectMetadata{
		APIName: "Task",
		Fields: []models.FieldMetadata{
			{
				APIName:   "Note",
				Type:      constants.FieldTypeString,
				MinLength: unicodeLengthIntPtr(5),
			},
		},
	}
	service := NewValidationService(nil)

	if err := service.ValidateRecordStaticConstraints(
		models.SObject{"Note": strings.Repeat("测", 3)},
		schema,
	); err == nil || !strings.Contains(err.Error(), "is too short") {
		t.Fatalf("three CJK code points error = %v, want is too short", err)
	}

	if err := service.ValidateRecordStaticConstraints(
		models.SObject{"Note": strings.Repeat("测", 5)},
		schema,
	); err != nil {
		t.Fatalf("five CJK code points error = %v, want nil", err)
	}
}
