package runtime

import (
	"encoding/json"
	"strings"
)

func validateAnswerArguments(fields map[string]json.RawMessage, arguments *knowledgeAnswerArguments) error {
	if fieldMissingOrNull(fields, "claims") || len(arguments.Claims) == 0 {
		return explorationToolValidationError(knowledgeAnswerFunction, repairIssueAnswerClaimsRequired)
	}
	for index, claim := range arguments.Claims {
		claim = strings.TrimSpace(claim)
		if claim == "" {
			return explorationToolValidationError(knowledgeAnswerFunction, repairIssueAnswerClaimEmpty)
		}
		if strings.TrimSpace(evidenceMarkerPattern.ReplaceAllString(claim, "")) == "" {
			return explorationToolValidationError(knowledgeAnswerFunction, repairIssueAnswerClaimCitationOnly)
		}
		arguments.Claims[index] = claim
	}
	if raw, present := fields["sourceBranchChange"]; present {
		if rawJSONNull(raw) || arguments.SourceBranchChange == nil {
			return explorationToolValidationError(knowledgeAnswerFunction, repairIssueAnswerBranchChangeInvalid)
		}
		arguments.SourceBranchChange.BranchRootAlias = strings.TrimSpace(arguments.SourceBranchChange.BranchRootAlias)
		if len(arguments.SourceBranchChange.BranchRootAlias) > maxReferenceBytes ||
			!rootReferencePattern.MatchString(arguments.SourceBranchChange.BranchRootAlias) {
			return explorationToolValidationError(knowledgeAnswerFunction, repairIssueAnswerBranchChangeInvalid)
		}
	}
	return nil
}

func groundedAnswerFromClaims(answerClaims []string) GroundedAnswer {
	claims := make([]GroundedClaim, 0, len(answerClaims))
	for _, text := range answerClaims {
		claims = append(claims, GroundedClaim{Text: text, EvidenceIDs: evidenceIDsFromMarkers(text)})
	}
	return GroundedAnswer{Claims: claims}
}

func evidenceIDsFromMarkers(text string) []string {
	matches := evidenceMarkerPattern.FindAllStringSubmatch(text, -1)
	result := make([]string, 0, len(matches))
	seen := make(map[string]struct{}, len(matches))
	for _, match := range matches {
		if len(match) != 2 {
			continue
		}
		if _, duplicate := seen[match[1]]; duplicate {
			continue
		}
		seen[match[1]] = struct{}{}
		result = append(result, match[1])
	}
	return result
}
