package expression

import (
	"testing"

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

// TestTodayNowArityParity asserts that the 0-arg builtins TODAY and NOW enforce
// their catalog-declared arity (MinArgs:0, MaxArgs:0) identically at both the
// validation layer (spec.CheckArity, the single source of truth that drives
// ValidateSyntax) and the runtime layer (Engine.Evaluate). Before the cutover,
// TODAY/NOW were bare variadic handlers, so Evaluate accepted TODAY(1)/NOW(1)
// even though validation rejected them — gate and runtime diverged. This test
// locks the two layers together.
func TestTodayNowArityParity(t *testing.T) {
	zeroArgFns := []string{"TODAY", "NOW"}

	t.Run("validation layer rejects above-max", func(t *testing.T) {
		for _, name := range zeroArgFns {
			if err := spec.CheckArity(name, 1); err == nil {
				t.Errorf("validation layer: %s(1) expected arity error, got nil", name)
			}
		}
	})

	t.Run("validation layer accepts zero args", func(t *testing.T) {
		for _, name := range zeroArgFns {
			if err := spec.CheckArity(name, 0); err != nil {
				t.Errorf("validation layer: %s() expected no error, got %v", name, err)
			}
		}
	})

	t.Run("runtime layer rejects above-max", func(t *testing.T) {
		engine := NewEngine()
		cases := []string{"TODAY(1)", "NOW(1)"}
		for _, expr := range cases {
			if _, err := engine.Evaluate(expr, map[string]interface{}{}); err == nil {
				t.Errorf("runtime layer: %s expected arity error, got nil", expr)
			}
		}
	})

	t.Run("runtime layer accepts zero args", func(t *testing.T) {
		engine := NewEngine()
		cases := []string{"TODAY()", "NOW()"}
		for _, expr := range cases {
			if _, err := engine.Evaluate(expr, map[string]interface{}{}); err != nil {
				t.Errorf("runtime layer: %s expected no error, got %v", expr, err)
			}
		}
	})
}
