package mcp

import (
	"encoding/json"
	"os"
	"path/filepath"
	"testing"
)

type agentteamInventoryRow struct {
	Tool string `json:"tool"`
}

func TestAgentTeamToolDefsAreCoveredByToolInventory(t *testing.T) {
	tools := loadAgentTeamToolInventory(t)

	for _, def := range MessageToolDefs() {
		tool, ok := agentteamToolInventoryTool(def.Name)
		if !ok {
			t.Fatalf("agentteam MCP tool %q is not classified for tool inventory coverage", def.Name)
		}
		if _, ok := tools[tool]; !ok {
			t.Fatalf("agentteam MCP tool %q maps to missing inventory tool %q", def.Name, tool)
		}
	}
}

func TestAgentTeamMCPInventoryMatchesMessageTools(t *testing.T) {
	defs := MessageToolDefs()
	if len(defs) != len(expectedMCPToolNames()) {
		t.Fatalf("AgentTeam MCP inventory has %d tools, want resolved %d", len(defs), len(expectedMCPToolNames()))
	}

	got := make(map[string]struct{}, len(defs))
	for _, def := range defs {
		got[def.Name] = struct{}{}
	}
	for _, name := range expectedMCPToolNames() {
		if _, ok := got[name]; !ok {
			t.Fatalf("AgentTeam MCP inventory missing resolved tool %q", name)
		}
	}
}

func TestAgentTeamAggregateIncludesKBRetrievalTools(t *testing.T) {
	message := &mcpHandler{}
	kb, err := NewKBHandler(KBHandlerConfig{Connection: testAgentTeamProtocol{}, Runtime: testKBDispatcher{}})
	if err != nil {
		t.Fatal(err)
	}
	agg, err := NewAgentTeamHandler(message, nil, kb)
	if err != nil {
		t.Fatal(err)
	}

	names := make(map[string]struct{}, len(agg.Tools()))
	for _, def := range agg.Tools() {
		names[def.Name] = struct{}{}
	}
	for _, name := range []string{"kb_search", "kb_fetch"} {
		if _, ok := names[name]; !ok {
			t.Fatalf("AgentTeam aggregate missing KB retrieval tool %q", name)
		}
	}
}

func loadAgentTeamToolInventory(t *testing.T) map[string]struct{} {
	t.Helper()
	path := filepath.Clean(filepath.Join("..", "..", "..", "..", "specs", "daemon", "agent-mcp-tool-inventory.json"))
	data, err := os.ReadFile(path)
	if err != nil {
		t.Fatalf("read resolved inventory %s: %v", path, err)
	}
	var rows []agentteamInventoryRow
	if err := json.Unmarshal(data, &rows); err != nil {
		t.Fatalf("unmarshal resolved inventory: %v", err)
	}
	tools := make(map[string]struct{}, len(rows))
	for _, row := range rows {
		tools[row.Tool] = struct{}{}
	}
	return tools
}

func agentteamToolInventoryTool(name string) (string, bool) {
	switch name {
	case "message_history_read":
		return "message_history_read", true
	case "message_reaction_list":
		return "message_reaction_list", true
	case "message_attachment_view":
		return "message_attachment_view", true
	case "message_search":
		return "message_search", true
	case "message_send":
		return "message_send held-refresh", true
	case "message_reaction_set", "message_attachment_upload":
		return "mutations payloads", true
	default:
		return "", false
	}
}
