package sfcrmappservice

import (
	"context"
	"errors"

	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/relatedcountsv1"
)

type RuntimeRelatedCountFunc func(context.Context, string, semantic.Request) (semantic.Response, error)

type relatedListCountRequest struct {
	ObjectAPIName    string `json:"objectApiName"`
	LookupField      string `json:"lookupField"`
	ParentRecordID   string `json:"parentRecordId"`
	ParentFieldValue string `json:"parentFieldValue"`
}

type relatedListCountResponse struct {
	ObjectAPIName string `json:"objectApiName"`
	LookupField   string `json:"lookupField"`
	Count         uint64 `json:"count"`
	Error         string `json:"error,omitempty"`
}

func countRelatedRecords(ctx context.Context, runtime RuntimeRelatedCountFunc, bearer string, requests []relatedListCountRequest) ([]relatedListCountResponse, error) {
	if runtime == nil {
		return nil, &semantic.Failure{Category: semantic.FailureUnavailable}
	}
	semanticRequest := semantic.Request{Counts: make([]semantic.CountSpec, len(requests))}
	for index, request := range requests {
		matchValue := request.ParentFieldValue
		if matchValue == "" {
			matchValue = request.ParentRecordID
		}
		semanticRequest.Counts[index] = semantic.CountSpec{
			ParentRecordID: request.ParentRecordID, ChildObjectID: request.ObjectAPIName,
			RelationshipField: request.LookupField, MatchValue: matchValue,
		}
	}
	if err := semantic.ValidateRequest(ctx, semanticRequest); err != nil {
		return nil, err
	}
	response, err := runtime(ctx, bearer, semanticRequest)
	if err != nil {
		return nil, err
	}
	if err := semantic.ValidateResponse(semanticRequest, response); err != nil {
		return nil, err
	}
	results := make([]relatedListCountResponse, len(requests))
	for index, request := range requests {
		results[index] = relatedListCountResponse{ObjectAPIName: request.ObjectAPIName, LookupField: request.LookupField}
		result := response.Results[index]
		switch result.Outcome {
		case semantic.CountOutcomeCounted:
			results[index].Count = result.Count
		case semantic.CountOutcomeNotAvailable:
			results[index].Error = "related list count unavailable"
		default:
			return nil, errors.New("sfcrm AppService: invalid Runtime related-count outcome")
		}
	}
	return results, nil
}
