package exec

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/desktop/internal/wire/apiclient"
)

func TestProjectRemotePageFollowsContinuationCursor(t *testing.T) {
	calls := 0
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		calls++
		require.Equal(t, http.MethodGet, r.Method)
		if calls == 1 {
			require.Equal(t, "1", r.URL.Query().Get("limit"))
			require.Empty(t, r.URL.Query().Get("cursor"))
			_, _ = io.WriteString(w, `{"projects":[{"id":"prj_1","rootPath":"/repo","name":"Repo"}],"hasMore":true,"nextCursor":"project-next"}`)
			return
		}
		require.Equal(t, "project-next", r.URL.Query().Get("cursor"))
		_, _ = io.WriteString(w, `{"projects":[],"hasMore":false}`)
	}))
	defer server.Close()
	remote := projectRemote{client: &apiclient.Client{ServerURL: server.URL, AgentID: "ag", AuthToken: "tok", RouteWorkspaceID: "ws", HTTPClient: server.Client()}}

	first, err := remote.listPage(context.Background(), projectListRequest{Limit: 1})
	require.NoError(t, err)
	require.True(t, first.HasMore)
	require.Equal(t, "project-next", first.NextCursor)
	second, err := remote.listPage(context.Background(), projectListRequest{Limit: 1, Cursor: first.NextCursor})
	require.NoError(t, err)
	require.Empty(t, second.Projects)
	require.False(t, second.HasMore)
}

func TestTeamRemotePageForwardsQueryAndCursor(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "backend", r.URL.Query().Get("q"))
		require.Equal(t, "2", r.URL.Query().Get("limit"))
		require.Equal(t, "team-next", r.URL.Query().Get("cursor"))
		_, _ = io.WriteString(w, `{"teams":[],"hasMore":false}`)
	}))
	defer server.Close()
	remote := teamRemote{client: &apiclient.Client{ServerURL: server.URL, AgentID: "ag", AuthToken: "tok", RouteWorkspaceID: "ws", HTTPClient: server.Client()}}

	page, err := remote.list(context.Background(), teamListInput{Query: "backend", Limit: 2, Cursor: "team-next"})
	require.NoError(t, err)
	require.Empty(t, page.Teams)
	require.False(t, page.HasMore)
}

func TestReviewRemotePageForwardsCursorAndRetainsEmptyFinalPage(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case http.MethodPost:
			_, _ = io.WriteString(w, `{"scopeId":"thread-1"}`)
		case http.MethodGet:
			require.Equal(t, "1", r.URL.Query().Get("limit"))
			require.Equal(t, "review-next", r.URL.Query().Get("cursor"))
			_, _ = io.WriteString(w, `{"contexts":[],"hasMore":false}`)
		default:
			t.Fatalf("unexpected method %s", r.Method)
		}
	}))
	defer server.Close()
	remote := reviewRemote{client: &apiclient.Client{ServerURL: server.URL, AgentID: "ag", AuthToken: "tok", RouteWorkspaceID: "ws", HTTPClient: server.Client(), TargetResolver: apiclient.NewTargetResolver()}}

	page, err := remote.listPage(context.Background(), "#ops:thread", reviewListRequest{Limit: 1, Cursor: "review-next"})
	require.NoError(t, err)
	require.Empty(t, page.Contexts)
	require.False(t, page.HasMore)
}

func TestScheduledMessageRunsRemotePageForwardsCursor(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "1", r.URL.Query().Get("limit"))
		require.Equal(t, "run-next", r.URL.Query().Get("cursor"))
		_, _ = fmt.Fprint(w, `{"runs":[],"hasMore":false}`)
	}))
	defer server.Close()
	remote := scheduledMessageRemote{client: &apiclient.Client{ServerURL: server.URL, AgentID: "ag", AuthToken: "tok", RouteWorkspaceID: "ws", HTTPClient: server.Client()}}

	page, err := remote.runsPage(context.Background(), scheduledMessageRunsRequest{ID: "sch_1", Limit: 1, Cursor: "run-next"})
	require.NoError(t, err)
	require.Empty(t, page.Runs)
	require.False(t, page.HasMore)
}
