package agent

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/workflow/planmanage"
)

func TestAgentWorkflowPlanUpdateLayoutOmissionAndNoChangeContract(t *testing.T) {
	omitted, err := decodeAgentWorkflowPlanJSONBytes[dto.AgentWorkflowPlanReviseInput]([]byte(
		`{"action":"update","planId":"pln_1","expectedRevision":4,"source":"source"}`,
	))
	require.NoError(t, err)
	require.Empty(t, omitted.Layout)

	provided, err := decodeAgentWorkflowPlanJSONBytes[dto.AgentWorkflowPlanReviseInput]([]byte(
		`{"action":"update","planId":"pln_1","expectedRevision":4,"source":"source","layout":{"nodes":{"a":{"x":1}}}}`,
	))
	require.NoError(t, err)
	require.JSONEq(t, `{"nodes":{"a":{"x":1}}}`, string(provided.Layout))

	require.NoError(t, requireAgentWorkflowPlanDraftChanged(4, 5))
	err = requireAgentWorkflowPlanDraftChanged(4, 4)
	response, ok := classifyAgentWorkflowPlanError(err)
	require.True(t, ok)
	require.Equal(t, http.StatusConflict, response.Status)
	require.Equal(t, "plan_no_changes", response.Code)
	require.Equal(t, "plan", response.Stage)
}

// TestClassifyPlanWakeEditErrorsCarryContract verifies the Plan Agent
// wake/edit lifecycle errors survive the classifier→ErrorResponse path with the
// resolved owning stage and stable code, instead of an ad-hoc envelope that
// drops the resolved fields.
func TestClassifyPlanWakeEditErrorsCarryContract(t *testing.T) {
	tests := []struct {
		name     string
		err      error
		wantCode string
	}{
		{name: "edit revision mismatch", err: planmanage.ErrAgentEditRevisionMismatch, wantCode: "workflow_agent_edit_revision_mismatch"},
		{name: "wake active", err: planmanage.ErrAgentWakeActive, wantCode: "workflow_agent_wake_active"},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			response, ok := classifyAgentWorkflowPlanError(test.err)
			require.True(t, ok)
			require.Equal(t, http.StatusConflict, response.Status)
			require.Equal(t, test.wantCode, response.Code)
			require.Equal(t, "plan", response.Stage, "wake/edit errors must carry the resolved plan stage")
			require.False(t, response.Retryable, "a plain wake/edit conflict is not retryable")
		})
	}
}
