package exec

import (
	"context"
	"encoding/json"
	"errors"
	"net/http"
	"net/http/httptest"
	"sync/atomic"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

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

// TestWorkflowRemoteStepRetryExhaustionPreservesDeliveryRace proves that when
// the outer transport deadline interrupts the bounded step_not_ready retry, the
// canonical delivery-race APIError survives instead of failing closed to an
// opaque internal error. The retry wait is injected to return a deadline-style
// error immediately, so the loop returns the last step_not_ready APIError.
func TestWorkflowRemoteStepRetryExhaustionPreservesDeliveryRace(t *testing.T) {
	var calls atomic.Int32
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		calls.Add(1)
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusConflict)
		_ = json.NewEncoder(w).Encode(map[string]any{
			"error":     "Workflow Step delivery is not ready",
			"code":      "step_not_ready",
			"stage":     "run",
			"retryable": true,
		})
	}))
	defer server.Close()

	client := &apiclient.Client{
		ServerURL: server.URL, AgentID: "agt_test", LocalAgentID: "agt_test",
		AuthToken: "test-token", RouteWorkspaceID: "wsp_test", HTTPClient: server.Client(),
	}
	remote := workflowRemote{
		client: client,
		callbackRetryWait: func(context.Context, int, time.Time) error {
			return errors.New("workflow run callback retry window elapsed")
		},
	}
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	_, _, err := remote.step(ctx, workflowStepInput{
		Action: "complete", RunID: "wri_1", StepID: "wfx_1", IdempotencyKey: "k-1",
	}, workflowRunContext{WorkspaceID: "wsp_test", AgentID: "agt_test", RunID: "wri_1", EffectID: "wfx_1"})
	require.Error(t, err)
	var apiErr *apiclient.APIError
	require.ErrorAs(t, err, &apiErr, "retry exhaustion must preserve the underlying APIError")
	require.Equal(t, "step_not_ready", apiErr.Code)
	require.Equal(t, http.StatusConflict, apiErr.StatusCode)
	require.True(t, apiErr.Retryable, "retry exhaustion must preserve top-level retryable")
	require.Equal(t, "run", apiErr.Stage())
	require.GreaterOrEqual(t, calls.Load(), int32(1), "the server must have been reached")
}
