package gateway

import (
	"sort"
	"strings"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/api/llm"
	"github.com/tidbcloud/AgentTeam/internal/apr/runtime"
	"github.com/tidbcloud/AgentTeam/internal/router"
)

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

	logger := newDiscardLogger()
	workspaceRouter := router.NewRouterForProfile(router.ProfileWorkspace, router.Dependencies{
		Logger: logger,
		API: router.APIDependencies{
			LLM: llm.Dependencies{APRDispatcher: runtime.NewDispatcher()},
		},
	})

	missing := make([]string, 0)
	for _, route := range workspaceRouter.Routes() {
		if strings.HasPrefix(route.Path, "/internal/agent/") {
			continue
		}
		policy, ok := router.EdgePolicyForRoute(router.ProfileWorkspace, route.Method, route.Path)
		require.True(t, ok, route.Method+" "+route.Path)
		if policy != router.EdgePolicyWorkspaceREST || !strings.HasPrefix(route.Path, "/api/v1/workspaces/:workspaceId/") {
			continue
		}
		path := strings.Replace(route.Path, "/:workspaceId/", "/wsp_contract/", 1)
		if _, ok := workspaceV1IMRoute(path); !ok {
			missing = append(missing, route.Method+" "+route.Path)
		}
	}
	sort.Strings(missing)
	require.Empty(t, missing)
}

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

	deletedPaths := []string{
		"/api/v1/workspaces/wsp_1/workflows",
		"/api/v1/workspaces/wsp_1/workflows:validate",
		"/api/v1/workspaces/wsp_1/workflows/wf_1",
		"/api/v1/workspaces/wsp_1/workflows/wf_1/runs/run_1/events",
	}
	for _, path := range deletedPaths {
		path := path
		t.Run(path, func(t *testing.T) {
			t.Parallel()
			_, ok := workspaceV1IMRoute(path)
			require.False(t, ok,
				"gateway allowlist must not recognize deleted legacy Workflow surface %q", path)
		})
	}
}

// TestWorkspaceV1IMRouteRejectsDeletedDirectoryRoutes pins the inverse of
// TestWorkspaceV1IMRouteCoversWorkspaceRESTRouteFamilies for the deleted
// Directory surface: once the backend /api/v1/workspaces/:workspaceId/directories*
// routes are removed, the gateway allowlist MUST NOT continue to recognize
// those paths. A stale allowlist entry would route ghost traffic to the
// workspace upstream even though no handler exists, masking the removal at
// the edge layer.
func TestWorkspaceV1IMRouteRejectsDeletedDirectoryRoutes(t *testing.T) {
	t.Parallel()

	deletedPaths := []string{
		"/api/v1/workspaces/wsp_1/directories",
		"/api/v1/workspaces/wsp_1/directories/browse",
		"/api/v1/workspaces/wsp_1/directories/dir_1",
		"/api/v1/workspaces/wsp_1/directories/dir_1/files",
		"/api/v1/workspaces/wsp_1/directories/dir_1/files/content",
	}
	for _, path := range deletedPaths {
		path := path
		t.Run(path, func(t *testing.T) {
			t.Parallel()
			_, ok := workspaceV1IMRoute(path)
			require.False(t, ok,
				"gateway allowlist must not recognize deleted Directory surface %q", path)
		})
	}
}
