package tokenanalysis

import (
	"errors"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

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

	analysis "github.com/tidbcloud/AgentTeam/desktop/internal/tokenanalysis"
)

func TestHumanRoutesAutoEnableAndToggleCollection(t *testing.T) {
	gin.SetMode(gin.TestMode)
	service := analysis.New(analysis.Dependencies{
		Agents: func() []analysis.Agent { return []analysis.Agent{{ID: "agent-a"}} },
	})
	t.Cleanup(func() { service.SetCollectionEnabled(false) })
	router := gin.New()
	RegisterHumanRoutes(router.Group(RootPath), Dependencies{Service: service})

	response := performRequest(router, http.MethodGet, RootPath+"/analysis?window=1d", "")
	require.Equal(t, http.StatusOK, response.Code)
	require.Contains(t, response.Body.String(), `"autoEnabled":true`)
	require.True(t, service.CollectionEnabled())

	response = performRequest(router, http.MethodPut, RootPath+"/collection", `{"enabled":false}`)
	require.Equal(t, http.StatusOK, response.Code)
	require.False(t, service.CollectionEnabled())

	response = performRequest(router, http.MethodPut, RootPath+"/collection", `{"enabled":true}{"enabled":false}`)
	require.Equal(t, http.StatusBadRequest, response.Code)
	require.False(t, service.CollectionEnabled())

	response = performRequest(router, http.MethodGet, RootPath+"/analysis?stop=true", "")
	require.Equal(t, http.StatusOK, response.Code)
	require.Contains(t, response.Body.String(), `"stopped":true`)
	require.NotContains(t, response.Body.String(), `"autoEnabled":true`)
	require.False(t, service.CollectionEnabled())
}

func TestAgentRouteUsesTokenBoundSelfScopeAndCannotToggle(t *testing.T) {
	gin.SetMode(gin.TestMode)
	service := analysis.New(analysis.Dependencies{
		Agents: func() []analysis.Agent {
			return []analysis.Agent{{ID: "agent-a"}, {ID: "agent-b"}}
		},
	})
	t.Cleanup(func() { service.SetCollectionEnabled(false) })
	router := gin.New()
	RegisterAgentRoutes(router.Group(RootPath+"/agents/:agentId"), Dependencies{
		Service: service,
		ValidateAgentToken: func(agentID, value string) error {
			if agentID != "agent-a" || value != "self-token" {
				return errors.New("unauthorized")
			}
			return nil
		},
	})

	response := performAgentRequest(router, http.MethodGet, RootPath+"/agents/agent-a/analysis", "self-token")
	require.Equal(t, http.StatusOK, response.Code)
	require.False(t, service.CollectionEnabled())

	response = performAgentRequest(router, http.MethodGet, RootPath+"/agents/agent-a/analysis?agentRef=agent-b", "self-token")
	require.Equal(t, http.StatusBadRequest, response.Code)
	require.Contains(t, response.Body.String(), "agent_ref_not_found")

	response = performAgentRequest(router, http.MethodGet, RootPath+"/agents/agent-b/analysis", "self-token")
	require.Equal(t, http.StatusUnauthorized, response.Code)
	response = performAgentRequest(router, http.MethodGet, RootPath+"/agents/agent-a/analysis", "generic-token")
	require.Equal(t, http.StatusUnauthorized, response.Code)
	response = performAgentRequest(router, http.MethodPut, RootPath+"/agents/agent-a/collection", "self-token")
	require.Equal(t, http.StatusNotFound, response.Code)
}

func performRequest(handler http.Handler, method, target, body string) *httptest.ResponseRecorder {
	request := httptest.NewRequest(method, target, strings.NewReader(body))
	if body != "" {
		request.Header.Set("Content-Type", "application/json")
	}
	response := httptest.NewRecorder()
	handler.ServeHTTP(response, request)
	return response
}

func performAgentRequest(handler http.Handler, method, target, bearer string) *httptest.ResponseRecorder {
	request := httptest.NewRequest(method, target, nil)
	if bearer != "" {
		request.Header.Set("Authorization", "Bearer "+bearer)
	}
	response := httptest.NewRecorder()
	handler.ServeHTTP(response, request)
	return response
}
