package agent

import (
	"net/http"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/core/domain"
	storeagent "github.com/tidbcloud/AgentTeam/internal/store/agent"
)

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

	gin.SetMode(gin.TestMode)
	router := gin.New()
	targetStore := &expectedTaskTargetStore{}
	board := &expectedTaskBoardService{}
	RegisterRoutes(router, Dependencies{
		Auth:               fakeAgentAuthenticator{agent: storeagent.AuthenticatedAgent{AgentID: "agt_0000000000test", WorkspaceID: "wsp_test", MemberID: "00000000test"}},
		TaskBoard:          board,
		TaskTargetResolver: targetStore,
	})
	response := agentTaskRequest(t, router, http.MethodPost, "/tasks", map[string]any{
		"parentTaskScope": map[string]any{
			"kind":    "task",
			"scopeId": "tsk_parent_scope",
		},
		"target": "#agentteam:f6997aed",
		"tasks":  []map[string]any{{"title": "child one"}, {"title": "child two"}},
	})

	require.Equal(t, http.StatusOK, response.Code, response.Body.String())
	require.NotNil(t, board.createSubtasksRequest.ParentTaskScope)
	require.Equal(t, domain.MessageScopeValue{
		Kind:    domain.MessageScopeKindTask,
		ScopeID: "tsk_parent_scope",
	}, *board.createSubtasksRequest.ParentTaskScope)
	require.Empty(t, board.createSubtasksRequest.Board)
	require.Empty(t, board.createSubtasksRequest.Task)
	require.Equal(t, []string{"child one", "child two"}, board.createSubtasksRequest.Titles)
	require.Equal(t, "chn_1", board.createSubtasksRequest.SourceChannelID)
	require.NotNil(t, board.createSubtasksRequest.Metadata)
	require.Equal(t, "thr_1", board.createSubtasksRequest.Metadata.SourceThreadChannelID)
	require.Equal(t, "msg_thread_root", board.createSubtasksRequest.Metadata.SourceThreadParentMessageID)
	require.Equal(t, "#agentteam:f6997aed", board.createSubtasksRequest.Metadata.SourceThreadRef)
	require.Equal(t, "#agentteam:f6997aed", targetStore.lastResolvedTarget)
	require.Zero(t, board.createRequest.Board)
}

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

	tests := map[string]map[string]any{
		"with channel": {
			"channel": "#agentteam",
			"parentTaskScope": map[string]any{
				"kind": "task", "scopeId": "tsk_parent_scope",
			},
			"tasks": []map[string]any{{"title": "child"}},
		},
		"with parent": {
			"parent": 5,
			"parentTaskScope": map[string]any{
				"kind": "task", "scopeId": "tsk_parent_scope",
			},
			"tasks": []map[string]any{{"title": "child"}},
		},
		"non-task kind": {
			"parentTaskScope": map[string]any{
				"kind": "channel", "scopeId": "chn_parent",
			},
			"tasks": []map[string]any{{"title": "child"}},
		},
		"malformed scope": {
			"parentTaskScope": map[string]any{
				"kind": "task", "scopeId": "bad scope",
			},
			"tasks": []map[string]any{{"title": "child"}},
		},
		"missing scope id": {
			"parentTaskScope": map[string]any{
				"kind": "task",
			},
			"tasks": []map[string]any{{"title": "child"}},
		},
		"unknown scope field": {
			"parentTaskScope": map[string]any{
				"kind": "task", "scopeId": "tsk_parent_scope", "extra": true,
			},
			"tasks": []map[string]any{{"title": "child"}},
		},
	}
	for name, body := range tests {
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			board := &expectedTaskBoardService{}
			response := agentTaskRequest(t, expectedTaskTestRouter(board), http.MethodPost, "/tasks", body)
			require.Equal(t, http.StatusBadRequest, response.Code, response.Body.String())
			require.Nil(t, board.createSubtasksRequest.ParentTaskScope)
			require.Zero(t, board.createRequest.Board)
		})
	}
}
