package programchecker

import (
	"strings"

	"github.com/nexuscrm/kernel/pkg/formula/spec"
)

// ValueSource records the kind of program reference that produced a TypeRef.
type ValueSource string

const (
	ValueSourceUnknown           ValueSource = "unknown"
	ValueSourceLiteral           ValueSource = "literal"
	ValueSourceVariable          ValueSource = "variable"
	ValueSourceFieldReference    ValueSource = "field_reference"
	ValueSourceFormulaExpression ValueSource = "formula_expression"
	ValueSourceActionInput       ValueSource = "action_input"
	ValueSourceActionOutput      ValueSource = "action_output"
	ValueSourceLoopIterator      ValueSource = "loop_iterator"
	ValueSourceConnectorMapping  ValueSource = "connector_mapping"
	ValueSourcePolicyReference   ValueSource = "policy_reference"
)

// TypeRef is the checker-local type descriptor. Scalar values deliberately use
// formula/spec.ValueType so formula returns and field-derived values compare
// against one vocabulary.
type TypeRef struct {
	Scalar           spec.ValueType
	Collection       bool
	NestedCollection bool
	ObjectAPIName    string
	Nullable         bool
	Source           ValueSource
}

func (t TypeRef) normalizedScalar() spec.ValueType {
	scalar := spec.ValueType(strings.TrimSpace(string(t.Scalar)))
	if scalar == "" {
		return spec.TypeUnknown
	}
	return scalar
}

func (t TypeRef) String() string {
	scalar := t.normalizedScalar()
	base := string(scalar)
	if scalar == spec.TypeObject {
		if objectAPIName := strings.TrimSpace(t.ObjectAPIName); objectAPIName != "" {
			base = "object<" + objectAPIName + ">"
		}
	}
	if t.Collection {
		base = "[]" + base
	}
	if t.NestedCollection {
		base = "[]" + base
	}
	if t.Nullable {
		base += "?"
	}
	return base
}
