package searchmetadata

import (
	"context"

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

// SearchableObjectNames returns the user-searchable object scope from the
// neutral metadata read path. It is the shared owner for metadata-derived search
// scope defaults; product dialects own their own wire projection.
func SearchableObjectNames(ctx context.Context, metadata contract.Metadata) []string {
	if metadata == nil {
		return nil
	}
	objects, err := metadata.ListObjects(ctx)
	if err != nil {
		return nil
	}
	out := make([]string, 0, len(objects))
	for i := range objects {
		if IsUserSearchableObject(&objects[i]) {
			out = append(out, objects[i].APIName)
		}
	}
	return out
}

// IsUserSearchableObject is the shared search-scope classifier for metadata
// objects. Keep it in shared so L1 dialect modules and backend transitional
// routes cannot drift on the same searchability fact.
func IsUserSearchableObject(schema *models.ObjectMetadata) bool {
	if schema == nil || schema.IsSystem || !schema.Searchable {
		return false
	}
	if constants.IsManagedSystemTable(schema.APIName) {
		return false
	}

	switch schema.TableType {
	case constants.TableTypeStandardObject:
		return true
	case constants.TableTypeCustomObject:
		return schema.IsCustom
	case "":
		return true
	default:
		return false
	}
}

// IsSearchableField returns whether a field is eligible for broad metadata
// search. Formula and rollup fields are deliberately excluded even when their
// logical type would otherwise be searchable, matching legacy v63 behavior.
func IsSearchableField(field models.FieldMetadata) bool {
	effectiveType := field.Type
	if field.LogicalType != nil {
		effectiveType = *field.LogicalType
	}
	normalized := constants.NormalizeFieldType(string(effectiveType))
	switch normalized {
	case constants.FieldTypeFormula, constants.FieldTypeRollupSummary:
		return false
	default:
		return fieldtypes.GetRegistry().IsSearchable(string(normalized))
	}
}
