package jin10

import (
	"context"
	"errors"
	"sort"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/extension/registry"
	"github.com/tidbcloud/AgentTeam/internal/extension/runner"
	"github.com/tidbcloud/AgentTeam/internal/service/extensionflow"
)

func TestExtensionPinsAuthDistributionAndDispatch(t *testing.T) {
	t.Parallel()

	ext, err := Extension(staticCredentialSource{
		credentials: runner.Credentials{"apiKey": "unused"},
	})
	require.NoError(t, err)
	require.Equal(t, Revision, ext.Implementation.Revision)
	require.Equal(t, registry.ConnectionRequired, ext.Implementation.ConnectionPolicy)
	require.Equal(t, runner.AuthBearer, ext.Implementation.Auth.Kind)
	require.Equal(t, []runner.CredentialField{
		runner.APIKeyField(
			"Jin10 API Key",
			"The Jin10 MCP API key from your Jin10 data service account.",
		),
	}, ext.Implementation.Auth.Fields)
	require.NotNil(t, ext.Implementation.ValidateCredentials)
	require.Equal(t, "app_jin10", ext.Distribution.AppID)
	require.Equal(t, "jin10", ext.Distribution.AppSlug)
	require.Equal(t, "/app-icons/jin10.svg", ext.Distribution.IconURL)
	require.True(t, ext.Distribution.GenericProviderConnection)

	lister, ok := ext.Implementation.Executor.(runner.ActionLister)
	require.True(t, ok)
	want := make([]string, 0, len(ext.Definition.Actions))
	for _, action := range ext.Definition.Actions {
		want = append(want, action.Name)
	}
	sort.Strings(want)
	require.Equal(t, want, lister.ActionNames())
}

func TestExecutorMapsClosedErrorsWithoutCredentialLeak(t *testing.T) {
	t.Parallel()

	client, err := newMCPClient(
		&mcpWireDouble{
			t:          t,
			credential: "never-reached",
		},
		allowedToolNames(),
		[]string{QuoteCodesResourceURI},
	)
	require.NoError(t, err)
	executor, err := newExecutor(
		staticCredentialSource{
			err: errors.New("database contained secret-token"),
		},
		client,
	)
	require.NoError(t, err)

	_, err = executor.Invoke(context.Background(), registry.BuiltinInvocation{
		WorkspaceID:           "workspace-1",
		ServiceInstallationID: "installation-1",
		Action:                ActionListCalendar,
		Input:                 []byte(`{}`),
	})
	code, ok := extensionflow.InvocationErrorCodeOf(err)
	require.True(t, ok)
	require.Equal(t, extensionflow.InvocationProviderAuthUnavailable, code)
	require.NotContains(t, err.Error(), "secret-token")

	_, err = executor.Invoke(context.Background(), registry.BuiltinInvocation{
		WorkspaceID:           "workspace-1",
		ServiceInstallationID: "installation-1",
		Action:                "call-tool",
		Input:                 []byte(`{}`),
	})
	code, ok = extensionflow.InvocationErrorCodeOf(err)
	require.True(t, ok)
	require.Equal(t, extensionflow.InvocationNotFound, code)
}
