package exec

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/require"

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

// TestClassifyAPIErrorDiagnosticIdentityFailClosesOnWhitespace proves the
// structured diagnostic code/path/field projection is byte-for-byte: a server
// diagnostic whose code has surrounding whitespace is never trimmed into an
// accepted identity that unlocks public diagnostics.
func TestClassifyAPIErrorDiagnosticIdentityFailClosesOnWhitespace(t *testing.T) {
	index := 1
	apiErr := &apiclient.APIError{
		StatusCode: http.StatusBadRequest,
		Method:     "POST",
		Path:       "/workflow/step",
		Message:    "node entry is unreachable",
		Code:       "plan_compile_failed",
		StageName:  "run",
		Diagnostics: []apiclient.Diagnostic{{
			Severity: "error",
			Code:     " plan.node_unreachable ",
			Path:     "$.nodes.entry",
			Field:    "entry",
			Index:    &index,
			Line:     12,
			Column:   3,
			Message:  "节点不可达",
		}},
	}
	classified := classifyAPIError(apiErr, "workflow step complete failed")
	// The whole diagnostic element is dropped (fail closed); the spaced code is
	// never trimmed into `plan.node_unreachable`.
	require.Empty(t, classified.Diagnostics, "a diagnostic with a spaced code must fail closed")
}

// TestClassifyAPIErrorAllowlistFailClosesOnWhitespace proves an untrusted server
// code with surrounding whitespace does not unlock public problem/hint/
// diagnostics/ServerCode.
func TestClassifyAPIErrorAllowlistFailClosesOnWhitespace(t *testing.T) {
	apiErr := &apiclient.APIError{
		StatusCode: http.StatusBadRequest,
		Method:     "POST",
		Path:       "/workflow/step",
		Message:    "server bounded public message",
		Code:       " plan_compile_failed ",
		StageName:  "run",
		ErrorPath:  "$.nodes.entry",
		Hint:       "hint",
		Diagnostics: []apiclient.Diagnostic{{
			Severity: "error", Code: "plan.node_unreachable", Path: "$.nodes.entry", Message: "node unreachable",
		}},
	}
	classified := classifyAPIError(apiErr, "workflow step complete failed")
	require.Equal(t, "workflow step complete failed", classified.Problem,
		"a spaced server code must not unlock the server public message")
	require.Empty(t, classified.Stage, "a spaced server code must not unlock Stage")
	require.Empty(t, classified.Path, "a spaced server code must not unlock Path")
	require.Empty(t, classified.ServerCode, "a spaced server code must not unlock ServerCode")
	require.Empty(t, classified.Diagnostics, "a spaced server code must not unlock diagnostics")
}

// TestWorkflowInvocationInputDiagnosticFailClosesOnSpacedCode proves the
// invocation input diagnostic recognition matches the apiErr code byte-for-byte:
// a spaced server code is never trimmed into the invocation_input_invalid
// identity that unlocks the structured diagnostic.
func TestWorkflowInvocationInputDiagnosticFailClosesOnSpacedCode(t *testing.T) {
	apiErr := &apiclient.APIError{
		StatusCode: http.StatusBadRequest,
		Method:     "POST",
		Path:       "/workflow/step",
		Message:    "invalid input",
		Code:       " invocation_input_invalid ",
		Diagnostics: []apiclient.Diagnostic{{
			Severity: "error",
			Code:     "invocation.input_invalid",
			Path:     "$.input.reviewers[0]",
			Message:  "reviewers must be a list",
		}},
	}
	_, ok := workflowInvocationInputDiagnostic(apiErr)
	require.False(t, ok, "a spaced apiErr code must not unlock the invocation input diagnostic")
}

// TestApplyErrorBudgetFailsClosedOnMalformedDiagnosticIdentity proves the
// Exec error-budget boundary drops a diagnostic whose code/path/field identity
// is malformed instead of trimming it into an accepted identity.
func TestApplyErrorBudgetFailsClosedOnMalformedDiagnosticIdentity(t *testing.T) {
	classified := &Error{
		Code: CodeValidation, Problem: "invalid input",
		Diagnostics: []Diagnostic{
			{Severity: "error", Code: " plan.node_unreachable ", Path: "$.nodes.entry", Field: "entry", Message: "unreachable"},
			{Severity: "error", Code: "plan.node_unreachable", Path: "$.nodes.entry", Field: "entry", Message: "unreachable"},
		},
	}
	envelope := ApplyErrorBudget(classified)
	require.Len(t, envelope.Diagnostics, 1, "the malformed-code diagnostic must fail closed")
	require.Equal(t, "plan.node_unreachable", envelope.Diagnostics[0].Code)
}
