package promptcompiler

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/AgentTeam/desktop/internal/types"
	"github.com/tidbcloud/AgentTeam/desktop/prompts"
)

func TestCompileAgentTeamSkillPlanKeepsOrderedBudgetedSlots(t *testing.T) {
	plan := CompileAgentTeamSkillPlan(func(name string) string { return "mcp_agentteam_" + name }, "mcp_agentteam_memory_search")
	if plan.Core == "" || plan.Reference == "" {
		t.Fatal("compiled skill plan must include core and reference")
	}
	if plan.BudgetTokens <= 0 || len(plan.OrderedSlots) != 2 {
		t.Fatalf("unexpected skill plan: %#v", plan)
	}
	require.NotNil(t, plan.CoreData)
	require.NotNil(t, plan.ReferenceData)
	require.Equal(t, &MemorySearchGuidanceTemplateData{SearchTool: "mcp_agentteam_memory_search"}, plan.MemorySearchData)
}

func TestAgentTeamSkillDocPartsPreserveCurrentTemplates(t *testing.T) {
	toolName := func(name string) string { return "mcp__agentteam__" + name }
	data := agentteamSkillDocData(toolName)
	parts := AgentTeamSkillDocParts(toolName)
	require.Equal(t, types.SkillDocParts{
		Core:      prompts.MustRender("wire/core.md", data),
		Reference: prompts.MustRender("wire/reference.md", data),
	}, parts)
	// 470: the core block absorbed the acknowledgment stopping rule that
	// keeps accepted work moving in the same wake.
	require.LessOrEqual(t, EstimateTokens(parts.Core), 470)
	require.Contains(t, parts.Core, "exact target of the current inbound delivery")
	require.Contains(t, parts.Core, "Delegated subagents return only to their leader")
	require.Contains(t, parts.Core, "current prompt explicitly authorizes communication to one exact target")
	require.Contains(t, parts.Core, "Merely naming or inheriting an ambient, historical/recovered, or Owner-DM target is never authorization")
	require.Contains(t, parts.Core, "independent of retired execution mechanisms")
	require.Contains(t, parts.Core, "mcp__agentteam__message_reaction_set")
	require.Contains(t, parts.Core, "received `👌`, strong agreement `💯`, same here `🙋`, working `⏳`, done `✅`, review passed `👍`")
	require.Contains(t, parts.Core, "acknowledgment-only or status-only replies")
	require.Contains(t, parts.Core, "Do not reply to another agent's status/completion unless it requests action")
	require.Contains(t, parts.Core, "After reporting actual completion, wait")
}

func TestCompileThreadContractMaterializesMemoryGuidanceAsRegisteredBlock(t *testing.T) {
	plan := CompileAgentTeamSkillPlan(func(name string) string { return "mcp__agentteam__" + name }, "mcp__agentteam__memory_search")
	env, err := New(DefaultPolicy()).CompileThreadContract(context.Background(), EventThreadStart, "memory-guidance", CompileInput{AgentID: "agt", Runtime: "codex", SkillPlan: plan})
	require.NoError(t, err)
	var found PromptBlock
	for _, block := range env.Bundle.Blocks {
		if block.ID == "platform.agentteam.memory_search" {
			found = block
			break
		}
	}
	require.Equal(t, "platform.agentteam.memory_search", found.ID)
	require.Contains(t, found.RenderedText(), "mcp__agentteam__memory_search")
}

func TestMemorySearchGuidanceUsesRegisteredTemplate(t *testing.T) {
	guidance := MemorySearchGuidance("mcp__agentteam__memory_search")
	require.Contains(t, guidance, "mcp__agentteam__memory_search")
	require.Contains(t, guidance, "one focused topic in Memory")
	require.Contains(t, guidance, "retry once")
	require.Contains(t, guidance, "bounded grep")
	require.NotContains(t, guidance, "MemorySearchGuidanceTemplateData")
}

func TestAgentTeamMemoryResumeReminderPreservesCurrentText(t *testing.T) {
	require.Equal(t,
		"\n\nMemory: your previous context may be incomplete. Before resuming, recover only the context needed to continue the current or pending work from this workspace. Start with the configured memory index and the recovery files named in the Workspace & Memory instructions; if those are missing or insufficient, inspect relevant files, git state, task context, and recent history, then continue.",
		AgentTeamMemoryResumeReminder(),
	)
}
