package agent

import (
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/desktop/internal/types"
)

func TestDecideProcessDelivery(t *testing.T) {
	tests := []struct {
		name string
		in   deliveryDecisionInput
		want deliveryDecision
	}{
		{
			name: "protocol direct delivery wins over stdin paths",
			in: deliveryDecisionInput{
				HasProtocolMessageDriver:  true,
				SupportsStdinNotification: true,
				HasSession:                true,
				IsIdle:                    true,
			},
			want: deliveryDecision{Kind: deliveryDecisionProtocol},
		},
		{
			name: "protocol delivery queues during active turn",
			in: deliveryDecisionInput{
				HasProtocolMessageDriver:  true,
				SupportsBusyStdinDelivery: false,
				SupportsStdinNotification: true,
				HasSession:                true,
				IsIdle:                    false,
			},
			want: deliveryDecision{Kind: deliveryDecisionQueue},
		},
		{
			name: "acked active-turn direct delivery wins over queue",
			in: deliveryDecisionInput{
				HasAckedBusyRuntimeInputDriver: true,
				SupportsStdinNotification:      true,
				HasSession:                     true,
				IsIdle:                         false,
			},
			want: deliveryDecision{Kind: deliveryDecisionAckedBusy},
		},
		{
			name: "acked active-turn direct delivery wins over transport-only busy protocol",
			in: deliveryDecisionInput{
				HasProtocolMessageDriver:       true,
				SupportsBusyStdinDelivery:      true,
				HasAckedBusyRuntimeInputDriver: true,
				SupportsStdinNotification:      true,
				HasSession:                     true,
				IsIdle:                         false,
			},
			want: deliveryDecision{Kind: deliveryDecisionAckedBusy},
		},
		{
			name: "protocol delivery can accept busy turn input when driver supports it",
			in: deliveryDecisionInput{
				HasProtocolMessageDriver:  true,
				SupportsBusyStdinDelivery: true,
				SupportsStdinNotification: true,
				HasSession:                true,
				IsIdle:                    false,
			},
			want: deliveryDecision{Kind: deliveryDecisionProtocol},
		},
		{
			name: "idle stdin delivery",
			in: deliveryDecisionInput{
				SupportsStdinNotification: true,
				HasSession:                true,
				IsIdle:                    true,
			},
			want: deliveryDecision{Kind: deliveryDecisionIdle},
		},
		{
			name: "busy stdin queues after first turn",
			in: deliveryDecisionInput{
				SupportsStdinNotification: true,
				HasSession:                true,
			},
			want: deliveryDecision{Kind: deliveryDecisionQueue},
		},
		{
			name: "queue when process is not running",
			in: deliveryDecisionInput{
				SupportsStdinNotification: true,
				HasSession:                true,
			},
			want: deliveryDecision{Kind: deliveryDecisionQueue},
		},
		{
			name: "queue when session is missing",
			in: deliveryDecisionInput{
				SupportsStdinNotification: true,
			},
			want: deliveryDecision{Kind: deliveryDecisionQueue},
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			require.Equal(t, tc.want, decideProcessDelivery(tc.in))
		})
	}
}

func TestRequeueInboxMessage(t *testing.T) {
	existing := []types.InboxMessage{{MessageID: "next"}}
	retry := types.InboxMessage{MessageID: "retry"}

	require.Equal(t,
		[]types.InboxMessage{{MessageID: "retry"}, {MessageID: "next"}},
		requeueInboxMessage(existing, retry, true),
	)
	require.Equal(t,
		[]types.InboxMessage{{MessageID: "next"}, {MessageID: "retry"}},
		requeueInboxMessage(existing, retry, false),
	)
}
