package dispatcher

import (
	"bytes"
	"log/slog"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/desktop/internal/api/exec"
)

// TestLogIsolatedExtensionDiagnostics proves the operator-visible structured
// Warn is emitted for each isolated Extension action with server/agent
// identity, while never including cache validators, raw schema bodies, or
// secrets.
func TestLogIsolatedExtensionDiagnostics(t *testing.T) {
	builtin, err := exec.DefaultCatalog()
	require.NoError(t, err)
	badAction := exec.ExtensionAction{
		ExtensionName: "app", DisplayName: "App",
		Name: "bad", Summary: "Bad",
		Safety:       exec.ExtensionSafety{Class: "read"},
		InputSchema:  map[string]any{"type": "object"},
		OutputSchema: map[string]any{"type": "object", "properties": map[string]any{"x": map[string]any{"$ref": "#/$defs/missingDef"}}},
	}
	domains := []exec.ExtensionDomain{{
		ExtensionName: "app", DisplayName: "App",
		Actions: []exec.ExtensionAction{badAction},
	}}
	snapshot := exec.NewExtensionSnapshot(`"ext-v1-isolation"`, domains)
	runtimeCatalog, err := exec.NewRuntimeCatalog(builtin, snapshot)
	require.NoError(t, err)
	require.NotEmpty(t, runtimeCatalog.Diagnostics())

	var buf bytes.Buffer
	handler := slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelWarn})
	previous := slog.Default()
	slog.SetDefault(slog.New(handler))
	t.Cleanup(func() { slog.SetDefault(previous) })

	logIsolatedExtensionDiagnostics(runtimeCatalog, "srv_1", "agt_1")

	out := buf.String()
	require.Contains(t, out, "isolated Extension action")
	require.Contains(t, out, "server=srv_1")
	require.Contains(t, out, "agent=agt_1")
	require.Contains(t, out, "extension=app")
	require.Contains(t, out, "action=bad")
	require.Contains(t, out, "schema=output")
	require.NotContains(t, out, "ext-v1-isolation")
	require.NotContains(t, out, "extensionCatalog")
	// The bounded cause may name the failing $defs path, but never the raw
	// schema body (the full original OutputSchema JSON) or any input.
	require.NotContains(t, out, `{"type":"object","properties":{"x"`)
	require.NotContains(t, out, `"$ref":"#/$defs/missingDef"`)
}

// TestLogIsolatedExtensionDiagnosticsSilentWhenClean proves no Warn is emitted
// when no action is isolated (no log spam for a healthy catalog).
func TestLogIsolatedExtensionDiagnosticsSilentWhenClean(t *testing.T) {
	builtin, err := exec.DefaultCatalog()
	require.NoError(t, err)
	runtimeCatalog, err := exec.NewRuntimeCatalog(
		builtin,
		exec.NewExtensionSnapshot("", nil),
	)
	require.NoError(t, err)
	require.Empty(t, runtimeCatalog.Diagnostics())

	var buf bytes.Buffer
	handler := slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelWarn})
	previous := slog.Default()
	slog.SetDefault(slog.New(handler))
	t.Cleanup(func() { slog.SetDefault(previous) })

	logIsolatedExtensionDiagnostics(runtimeCatalog, "srv_1", "agt_1")
	require.NotContains(t, buf.String(), "isolated Extension action")
}
