package agent

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"

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

func requiredAgentInvocationID(name string, raw string) (string, error) {
	value := strings.TrimSpace(raw)
	if value == "" {
		return "", publicError(http.StatusBadRequest, "run_invalid_request", name+" is required")
	}
	return value, nil
}

func optionalAgentInvocationID(name string, raw json.RawMessage) (string, error) {
	if len(bytes.TrimSpace(raw)) == 0 {
		return "", nil
	}
	var decoded string
	if err := json.Unmarshal(raw, &decoded); err != nil || strings.TrimSpace(decoded) == "" {
		return "", publicError(http.StatusBadRequest, "run_invalid_request", name+" must be non-empty when provided")
	}
	return strings.TrimSpace(decoded), nil
}

func requiredAgentInvocationInput(raw json.RawMessage) (json.RawMessage, error) {
	trimmed := bytes.TrimSpace(raw)
	if len(trimmed) == 0 || bytes.Equal(trimmed, []byte("null")) || trimmed[0] != '{' {
		return nil, publicError(http.StatusBadRequest, "run_invalid_request", "input must be a JSON object")
	}
	if len(raw) > invocation.MaxInputBytes {
		return nil, publicError(
			http.StatusRequestEntityTooLarge,
			"run_request_too_large",
			fmt.Sprintf("input must not exceed %d bytes", invocation.MaxInputBytes),
		)
	}
	return raw, nil
}

func agentWorkflowInvocationPrincipalUnavailableError() error {
	return invocationmanage.RequestError{
		Kind: storeerr.ErrForbidden, Code: invocationmanage.ErrorCodePrincipalUnavailable,
		Message: "Run start principal is unavailable",
	}
}

func classifyWorkflowInvocationError(err error) (api.ErrorResponse, bool) {
	classified, ok := publicerr.Classify(err, publicerr.Options{
		Stage:       publicerr.StageInvocation,
		DefaultCode: "run_start_failed",
		Unredacted:  true,
	})
	if !ok {
		return api.ErrorResponse{}, false
	}
	return workflowErrorResponse(classified, nil), true
}
