package agent

import (
	"encoding/json"
	"strings"
)

func claudeResultErrorTexts(errors []string, result json.RawMessage, abnormal bool) []string {
	texts := append([]string(nil), errors...)
	if !abnormal {
		return texts
	}
	var resultText string
	if err := json.Unmarshal(result, &resultText); err == nil && strings.TrimSpace(resultText) != "" {
		texts = append(texts, resultText)
	}
	return texts
}

func claudeResultErrorMessage(subtype, stopReason string, errors []string) string {
	parts := make([]string, 0, 2)
	if subtypeDetail := claudeResultSubtypeDetail(subtype); subtypeDetail != "" {
		parts = append(parts, subtypeDetail)
	}
	if len(errors) > 0 {
		errorParts := make([]string, 0, len(errors))
		for _, errText := range errors {
			detail := claudeResultErrorDetail(errText)
			if detail == "" || claudeResultErrorDetailAlreadyIncluded(errorParts, detail) {
				continue
			}
			errorParts = append(errorParts, detail)
		}
		if len(errorParts) > 0 {
			parts = append(parts, strings.Join(errorParts, "; "))
		}
	}
	if len(parts) == 0 {
		if stopReason = strings.TrimSpace(stopReason); stopReason != "" {
			parts = append(parts, "stop reason: "+stopReason)
		}
	}
	if len(parts) == 0 {
		return "Claude could not complete the request"
	}
	detail := strings.Join(parts, "; ")
	if strings.HasPrefix(detail, "Claude ") {
		return detail
	}
	return "Claude could not complete the request: " + detail
}

func claudeResultErrorDetailAlreadyIncluded(parts []string, detail string) bool {
	if runtimeErrorDetailAlreadyIncluded(parts, detail) {
		return true
	}
	const friendlyPrefix = "Claude API request failed:"
	semanticKey := func(text string) string {
		text = strings.TrimSpace(text)
		if len(text) >= len(friendlyPrefix) && strings.EqualFold(text[:len(friendlyPrefix)], friendlyPrefix) {
			text = strings.TrimSpace(text[len(friendlyPrefix):])
		}
		return normalizeClaudeErrorText(text)
	}
	want := semanticKey(detail)
	for _, part := range parts {
		if want != "" && semanticKey(part) == want {
			return true
		}
	}
	return false
}

func claudeResultTransientRuntimeError(errors []string) transientRuntimeErrorClassification {
	for _, errText := range errors {
		if classification := classifyTransientRuntimeErrorText(errText); classification.Retryable {
			return classification
		}
		detail := claudeResultErrorDetail(errText)
		if classification := classifyTransientRuntimeErrorText(detail); classification.Retryable {
			return classification
		}
	}
	return transientRuntimeErrorClassification{}
}

func claudeResultSubtypeDetail(subtype string) string {
	subtype = strings.TrimSpace(subtype)
	if subtype == "" || strings.EqualFold(subtype, "success") {
		return ""
	}
	if subtype == "error_max_turns" {
		return "maximum turn limit reached"
	}
	return "result: " + subtype
}

func claudeResultErrorDetail(errText string) string {
	errText = strings.TrimSpace(errText)
	if errText == "" {
		return ""
	}
	const apiErrorPrefix = "API Error:"
	if len(errText) < len(apiErrorPrefix) || !strings.EqualFold(errText[:len(apiErrorPrefix)], apiErrorPrefix) {
		return errText
	}

	message := "Claude API request failed"
	body := strings.TrimSpace(errText[len(apiErrorPrefix):])
	status, rest, hasRest := strings.Cut(body, " ")
	validStatus := len(status) == 3
	for _, ch := range status {
		validStatus = validStatus && ch >= '0' && ch <= '9'
	}
	if validStatus {
		message += " (HTTP " + status + ")"
		body = ""
		if hasRest {
			body = strings.TrimSpace(rest)
		}
	}
	if body == "" {
		return message
	}
	if strings.HasPrefix(body, "{") || strings.HasPrefix(body, "[") {
		if detail := runtimeErrorDetailFromRaw(json.RawMessage(body), nil, 0); detail != "" {
			body = detail
		}
	}
	return message + ": " + body
}
