package agent

import (
	"context"
	"net/http"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/workflow/publicerr"
)

// WorkflowRecoveryResetter is the narrow persistence boundary used by the
// shared Agent Workflow success exit. Implementations own the durable
// (workspace, agent) recovery epoch and reset it atomically.
type WorkflowRecoveryResetter interface {
	ResetAgentRecovery(context.Context, string, string) error
}

const workflowRecoveryResetFailedCode = "workflow_recovery_reset_failed"

// workflowRecoveryResetError keeps the public failure bounded while preserving
// the repository cause for server-side observation. It intentionally does not
// unwrap that repository cause: a persistence failure must always classify as a
// retryable 5xx rather than inheriting an incidental store sentinel from the
// driver.
type workflowRecoveryResetError struct {
	publicerr.WorkflowError
	cause error
}

func (err workflowRecoveryResetError) Error() string {
	return err.WorkflowError.Problem
}

// Unwrap exposes only the safe canonical WorkflowError to the classifier. The
// repository cause remains available through InternalCause and never enters
// errors.Is/As classification.
func (err workflowRecoveryResetError) Unwrap() error { return err.WorkflowError }

func (err workflowRecoveryResetError) InternalCause() error { return err.cause }

// workflowRecoverySuccessOption installs the one success hook shared by the
// Plan, Trigger, Run, and Step CLI routes. It deliberately runs after the
// route handler has returned a successful response and never runs for
// authentication, decoding, validation, authorization, or business errors.
func workflowRecoverySuccessOption(resetters ...WorkflowRecoveryResetter) api.HandlerOption {
	if len(resetters) == 0 || resetters[0] == nil {
		return nil
	}
	resetter := resetters[0]
	return api.WithAgentSuccess(func(request api.AgentScopedRequest, response api.Response) error {
		status := response.Status
		if status == 0 {
			status = http.StatusOK
		}
		if status < http.StatusOK || status >= http.StatusMultipleChoices {
			return nil
		}
		if err := resetter.ResetAgentRecovery(
			request.Context(),
			strings.TrimSpace(request.Principal.WorkspaceID),
			strings.TrimSpace(request.Principal.AgentID),
		); err != nil {
			return workflowRecoveryResetError{
				WorkflowError: publicerr.WorkflowError{
					Status:    http.StatusInternalServerError,
					Code:      workflowRecoveryResetFailedCode,
					Problem:   "Workflow recovery state could not be persisted; retry the request",
					Hint:      "Retry the same command",
					Retryable: true,
				},
				cause: err,
			}
		}
		return nil
	})
}
