package router

import "github.com/kami/maven/internal/lexicon"

// ActHasEntityTarget reports whether an act names something that Nexus may be
// asked to resolve. A local zero-argument tool may still be valid; this gate is
// only about crossing into the ecosystem, where an entity is mandatory.
//
// A matched function carries its target in Args. An unmatched entity act is
// the Hexis discovery lane, so it must at least contain a verb plus a subject.
// A bare verb and a demonstrative-only tail carry no target evidence and stay
// local/clarify instead of sending free ambiguity to Nexus.
func ActHasEntityTarget(decision Decision) bool {
	if decision.Intent != IntentAct {
		return false
	}
	if decision.Slots.HasFn {
		if len(decision.Slots.Args) > 0 {
			return hasNamedEntityToken(decision.Slots.Args)
		}
		// A resident-model act may name the accepted verb and its target in
		// Text while leaving Args empty. HasFn establishes that the first token
		// is the operation; only a meaningful tail can establish the entity.
		tokens := planTokens(decision.Slots.Text)
		return len(tokens) > 1 && hasNamedEntityToken(tokens[1:])
	}
	tokens := planTokens(decision.Slots.Text)
	if len(tokens) < 2 {
		return false
	}
	return hasNamedEntityToken(tokens[1:])
}

func hasNamedEntityToken(tokens []string) bool {
	references := lexicon.UnresolvedReferences()
	for _, token := range tokens {
		if lexicon.IsFillerParticle(token) || hasExactWord(references, token) {
			continue
		}
		return true
	}
	return false
}
