package taskboard

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestTaskTimelineActivityPageQueryScopesActivityReadsToTaskTarget(t *testing.T) {
	query, args := taskTimelineActivityPageQuery("tsk_1", TaskTimelineCursor{}, 26)

	require.Equal(t, []any{"tsk_1"}, args)
	require.Contains(t, query, "WITH task_target AS (")
	require.Contains(t, query, "message_candidates AS (")
	require.Contains(t, query, "activity_candidates AS (")
	require.Contains(t, query, "FROM task_target t\n  JOIN scope_messages sm")
	require.Contains(t, query, "FROM task_target t\n  JOIN scope_activity_events ae")
	require.Contains(t, query, "FROM page_candidates timeline")
	require.Contains(t, query, "FROM activity_candidates discussion_activity")
	require.Contains(t, query, "sm.id = discussion_activity.source_message_id")
	require.Contains(t, query, "FROM scope_activity_events canonical_discussion_activity")
	require.Contains(t, query, "LIMIT 26")
	require.NotContains(t, query, "FROM scope_activity_events ae\n  WHERE ae.activity_ref_type = 'task_event'")
	require.NotContains(t, query, "FROM tasks t\nJOIN scope_messages sm")
}

func TestTaskTimelineActivityPageQueryUsesCanonicalParentAuthority(t *testing.T) {
	query, args := taskTimelineActivityPageQuery("tsk_1", TaskTimelineCursor{}, 26, "wsp_1")

	require.Equal(t, []any{"wsp_1", "tsk_1"}, args)
	require.Contains(t, query, "JOIN task_boards task_board")
	require.Contains(t, query, "task_board.channel_id")
	require.Contains(t, query, "t.channel_id = task_board.channel_id")
	require.Contains(t, query, "task_scope.status = 'active'")
	require.Contains(t, query, "task_channel.status = 'active'")
}

func TestTaskTimelineActivityPageQueryCursorKeepsTaskTargetPlaceholder(t *testing.T) {
	cursorTime := time.Date(2026, 6, 5, 10, 0, 0, 0, time.UTC)
	query, args := taskTimelineActivityPageQuery("tsk_1", TaskTimelineCursor{
		ID:        "tev_1",
		CreatedAt: cursorTime,
	}, 26)

	require.Equal(t, []any{"tsk_1", "tev_1", cursorTime}, args)
	require.Contains(t, query, "WHERE id = $1")
	require.Contains(t, query, "ON cursor_timeline.id = $2")
	require.Contains(t, query, "timeline.created_at < $3")
	require.Contains(t, query, "timeline.id < $2")
}

func TestTaskTimelineActivityPageQueryV2CursorBoundsBothSources(t *testing.T) {
	cursorTime := time.Date(2026, 6, 5, 10, 0, 0, 0, time.UTC)
	query, args := taskTimelineActivityPageQuery("tsk_1", TaskTimelineCursor{
		Seq:       42,
		ID:        "tev_1",
		CreatedAt: cursorTime,
	}, 26, "wsp_1")

	require.Equal(t, []any{"wsp_1", "tsk_1", int64(42), "tev_1"}, args)
	require.Contains(t, query, "sm.seq < $3")
	require.Contains(t, query, "sm.id < $4")
	require.Contains(t, query, "ae.seq < $3")
	require.Contains(t, query, "ae.id < $4")
	require.NotContains(t, query, "cursor_timeline")
}

func TestTaskDetailReadModesKeepLegacyTimelineAndAllowNarrowReads(t *testing.T) {
	ctx := context.Background()
	fixture := seedTaskboardUserFixture(t, ctx)

	created, err := fixture.service.CreateTasks(ctx, CreateTasksRequest{
		Context: NewUserServiceContext(fixture.workspaceID, fixture.ownerUserID, fixture.ownerDisplayName),
		Board:   BoardRef{ChannelID: fixture.channelID},
		Titles:  []string{"Load Task detail independently"},
	})
	require.NoError(t, err)
	require.Len(t, created.Tasks, 1)
	taskRef := TaskRef{TaskID: created.Tasks[0].ID}
	serviceContext := NewUserServiceContext(fixture.workspaceID, fixture.ownerUserID, fixture.ownerDisplayName)

	legacy, err := fixture.service.GetTaskDetail(ctx, GetTaskDetailRequest{
		Context: serviceContext,
		Task:    taskRef,
	})
	require.NoError(t, err)
	require.NotEmpty(t, legacy.Detail.Timeline)

	withoutTimeline, err := fixture.service.GetTaskDetail(ctx, GetTaskDetailRequest{
		Context:      serviceContext,
		Task:         taskRef,
		SkipTimeline: true,
	})
	require.NoError(t, err)
	require.Equal(t, created.Tasks[0].ID, withoutTimeline.Detail.Task.ID)
	require.Empty(t, withoutTimeline.Detail.Timeline)

	taskOnly, err := fixture.service.GetTaskDetail(ctx, GetTaskDetailRequest{
		Context:  serviceContext,
		Task:     taskRef,
		TaskOnly: true,
	})
	require.NoError(t, err)
	require.Equal(t, created.Tasks[0].ID, taskOnly.Detail.Task.ID)
	require.Empty(t, taskOnly.Detail.Timeline)
	require.Empty(t, taskOnly.Detail.Subtasks)
	require.Empty(t, taskOnly.Detail.Checkpoints)
}
