package review

import (
	"context"
	"sort"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/store/agent"
)

func TestProjectPageUsesStableUpdatedAtIDCursor(t *testing.T) {
	ctx := context.Background()
	db := startReviewRollbackDB(t, ctx)
	seed := seedProjectTestWorkspace(t, ctx, db, "page_cursor")
	store := newProjectTestStore(db)
	updatedAt := time.Date(2026, 8, 1, 12, 0, 0, 0, time.UTC)

	projects := make([]agent.Project, 0, 3)
	for index, name := range []string{"Alpha", "Beta", "Gamma"} {
		project, err := store.CreateProjectForUser(ctx, seed.OwnerUserID, agent.CreateProjectParams{
			WorkspaceID: seed.WorkspaceID,
			MachineID:   "mac_page",
			RootPath:    "/repo/page-" + name,
			Name:        name,
			Visibility:  agent.ProjectVisibilityPrivate,
		})
		require.NoError(t, err)
		project.UpdatedAt = updatedAt.Add(-time.Duration(index/2) * time.Hour)
		_, err = db.Exec(ctx, `UPDATE projects SET updated_at = $1 WHERE id = $2`, project.UpdatedAt, project.ID)
		require.NoError(t, err)
		projects = append(projects, project)
	}

	expected := append([]agent.Project(nil), projects...)
	sort.Slice(expected, func(i, j int) bool {
		if expected[i].UpdatedAt.Equal(expected[j].UpdatedAt) {
			return expected[i].ID < expected[j].ID
		}
		return expected[i].UpdatedAt.After(expected[j].UpdatedAt)
	})

	var actual []agent.Project
	options := agent.ProjectListOptions{Limit: 1}
	for {
		page, err := store.ListProjectPageForUser(ctx, seed.OwnerUserID, seed.WorkspaceID, options)
		require.NoError(t, err)
		actual = append(actual, page.Projects...)
		if !page.HasMore {
			break
		}
		require.Len(t, page.Projects, 1)
		last := page.Projects[0]
		options.CursorUpdatedAt = last.UpdatedAt
		options.CursorID = last.ID
	}

	require.Equal(t, []string{expected[0].ID, expected[1].ID, expected[2].ID}, []string{actual[0].ID, actual[1].ID, actual[2].ID})
}

func TestProjectPageSearchesAndFiltersMachines(t *testing.T) {
	ctx := context.Background()
	db := startReviewRollbackDB(t, ctx)
	seed := seedProjectTestWorkspace(t, ctx, db, "page_filter")
	store := newProjectTestStore(db)

	for _, input := range []agent.CreateProjectParams{
		{WorkspaceID: seed.WorkspaceID, MachineID: "mac_online", RootPath: "/repo/agentteam-web", Name: "Web", Visibility: agent.ProjectVisibilityPrivate},
		{WorkspaceID: seed.WorkspaceID, MachineID: "mac_offline", RootPath: "/repo/docs", Name: "AgentTeam Docs", Visibility: agent.ProjectVisibilityPrivate},
		{WorkspaceID: seed.WorkspaceID, MachineID: "mac_online", RootPath: "/repo/other", Name: "Other", Visibility: agent.ProjectVisibilityPrivate},
	} {
		_, err := store.CreateProjectForUser(ctx, seed.OwnerUserID, input)
		require.NoError(t, err)
	}

	page, err := store.ListProjectPageForUser(ctx, seed.OwnerUserID, seed.WorkspaceID, agent.ProjectListOptions{
		Limit: 20,
		Query: "AGENTTEAM",
	})
	require.NoError(t, err)
	require.Len(t, page.Projects, 2)

	page, err = store.ListProjectPageForUser(ctx, seed.OwnerUserID, seed.WorkspaceID, agent.ProjectListOptions{
		Limit:      20,
		Query:      "AGENTTEAM",
		MachineIDs: []string{"mac_online"},
	})
	require.NoError(t, err)
	require.Len(t, page.Projects, 1)
	require.Equal(t, "/repo/agentteam-web", page.Projects[0].RootPath)

	page, err = store.ListProjectPageForUser(ctx, seed.OwnerUserID, seed.WorkspaceID, agent.ProjectListOptions{
		Limit:             20,
		ExcludeMachineIDs: []string{"mac_online"},
	})
	require.NoError(t, err)
	require.Len(t, page.Projects, 1)
	require.Equal(t, "mac_offline", page.Projects[0].MachineID)
}
