package fanout

import (
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/store/message"
)

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

	for _, mutation := range []struct {
		name string
		run  func(DeliveryFanout)
	}{
		{
			name: "add",
			run: func(deliveryFanout DeliveryFanout) {
				deliveryFanout.DeliverReactionAdded(
					t.Context(),
					"wsp_task_reaction",
					"msg_task_reaction",
					message.AddReactionResult{
						Changed:     true,
						ChannelID:   "tsk_task_reaction",
						ChannelType: message.ConversationKindTask,
						Delivery: &message.ReactionDelivery{
							Recipient: message.AgentRecipient{AgentID: "agt_reaction"},
							Seq:       9,
						},
					},
					[]message.MessageReactionAggregate{{Emoji: "👍", Count: 1}},
				)
			},
		},
		{
			name: "remove",
			run: func(deliveryFanout DeliveryFanout) {
				deliveryFanout.DeliverReactionRemoved(
					t.Context(),
					"wsp_task_reaction",
					"msg_task_reaction",
					message.RemoveReactionResult{
						Changed:     true,
						ChannelID:   "tsk_task_reaction",
						ChannelType: message.ConversationKindTask,
					},
					nil,
				)
			},
		},
	} {
		mutation := mutation
		t.Run(mutation.name, func(t *testing.T) {
			t.Parallel()

			guard := &taskScopeLifecycleGuardStub{}
			notifier := &capturingNotifier{}
			realtime := &fakeRealtime{}
			deliveryFanout := NewDeliveryFanout(notifier, realtime, nil).
				WithTaskScopeLifecycleGuard(guard)

			mutation.run(deliveryFanout)

			require.Equal(t, []taskScopeLifecycleGuardCall{{
				workspaceID: "wsp_task_reaction",
				scopeID:     "tsk_task_reaction",
			}}, guard.calls)
			require.Zero(t, guard.callbackCalls)
			require.Empty(t, notifier.messages)
			require.Empty(t, realtime.reactionChanged)
		})
	}
}

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

	guard := &taskScopeLifecycleGuardStub{}
	notifier := &capturingNotifier{}
	realtime := &fakeRealtime{}
	deliveryFanout := NewDeliveryFanout(notifier, realtime, nil).
		WithTaskScopeLifecycleGuard(guard)

	deliveryFanout.DeliverReactionAdded(
		t.Context(),
		"wsp_reaction",
		"msg_reaction",
		message.AddReactionResult{
			Changed:     true,
			ChannelID:   "chn_reaction",
			ChannelType: message.ConversationKindChannel,
			Delivery: &message.ReactionDelivery{
				Recipient: message.AgentRecipient{AgentID: "agt_reaction"},
				Seq:       9,
			},
		},
		nil,
	)

	require.Empty(t, guard.calls)
	require.Zero(t, guard.callbackCalls)
	require.Len(t, notifier.messages, 1)
	require.Equal(t, []string{"chn_reaction:msg_reaction"}, realtime.reactionChanged)
}
