package persistence

import (
	"testing"

	domainschema "github.com/nexuscrm/kernel/pkg/schema"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

func TestPreparePackOwnedFieldMetadataCopiesUniqueFromColumn(t *testing.T) {
	repo := NewSchemaRepository(nil, nil)
	field := testPackOwnedFieldContext()
	field.Field.IsUnique = false
	field.ColumnDefinition.Unique = true

	got := repo.preparePackOwnedFieldMetadata(field, field.ColumnDefinition, field.OwnerPack)
	if got.Field == nil {
		t.Fatal("preparePackOwnedFieldMetadata returned nil Field")
	}
	if !got.Field.IsUnique {
		t.Fatal("preparePackOwnedFieldMetadata did not copy Unique from column definition")
	}
}

func TestPackOwnedAllowedDeleteRulesAcceptsNoActionForDefault(t *testing.T) {
	got := packOwnedAllowedDeleteRules("")
	if got != [2]string{"RESTRICT", "NO ACTION"} {
		t.Fatalf("packOwnedAllowedDeleteRules(\"\") = %#v, want RESTRICT and NO ACTION", got)
	}

	got = packOwnedAllowedDeleteRules("cascade")
	if got != [2]string{"CASCADE", "CASCADE"} {
		t.Fatalf("packOwnedAllowedDeleteRules(\"cascade\") = %#v, want explicit CASCADE only", got)
	}
}

func TestPackOwnedPhysicalColumnMatchesNormalizesTypeAndDefaults(t *testing.T) {
	repo := NewSchemaRepository(nil, nil)
	boolDefault := "1"
	if !repo.packOwnedPhysicalColumnMatches(&physicalColumnSpec{
		ColumnType:    "tinyint(1)",
		IsNullable:    false,
		ColumnDefault: &boolDefault,
	}, domainschema.ColumnDefinition{
		Name:     "IsEscalated__c",
		Type:     "BOOLEAN",
		Nullable: false,
		Default:  "true",
	}) {
		t.Fatal("packOwnedPhysicalColumnMatches rejected normalized boolean shape")
	}

	timestampDefault := "current_timestamp()"
	if !repo.packOwnedPhysicalColumnMatches(&physicalColumnSpec{
		ColumnType:    "timestamp",
		IsNullable:    false,
		ColumnDefault: &timestampDefault,
	}, domainschema.ColumnDefinition{
		Name:     "TouchedAt__c",
		Type:     "TIMESTAMP",
		Nullable: false,
		Default:  "CURRENT_TIMESTAMP",
	}) {
		t.Fatal("packOwnedPhysicalColumnMatches rejected normalized timestamp default")
	}
}

func testPackOwnedFieldContext() domainschema.FieldWithContext {
	ownerPack := "extension-pack"
	field := &models.FieldMetadata{
		APIName:    "EscalationCode__c",
		Label:      "Escalation Code",
		Type:       constants.FieldTypeString,
		Createable: true,
		Updateable: true,
		OwnerKind:  constants.FieldOwnerKindPack,
		OwnerPack:  &ownerPack,
	}
	col := domainschema.ColumnDefinition{
		Name:        "EscalationCode__c",
		Label:       "Escalation Code",
		Type:        "VARCHAR(255)",
		LogicalType: string(constants.FieldTypeString),
		Nullable:    true,
	}
	return domainschema.FieldWithContext{
		Field:                field,
		ColumnDefinition:     col,
		TableName:            "Issue",
		ObjectID:             "obj_issue",
		FieldID:              "fld_issue_escalationcode",
		OwnerKind:            constants.FieldOwnerKindPack,
		OwnerPack:            ownerPack,
		CapabilitiesDeclared: true,
	}
}

func testPackOwnedFormulaFieldContext() domainschema.FieldWithContext {
	ownerPack := "extension-pack"
	formula := "IF(ISBLANK(ContactId), Lead.Title, Contact.Title)"
	mode := "active"
	returnType := models.FieldType(constants.FieldTypeString)
	field := &models.FieldMetadata{
		APIName:     "EscalationScore__c",
		Label:       "Escalation Score",
		Type:        constants.FieldTypeString,
		Createable:  false,
		Updateable:  false,
		Formula:     &formula,
		FormulaMode: &mode,
		ReturnType:  &returnType,
		OwnerKind:   constants.FieldOwnerKindPack,
		OwnerPack:   &ownerPack,
	}
	col := domainschema.ColumnDefinition{
		Name:        "EscalationScore__c",
		Label:       "Escalation Score",
		Type:        "VARCHAR(255)",
		LogicalType: string(constants.FieldTypeString),
		Formula:     formula,
		FormulaMode: mode,
		ReturnType:  string(constants.FieldTypeString),
		Nullable:    true,
	}
	return domainschema.FieldWithContext{
		Field:                field,
		ColumnDefinition:     col,
		TableName:            "Issue",
		ObjectID:             "obj_issue",
		FieldID:              "fld_issue_escalationscore",
		OwnerKind:            constants.FieldOwnerKindPack,
		OwnerPack:            ownerPack,
		CapabilitiesDeclared: true,
	}
}

func testPackOwnedProjectionFieldContext() domainschema.FieldWithContext {
	ownerPack := "extension-pack"
	mode := "active"
	returnType := models.FieldType(constants.FieldTypeString)
	projection := &models.FieldProjectionConfig{
		Kind:           "lookup",
		TargetObject:   "Product2",
		SelectField:    "Name",
		ExcludeDeleted: true,
		Matches: []models.FieldProjectionMatch{
			{TargetField: "Id", SourceField: "Product2Id"},
		},
	}
	field := &models.FieldMetadata{
		APIName:          "Name",
		Label:            "Name",
		Type:             constants.FieldTypeString,
		Createable:       false,
		Updateable:       false,
		FormulaMode:      &mode,
		ReturnType:       &returnType,
		ProjectionConfig: projection,
		OwnerKind:        constants.FieldOwnerKindPack,
		OwnerPack:        &ownerPack,
	}
	col := domainschema.ColumnDefinition{
		Name:             "Name",
		Label:            "Name",
		Type:             "VARCHAR(255)",
		LogicalType:      string(constants.FieldTypeString),
		FormulaMode:      mode,
		ReturnType:       string(constants.FieldTypeString),
		ProjectionConfig: projection,
		Nullable:         true,
	}
	return domainschema.FieldWithContext{
		Field:                field,
		ColumnDefinition:     col,
		TableName:            "PricebookEntry",
		ObjectID:             "obj_pricebookentry",
		FieldID:              "fld_pricebookentry_name",
		OwnerKind:            constants.FieldOwnerKindPack,
		OwnerPack:            ownerPack,
		CapabilitiesDeclared: true,
	}
}

func testPackOwnedWriteMaterializedFormulaFieldContext() domainschema.FieldWithContext {
	ownerPack := "extension-pack"
	formula := "IF(ISBLANK(ContactId), Lead.Title, Contact.Title)"
	mode := "active"
	storageMode := "write_materialized"
	returnType := models.FieldType(constants.FieldTypeString)
	field := &models.FieldMetadata{
		APIName:            "EscalationStored__c",
		Label:              "Escalation Stored",
		Type:               constants.FieldTypeFormula,
		Createable:         false,
		Updateable:         false,
		Formula:            &formula,
		FormulaMode:        &mode,
		FormulaStorageMode: &storageMode,
		ReturnType:         &returnType,
		OwnerKind:          constants.FieldOwnerKindPack,
		OwnerPack:          &ownerPack,
	}
	col := domainschema.ColumnDefinition{
		Name:               "EscalationStored__c",
		Label:              "Escalation Stored",
		Type:               "VARCHAR(255)",
		LogicalType:        string(constants.FieldTypeFormula),
		Formula:            formula,
		FormulaMode:        mode,
		FormulaStorageMode: storageMode,
		ReturnType:         string(constants.FieldTypeString),
		Nullable:           true,
	}
	return domainschema.FieldWithContext{
		Field:                field,
		ColumnDefinition:     col,
		TableName:            "Issue",
		ObjectID:             "obj_issue",
		FieldID:              "fld_issue_escalationstored",
		OwnerKind:            constants.FieldOwnerKindPack,
		OwnerPack:            ownerPack,
		CapabilitiesDeclared: true,
	}
}
