package run

import (
	"errors"

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

// publicError constructs an API-layer domain error that the shared classifier
// projects into the public Workflow error contract.
func publicError(status int, code string, problem string) error {
	return publicerr.WorkflowError{
		Kind: storeerr.ErrBadRequest, Status: status, Code: code, Problem: problem,
	}
}

func classifyError(err error) (api.ErrorResponse, bool) {
	// API-layer HTTP errors carry an explicit status and stable code that must
	// pass through verbatim (for example malformed calendar query parameters).
	// They are not store/domain failures, so the public Workflow classifier
	// must not re-map or collapse them.
	var httpError api.HTTPError
	if errors.As(err, &httpError) {
		code := httpError.Code
		if code == "" {
			code = "run_request_failed"
		}
		return api.ErrorResponse{
			Status:  httpError.Status,
			Message: httpError.Error(),
			Code:    code,
			Stage:   string(publicerr.StageRun),
		}, true
	}

	classified, ok := publicerr.Classify(err, publicerr.Options{
		Stage:       publicerr.StageRun,
		DefaultCode: "run_request_failed",
		ProtectedSelectors: map[string]string{
			string(runmanage.ErrorCodeNotFound):  string(runmanage.ErrorCodeNotFound),
			string(runmanage.ErrorCodeForbidden): string(runmanage.ErrorCodeNotFound),
		},
		ProtectedNotFoundCode: string(runmanage.ErrorCodeNotFound),
	})
	if !ok {
		return api.ErrorResponse{}, false
	}
	return workflowErrorResponse(classified), true
}

// workflowErrorResponse maps a public Workflow classification into the shared
// API error envelope, carrying every public contract field.
func workflowErrorResponse(classified publicerr.Classified) api.ErrorResponse {
	response := api.ErrorResponse{
		Status: classified.Status, Message: classified.Error.Problem,
		Code: classified.Error.Code, Details: classified.Details,
		Stage: string(classified.Error.Stage), Path: classified.Error.Path,
		Hint: classified.Error.Hint, Retryable: classified.Error.Retryable,
		Diagnostics: classified.Error.Diagnostics,
	}
	if classified.Error.Truncation != nil {
		response.Truncation = classified.Error.Truncation
	}
	return response
}

// ClassifyError shares the first-class Run error contract with trusted Agent
// transports without duplicating status/code mapping.
func ClassifyError(err error) (api.ErrorResponse, bool) {
	return classifyError(err)
}
