package acp_test

import (
	"context"
	"testing"

	"github.com/google/uuid"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/yan1h/agent-coding-workflow/internal/acp"
	"github.com/yan1h/agent-coding-workflow/internal/infra/errs"
)

func TestAgentKindService_MCPServers_Validation(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	svc := acp.NewAgentKindService(newFakeAgentKindRepo(), testEncryptor(t), nil)
	admin := acp.Caller{UserID: uuid.New(), IsAdmin: true}

	base := acp.CreateAgentKindInput{Name: "k", DisplayName: "K", BinaryPath: "/x", Enabled: true}

	cases := []struct {
		name    string
		servers []acp.McpServerSpec
	}{
		{"missing name", []acp.McpServerSpec{{Type: acp.McpStdio, Command: "/x"}}},
		{"reserved acw name", []acp.McpServerSpec{{Name: "acw", Type: acp.McpHTTP, URL: "http://x"}}},
		{"duplicate name", []acp.McpServerSpec{
			{Name: "d", Type: acp.McpStdio, Command: "/x"},
			{Name: "d", Type: acp.McpHTTP, URL: "http://x"},
		}},
		{"stdio without command", []acp.McpServerSpec{{Name: "a", Type: acp.McpStdio}}},
		{"http without url", []acp.McpServerSpec{{Name: "a", Type: acp.McpHTTP}}},
		{"invalid type", []acp.McpServerSpec{{Name: "a", Type: "magic"}}},
	}
	for _, tc := range cases {
		in := base
		in.MCPServers = tc.servers
		_, err := svc.Create(ctx, admin, in)
		ae, ok := errs.As(err)
		require.True(t, ok, "case %s should fail", tc.name)
		assert.Equal(t, errs.CodeInvalidInput, ae.Code, "case %s", tc.name)
	}
}

func TestAgentKindService_MCPServers_CreateAndUpdate(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	svc := acp.NewAgentKindService(newFakeAgentKindRepo(), testEncryptor(t), nil)
	admin := acp.Caller{UserID: uuid.New(), IsAdmin: true}

	k, err := svc.Create(ctx, admin, acp.CreateAgentKindInput{
		Name: "k", DisplayName: "K", BinaryPath: "/x", Enabled: true,
		MCPServers: []acp.McpServerSpec{
			{Name: "ctx7", Type: acp.McpHTTP, URL: "https://mcp.ctx7.dev", Headers: map[string]string{"X-Key": "v"}},
		},
	})
	require.NoError(t, err)
	assert.NotEmpty(t, k.EncryptedMCPServers) // 已加密落库

	// nil = 不改
	updated, err := svc.Update(ctx, admin, k.ID, acp.UpdateAgentKindInput{})
	require.NoError(t, err)
	assert.Equal(t, k.EncryptedMCPServers, updated.EncryptedMCPServers)

	// 空列表 = 清空
	updated, err = svc.Update(ctx, admin, k.ID, acp.UpdateAgentKindInput{MCPServers: []acp.McpServerSpec{}})
	require.NoError(t, err)
	assert.NotEqual(t, k.EncryptedMCPServers, updated.EncryptedMCPServers)
}
