package exec

import (
	"encoding/json"
	"fmt"
	"strconv"
)

// mutationRetrievalPath only emits a follow-up to a read-only catalog action
// after constructing and validating the complete typed input. Wire-provided
// paths are never used; this canonical builder is also used by the strict
// LocalClient decoder when it re-projects an applied receipt.
func mutationRetrievalPath(domain, action string, identifiers map[string]string) string {
	targetDomain, targetAction := domain, action
	args := make(map[string]any)
	complete := false
	switch domain {
	case "agent":
		targetAction, complete = "get", identifiers["agentId"] != ""
		args["agentId"] = identifiers["agentId"]
	case "team":
		targetAction, complete = "get", identifiers["teamId"] != ""
		args["teamId"] = identifiers["teamId"]
	case "channel":
		targetAction, complete = "get", identifiers["channelId"] != ""
		args["channelId"] = identifiers["channelId"]
	case "skill":
		targetAction, complete = "get", identifiers["skillId"] != ""
		args["skillId"] = identifiers["skillId"]
	case "scheduled-message":
		targetAction, complete = "get", identifiers["id"] != ""
		args["id"] = identifiers["id"]
	case "role":
		targetAction, complete = "request-get", identifiers["requestId"] != ""
		args["requestId"] = identifiers["requestId"]
	case "review":
		targetAction, complete = "list", identifiers["thread"] != ""
		args["thread"] = identifiers["thread"]
	case "task":
		numberText := identifiers["number"]
		if numberText == "" {
			numberText = identifiers["taskNumber"]
		}
		number, err := strconv.Atoi(numberText)
		targetAction, complete = "get", identifiers["channel"] != "" && err == nil && number > 0
		args["channel"], args["number"] = identifiers["channel"], number
	case "workflow":
		args["action"] = "show"
		switch action {
		case "plan":
			targetAction, complete = "plan", identifiers["planId"] != ""
			args["planId"] = identifiers["planId"]
		case "trigger":
			targetAction, complete = "trigger", identifiers["triggerId"] != ""
			args["triggerId"] = identifiers["triggerId"]
		case "run":
			targetAction, complete = "run", identifiers["runId"] != ""
			args["runId"] = identifiers["runId"]
		case "step":
			targetAction, complete = "step", identifiers["runId"] != "" && identifiers["stepId"] != ""
			args["runId"], args["stepId"] = identifiers["runId"], identifiers["stepId"]
		}
	}
	if !complete {
		return ""
	}
	encoded, err := json.Marshal(args)
	if err != nil || !mutationReceiptFollowUpInputValid(targetDomain, targetAction, encoded) {
		return ""
	}
	return fmt.Sprintf("agentteam exec %s %s %s", targetDomain, targetAction, encoded)
}

func mutationReceiptFollowUpInputValid(domain, action string, input json.RawMessage) bool {
	if domain == "workflow" {
		if classifyWorkflowOperation(action, workflowOperationFromRaw(input)) != workflowOperationRead {
			return false
		}
	} else {
		policy, ok := builtinActionPolicyFor(domain, action)
		if !ok || policy.Risk != builtinRiskReadOnly {
			return false
		}
	}
	catalog, err := DefaultCatalog()
	if err != nil || catalog == nil {
		return false
	}
	return catalog.ValidateInput(domain, action, input) == nil
}
