package packs

import (
	"context"
	"strings"
	"testing"

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

func testFormulaFunctionBundleComponentPayload() string {
	return `{
		"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\""
				}
			}
		]
	}`
}

func formulaFunctionBundleManifestComponent(payload string) string {
	return `{
		"kind": "formula_function_bundle",
		"businessKey": "probe-functions",
		"manageability": "locked",
		"payload": ` + jsonRawMessage(payload) + `
	}`
}

func TestFormulaFunctionBundleSourcePackPublishesRuntimeBundleAndRemovalClears(t *testing.T) {
	if err := formula.RegisterRuntimeFunctionBundles(nil); err != nil {
		t.Fatalf("clear runtime formula bundles before test: %v", err)
	}
	t.Cleanup(func() {
		_ = formula.RegisterRuntimeFunctionBundles(nil)
	})

	root := writePackFixture(t, "formula-functions", validPackManifest(`[
		`+formulaFunctionBundleManifestComponent(testFormulaFunctionBundleComponentPayload())+`
	]`, ``))

	report := ValidateInstallablePackSourceWithOptions("local_path:"+root, testPackSourceOptions(t))
	if report.HasErrors() {
		t.Fatalf("ValidateInstallablePackSourceWithOptions diagnostics:\n%s", report.Error())
	}
	if report.Pack == nil {
		t.Fatal("ValidateInstallablePackSourceWithOptions did not construct installable pack")
	}

	if err := RegisterRuntimeMetadataForPacks(context.Background(), nil, []Pack{report.Pack}); err != nil {
		t.Fatalf("RegisterRuntimeMetadataForPacks with formula bundle: %v", err)
	}
	engine := formula.NewEngine()
	got, err := engine.Evaluate(`PACK_PREFIX(Name)`, &formula.Context{Record: map[string]interface{}{"Name": "alpha"}})
	if err != nil {
		t.Fatalf("Evaluate PACK_PREFIX from source pack runtime bundle: %v", err)
	}
	if got != "alpha-probe" {
		t.Fatalf("Evaluate PACK_PREFIX from source pack runtime bundle = %v, want alpha-probe", got)
	}

	if err := RegisterRuntimeMetadataForPacks(context.Background(), nil, nil); err != nil {
		t.Fatalf("RegisterRuntimeMetadataForPacks after removal: %v", err)
	}
	engine = formula.NewEngine()
	if err := engine.ValidateSyntax(`PACK_PREFIX(Name)`); err == nil || !strings.Contains(err.Error(), "PACK_PREFIX") {
		t.Fatalf("ValidateSyntax PACK_PREFIX after removal = %v, want fail closed", err)
	}
}

func TestFormulaFunctionBundleSourcePackRuntimeBundlesAreDeepCloned(t *testing.T) {
	root := writePackFixture(t, "formula-functions", validPackManifest(`[
		`+formulaFunctionBundleManifestComponent(testFormulaFunctionBundleComponentPayload())+`
	]`, ``))

	report := ValidateInstallablePackSourceWithOptions("local_path:"+root, testPackSourceOptions(t))
	if report.HasErrors() {
		t.Fatalf("ValidateInstallablePackSourceWithOptions diagnostics:\n%s", report.Error())
	}
	if report.Pack == nil {
		t.Fatal("ValidateInstallablePackSourceWithOptions did not construct installable pack")
	}

	bundles := report.Pack.RuntimeFormulaFunctionBundles()
	if len(bundles) != 1 || len(bundles[0].Functions) != 1 || len(bundles[0].Functions[0].Evaluator.Params) != 1 {
		t.Fatalf("RuntimeFormulaFunctionBundles returned unexpected shape: %#v", bundles)
	}
	bundles[0].Functions[0].Name = "MUTATED"
	bundles[0].Functions[0].Evaluator.Params[0] = "mutated"

	bundles = report.Pack.RuntimeFormulaFunctionBundles()
	if got := bundles[0].Functions[0].Name; got != "PACK_PREFIX" {
		t.Fatalf("RuntimeFormulaFunctionBundles leaked function name mutation: got %q", got)
	}
	if got := bundles[0].Functions[0].Evaluator.Params[0]; got != "value" {
		t.Fatalf("RuntimeFormulaFunctionBundles leaked evaluator params mutation: got %q", got)
	}
}

func TestValidateInstallablePackSourceRejectsFormulaFunctionBundleWithoutEvaluator(t *testing.T) {
	payload := `{
		"functions": [
			{
				"name": "PACK_PREFIX",
				"minArgs": 1,
				"maxArgs": 1,
				"return": { "kind": "fixed", "type": "string" },
				"args": [{ "type": "string", "nullable": true }]
			}
		]
	}`
	root := writePackFixture(t, "formula-functions", validPackManifest(`[
		`+formulaFunctionBundleManifestComponent(payload)+`
	]`, ``))

	report := ValidateInstallablePackSourceWithOptions("local_path:"+root, testPackSourceOptions(t))
	assertInstallableDiagnostic(t, report, "component.payload.invalid_schema")
}
