package searchv1

import (
	"context"
	"strings"

	common "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
)

func ValidateScopeOrderRequest(ctx context.Context, request ScopeOrderRequest) error {
	if err := validateContext(ctx); err != nil {
		return err
	}
	return validateScopeOrderRequestShape(request)
}

func validateScopeOrderRequestShape(request ScopeOrderRequest) error {
	if len(request.ObjectIDs) == 0 || len(request.ObjectIDs) > MaxObjects {
		return invalid(common.InvalidComponentQueryPlan)
	}
	for _, objectID := range request.ObjectIDs {
		if !common.ValidObjectIdentifier(objectID) {
			return invalid(common.InvalidComponentObjectID)
		}
	}
	if !uniqueFolded(request.ObjectIDs) {
		return invalid(common.InvalidComponentQuerySelection)
	}
	return validateSize(request, MaxSemanticRequestBytes, common.LimitSemanticRequest)
}

func ValidateScopeOrderResponse(request ScopeOrderRequest, response ScopeOrderResponse) error {
	if validateScopeOrderRequestShape(request) != nil ||
		!common.ValidReceipts(response.Receipts, CapabilityName) ||
		len(response.ObjectIDs) > len(request.ObjectIDs) ||
		len(response.ObjectIDs) > MaxObjects {
		return internal()
	}
	requestObjects := foldedSet(request.ObjectIDs)
	seen := make(map[string]struct{}, len(response.ObjectIDs))
	for _, objectID := range response.ObjectIDs {
		if !common.ValidObjectIdentifier(objectID) {
			return internal()
		}
		key := strings.ToLower(objectID)
		if _, ok := requestObjects[key]; !ok {
			return internal()
		}
		if _, duplicate := seen[key]; duplicate {
			return internal()
		}
		seen[key] = struct{}{}
	}
	return validateSize(response, MaxSemanticResponseBytes, common.LimitSemanticResponse)
}
