package session

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"
	sessionapi "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/api/agent-gateway/session/v1"
	sessionentity "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/agent-gateway/session/v1"
	serviceapi "github.com/tidbcloud/aisupport/services/agent-gateway/internal/services/session/api"
	"go.uber.org/mock/gomock"
)

func TestHandlerListSessionsMapsRequestToServiceOptions(t *testing.T) {
	service := serviceapi.NewMockService(gomock.NewController(t))
	sessions := []*sessionentity.Session{{SessionId: "session-1"}}
	service.EXPECT().ListSessions(gomock.Any(), serviceapi.ListSessionsOptions{
		SessionID:           "session-1",
		SourceType:          sessionentity.MessageSourceType_MESSAGE_SOURCE_TYPE_LARK,
		SourceInstanceID:    "lark-bot",
		SourceSessionKey:    "chat:thread",
		InitiatorEmail:      "user@example.com",
		LarkChatID:          "chat",
		LarkThreadID:        "thread",
		LarkAnchorMessageID: "root",
		LarkEntryMessageID:  "first",
		Status:              sessionentity.SessionStatus_SESSION_STATUS_ACTIVE,
		Page:                2,
		PageSize:            20,
	}).Return(sessions, nil)
	handler := &Handler{service: service}

	resp, err := handler.ListSessions(context.Background(), &sessionapi.ListSessionsRequest{
		SessionId:        "session-1",
		SourceType:       sessionentity.MessageSourceType_MESSAGE_SOURCE_TYPE_LARK,
		SourceInstanceId: "lark-bot",
		SourceSessionKey: "chat:thread",
		InitiatorEmail:   "user@example.com",
		Lark: &sessionapi.LarkSessionFilter{
			ChatId:          "chat",
			ThreadId:        "thread",
			AnchorMessageId: "root",
			EntryMessageId:  "first",
		},
		Status:   sessionentity.SessionStatus_SESSION_STATUS_ACTIVE,
		Page:     2,
		PageSize: 20,
	})

	require.NoError(t, err)
	require.Equal(t, sessions, resp.Sessions)
}

func TestHandlerGetSessionReturnsFoundFlag(t *testing.T) {
	service := serviceapi.NewMockService(gomock.NewController(t))
	session := &sessionentity.Session{SessionId: "session-1"}
	service.EXPECT().GetSession(gomock.Any(), "session-1").Return(session, true, nil)
	handler := &Handler{service: service}

	resp, err := handler.GetSession(context.Background(), &sessionapi.GetSessionRequest{
		SessionId: "session-1",
	})

	require.NoError(t, err)
	require.True(t, resp.Found)
	require.Equal(t, session, resp.Session)
}

func TestHandlerGetSessionReturnsMissing(t *testing.T) {
	service := serviceapi.NewMockService(gomock.NewController(t))
	service.EXPECT().GetSession(gomock.Any(), "missing").Return(nil, false, nil)
	handler := &Handler{service: service}

	resp, err := handler.GetSession(context.Background(), &sessionapi.GetSessionRequest{
		SessionId: "missing",
	})

	require.NoError(t, err)
	require.False(t, resp.Found)
	require.Nil(t, resp.Session)
}

func TestHandlerListSessionTasksPassesLimit(t *testing.T) {
	service := serviceapi.NewMockService(gomock.NewController(t))
	tasks := []*sessionentity.Task{{TaskId: "task"}}
	service.EXPECT().ListSessionTasks(gomock.Any(), "session-1", 5).Return(tasks, nil)
	handler := &Handler{service: service}

	resp, err := handler.ListSessionTasks(context.Background(), &sessionapi.ListSessionTasksRequest{
		SessionId: "session-1",
		Limit:     5,
	})

	require.NoError(t, err)
	require.Equal(t, tasks, resp.Tasks)
}

func TestHandlerDeleteSessionPassesSessionID(t *testing.T) {
	service := serviceapi.NewMockService(gomock.NewController(t))
	service.EXPECT().DeleteSession(gomock.Any(), "session-1").Return(nil)
	handler := &Handler{service: service}

	resp, err := handler.DeleteSession(context.Background(), &sessionapi.DeleteSessionRequest{
		SessionId: "session-1",
	})

	require.NoError(t, err)
	require.NotNil(t, resp)
}
