package dispatcher

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/desktop/internal/agent"
	"github.com/tidbcloud/AgentTeam/desktop/internal/consts"
	"github.com/tidbcloud/AgentTeam/desktop/internal/types"
	"github.com/tidbcloud/AgentTeam/desktop/internal/wire/manager"
)

type wakeFallbackChannel struct {
	id      string
	events  []types.AgentEvent
	meta    types.Metadata
	message types.OutboundMessage
	sends   chan types.OutboundMessage
}

func (c *wakeFallbackChannel) ID() string                  { return c.id }
func (c *wakeFallbackChannel) Enabled() bool               { return true }
func (c *wakeFallbackChannel) Start(context.Context) error { return nil }
func (c *wakeFallbackChannel) Stop(context.Context) error  { return nil }
func (c *wakeFallbackChannel) Send(_ context.Context, meta types.Metadata, msg types.OutboundMessage) error {
	c.meta = meta
	c.message = msg
	if c.sends != nil {
		c.sends <- msg
	}
	return nil
}
func (c *wakeFallbackChannel) Emit(event types.AgentEvent) {
	c.events = append(c.events, event)
}

func TestWakeStatusCallbackDoesNotRelayDMDirectOutput(t *testing.T) {
	manager := manager.New(nil, nil)
	ch := &wakeFallbackChannel{id: "agentteam", sends: make(chan types.OutboundMessage, 1)}
	manager.Register(ch)
	d := &Dispatcher{
		serverConnections: manager,
		sessionManager:    NewSessionManager(),
	}
	callback := d.buildWakeStatusCallback("agentteam", "server-agent")
	require.NotNil(t, callback)

	callback(agent.WakeStatusEvent{
		MessageID: "msg-1",
		WakeToken: "wake-1",
		Target:    "dm:@owner",
		Status:    consts.WakeStatusCompletedWithoutVisibleReply,
	})

	select {
	case sent := <-ch.sends:
		t.Fatalf("direct runtime text fallback should not be sent as a AgentTeam message: %#v", sent)
	case <-time.After(50 * time.Millisecond):
	}
	require.Empty(t, ch.message.Content)
}

func TestWakeStatusFailedDoesNotSendFallbackMessage(t *testing.T) {
	d := mustNewDispatcher("http://server.test")
	defer d.Close()
	ch := &wakeFallbackChannel{id: "agentteam"}
	d.serverConnections.Register(ch)

	callback := d.buildWakeStatusCallback("agentteam", "server-agent")
	require.NotNil(t, callback)
	callback(agent.WakeStatusEvent{
		MessageID: "msg-1",
		WakeToken: "wake-1",
		Target:    "#ops",
		Status:    consts.WakeStatusFailed,
		Detail:    "runtime said no",
	})

	require.Empty(t, ch.message.Content)
	require.Len(t, ch.events, 1)
	wakeStatus, ok := ch.events[0].(types.WakeStatusEvent)
	require.True(t, ok)
	require.Equal(t, consts.WakeStatusFailed, wakeStatus.Status)
	require.Equal(t, "runtime said no", wakeStatus.Detail)
}
