package plan

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

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

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/store/identity"
	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
	"github.com/tidbcloud/AgentTeam/internal/store/workspace"
)

type rejectingDirectPublishGuard struct {
	calls [][2]string
}

func (guard *rejectingDirectPublishGuard) RequireUnlinkedPlan(_ context.Context, workspaceID, planID string) error {
	guard.calls = append(guard.calls, [2]string{workspaceID, planID})
	return storeerr.Conflict("Team Workflow approval is required")
}

func TestPlanLifecycleMutationsCannotBypassTeamWorkflowApproval(t *testing.T) {
	guard := &rejectingDirectPublishGuard{}
	handlers := newRouteHandlers(nil, guard)
	handler := handlers.versions

	request := guardedPlanRequest(t, "pln_team", "3")
	_, err := handler.Publish(api.WorkspaceScopedJSON[dto.WorkflowPlanPublishRequest]{
		WorkspaceScopedRequest: request,
		Body:                   dto.WorkflowPlanPublishRequest{DraftRevision: 2},
	})
	require.ErrorIs(t, err, storeerr.ErrConflict)

	request = guardedPlanRequest(t, "pln_team", "3")
	_, err = handler.Republish(api.WorkspaceScopedJSON[dto.WorkflowPlanRepublishRequest]{
		WorkspaceScopedRequest: request,
	})
	require.ErrorIs(t, err, storeerr.ErrConflict)

	request = guardedPlanRequest(t, "pln_team", "3")
	_, err = handler.MakeDefault(request)
	require.ErrorIs(t, err, storeerr.ErrConflict)

	request = guardedPlanRequest(t, "pln_team", "3")
	_, err = handlers.detail.Archive(request)
	require.ErrorIs(t, err, storeerr.ErrConflict)

	request = guardedPlanRequest(t, "pln_team", "3")
	_, err = handlers.detail.Restore(request)
	require.ErrorIs(t, err, storeerr.ErrConflict)
	require.Equal(t, [][2]string{
		{"wsp_1", "pln_team"}, {"wsp_1", "pln_team"}, {"wsp_1", "pln_team"},
		{"wsp_1", "pln_team"}, {"wsp_1", "pln_team"},
	}, guard.calls)
}

func guardedPlanRequest(t *testing.T, planID, version string) api.WorkspaceScopedRequest {
	t.Helper()
	gin.SetMode(gin.TestMode)
	ctx, _ := gin.CreateTestContext(httptest.NewRecorder())
	ctx.Request = httptest.NewRequest(http.MethodPost, "/", nil)
	ctx.Request.Header.Set("If-Match", planETag(planID, 4))
	ctx.Params = []gin.Param{{Key: "planId", Value: planID}, {Key: "versionId", Value: version}}
	return api.WorkspaceScopedRequest{
		AuthenticatedRequest: api.AuthenticatedRequest{Gin: ctx, User: identity.AuthenticatedUser{User: identity.User{ID: "usr_1"}}},
		Workspace:            workspace.Summary{WorkspaceID: "wsp_1", MemberID: "mem_1"},
	}
}
