package programchecker

import (
	"testing"

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

func TestFormulaRegistryReaderUsesDefaultSpecRegistry(t *testing.T) {
	registry, err := formula.ExecutableFunctionRegistryWithBundles(nil)
	if err != nil {
		t.Fatalf("ExecutableFunctionRegistryWithBundles: %v", err)
	}
	reader := NewFormulaCatalogReader(registry)

	sig, ok, err := reader.FormulaFunction("len")
	if err != nil {
		t.Fatalf("FormulaFunction: %v", err)
	}
	if !ok {
		t.Fatal("FormulaFunction(len) = false, want registered default function")
	}
	if sig.Spec.Name != "LEN" {
		t.Fatalf("Spec.Name = %q, want LEN", sig.Spec.Name)
	}
	if sig.Spec.Return.Kind != spec.ReturnFixed || sig.Spec.Return.Fixed != spec.TypeNumber {
		t.Fatalf("Spec.Return = %#v, want fixed number", sig.Spec.Return)
	}
	if sig.Definition != nil {
		t.Fatalf("Definition = %#v, want nil for L0 catalog function without bundle definition", sig.Definition)
	}
}

func TestFormulaRegistryReaderRetainsBundleDefinition(t *testing.T) {
	bundle, err := formula.ParseFunctionBundlePayload([]byte(`{
		"functions": [
			{
				"name": "PACK_PREFIX",
				"minArgs": 1,
				"maxArgs": 1,
				"return": { "kind": "fixed", "type": "string" },
				"args": [{ "type": "string", "nullable": true }],
				"evaluator": {
					"kind": "formula_expr_v1",
					"params": ["value"],
					"body": "value + \"-probe\""
				}
			}
		]
	}`))
	if err != nil {
		t.Fatalf("ParseFunctionBundlePayload: %v", err)
	}
	registry, err := formula.ExecutableFunctionRegistryWithBundles([]formula.FunctionBundle{bundle})
	if err != nil {
		t.Fatalf("ExecutableFunctionRegistryWithBundles: %v", err)
	}
	reader := NewFormulaCatalogReader(registry)

	sig, ok, err := reader.FormulaFunction("PACK_PREFIX")
	if err != nil {
		t.Fatalf("FormulaFunction: %v", err)
	}
	if !ok {
		t.Fatal("FormulaFunction(PACK_PREFIX) = false, want bundle function")
	}
	if sig.Definition == nil {
		t.Fatal("Definition = nil, want bundle definition")
	}
	sig.Definition.Evaluator.Body = "mutated"

	again, ok, err := reader.FormulaFunction("PACK_PREFIX")
	if err != nil {
		t.Fatalf("FormulaFunction second read: %v", err)
	}
	if !ok || again.Definition == nil {
		t.Fatal("FormulaFunction second read missing bundle definition")
	}
	if got, want := again.Definition.Evaluator.Body, `value + "-probe"`; got != want {
		t.Fatalf("Definition body after caller mutation = %q, want %q", got, want)
	}
}
