package server

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/extension/providers/mail/mailruntime"
	"github.com/tidbcloud/AgentTeam/internal/service/extensionflow"
	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
)

// TestMailInvocationAuthorizerFailsClosedWhileUnbound proves the fresh
// authorization fence denies every mutation before a profile owning the
// authoritative resolver binds the holder: the wiring order constructs the
// Mail runtime before the extensionflow catalog service, so the unbound
// window must never admit an invocation.
func TestMailInvocationAuthorizerFailsClosedWhileUnbound(t *testing.T) {
	t.Parallel()

	authorizer := &mailInvocationAuthorizer{}
	err := authorizer.ReauthorizeInvocation(
		context.Background(),
		mailruntime.InvocationAuthorization{
			WorkspaceID:          "wsp_1",
			AgentID:              "agt_1",
			AgentMemberID:        "mem_1",
			AuthorizedByMemberID: "mem_authorizer",
			InstallationID:       "inst_1",
			ConnectionID:         "conn_1",
			ConnectionGeneration: "gen_1",
			SelectionID:          "sel_1",
			ExtensionName:        "mail",
			Action:               "send-draft",
			DefinitionVersion:    1,
			DefinitionDigest:     "sha256:abc",
			CatalogVersion:       7,
		},
	)
	require.ErrorIs(t, err, storeerr.ErrForbidden)
	require.Contains(
		t,
		err.Error(),
		"resolver is not bound",
	)
}

// TestMailInvocationAuthorizerBindsOnceAndDelegates proves the holder keeps
// delegating to the bound resolver after bind, instead of staying on the
// unbound default-deny fence.
func TestMailInvocationAuthorizerBindsOnceAndDelegates(t *testing.T) {
	t.Parallel()

	authorizer := &mailInvocationAuthorizer{}
	authorizer.Bind(extensionflow.New(nil, nil, nil, extensionflow.Options{}))

	err := authorizer.ReauthorizeInvocation(
		context.Background(),
		mailruntime.InvocationAuthorization{},
	)
	// The empty envelope cannot be authorized by the resolver; the point is
	// that the call reaches the resolver instead of the unbound fence.
	require.Error(t, err)
	require.NotContains(t, err.Error(), "not bound")
}
