package sfcrmappservice

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"math/big"
	"net/http"
	"sort"
	"strconv"
	"strings"

	crmwire "github.com/pingcap-inc/nexuscrm-app-packs/sfcrm/wire"
	catalogsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/catalog/consumerv1"
	commonsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	permissionsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/effectivepermissionsv1"
	querysemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
	reportsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/reportv1"
)

const (
	analyticsPermissionRunReports = "RunReports"
	analyticsReportObject         = "Report"
	analyticsDashboardObject      = "Dashboard"
	analyticsComponentObject      = "DashboardComponent"
	analyticsDefaultListLimit     = uint32(200)
	analyticsMaxListLimit         = uint64(2000)
	analyticsDashboardMaxParts    = uint32(100)
)

type RuntimeReadReportFunc func(
	context.Context,
	string,
	reportsemantic.Request,
) (reportsemantic.Response, error)

// RuntimeAnalyticsClient is the L1 orchestration boundary for Salesforce
// analytics reads. Runtime owns authorization, record/history access and saved
// report execution. This client owns Salesforce routes, response semantics and
// CRM virtual-source assembly; it has no database, repository or legacy
// fallback.
type RuntimeAnalyticsClient struct {
	query                RuntimeQueryFunc
	history              RuntimeHistoryQueryFunc
	readReport           RuntimeReadReportFunc
	readPermissions      RuntimeReadEffectivePermissionsFunc
	appMetadata          RuntimeGetAppMetadataViewV3Func
	reconcileAppMetadata RuntimeReconcileAppMetadataV3ReceiptsFunc
}

func NewRuntimeAnalyticsClient(
	query RuntimeQueryFunc,
	history RuntimeHistoryQueryFunc,
	readReport RuntimeReadReportFunc,
	readPermissions RuntimeReadEffectivePermissionsFunc,
	appMetadata RuntimeGetAppMetadataViewV3Func,
) (*RuntimeAnalyticsClient, error) {
	if query == nil || history == nil || readReport == nil || readPermissions == nil || appMetadata == nil {
		return nil, errors.New("sfcrm AppService: Runtime Query, HistoryQuery, ReportRead, effective-permission and AppMetadataViewV3 clients are required for analytics reads")
	}
	return &RuntimeAnalyticsClient{query: query, history: history, readReport: readReport, readPermissions: readPermissions, appMetadata: appMetadata}, nil
}

type analyticsRouteKind uint8

const (
	analyticsRouteDashboards analyticsRouteKind = iota + 1
	analyticsRouteDashboard
	analyticsRouteDashboardRefresh
	analyticsRouteDashboardStatus
	analyticsRouteReports
	analyticsRouteReport
	analyticsRouteReportDescribe
	analyticsRouteReportExecution
	analyticsRouteReportDefinitionExecution
)

type analyticsRoute struct {
	kind    analyticsRouteKind
	version string
	id      string
}

func matchAnalyticsRoute(path string) analyticsRoute {
	parts := strings.Split(strings.Trim(path, "/"), "/")
	if len(parts) < 5 || parts[0] != "services" || parts[1] != "data" || parts[3] != "analytics" {
		return analyticsRoute{}
	}
	if _, ok := recordViewVersions[parts[2]]; !ok {
		return analyticsRoute{}
	}
	base := analyticsRoute{version: parts[2]}
	switch {
	case len(parts) == 5 && parts[4] == "dashboards":
		base.kind = analyticsRouteDashboards
	case len(parts) == 6 && parts[4] == "dashboards" && parts[5] != "":
		base.kind, base.id = analyticsRouteDashboard, parts[5]
	case len(parts) == 7 && parts[4] == "dashboards" && parts[5] != "" && parts[6] == "refresh":
		base.kind, base.id = analyticsRouteDashboardRefresh, parts[5]
	case len(parts) == 7 && parts[4] == "dashboards" && parts[5] != "" && parts[6] == "status":
		base.kind, base.id = analyticsRouteDashboardStatus, parts[5]
	case len(parts) == 5 && parts[4] == "reports":
		base.kind = analyticsRouteReports
	case len(parts) == 6 && parts[4] == "reports" && parts[5] != "" && parts[5] != "execute":
		base.kind, base.id = analyticsRouteReport, parts[5]
	case len(parts) == 7 && parts[4] == "reports" && parts[5] != "" && parts[6] == "describe":
		base.kind, base.id = analyticsRouteReportDescribe, parts[5]
	case len(parts) == 5 && parts[4] == "report-execution":
		base.kind = analyticsRouteReportExecution
	case len(parts) == 6 && parts[4] == "reports" && parts[5] == "execute":
		base.kind = analyticsRouteReportDefinitionExecution
	}
	return base
}

func (service *Service) serveAnalytics(writer http.ResponseWriter, request *http.Request) bool {
	route := matchAnalyticsRoute(request.URL.Path)
	if route.kind == 0 || service.analytics == nil {
		return false
	}
	if !analyticsMethodAllowed(route.kind, request.Method) {
		writer.Header().Set("Allow", analyticsAllowedMethods(route.kind))
		writeCRMError(writer, http.StatusMethodNotAllowed, crmwire.SFCodeInvalidRequest, "Method not allowed")
		return true
	}

	service.requests.Add(1)
	if service.draining.Load() {
		service.drainRejected.Add(1)
		service.failures.Add(1)
		writeCRMError(writer, http.StatusServiceUnavailable, crmwire.SFCodeUnknownException, "Service is draining")
		return true
	}
	bearer, ok := endUserBearer(request.Header.Values("Authorization"))
	if !ok {
		service.localRejected.Add(1)
		service.failures.Add(1)
		writeCRMError(writer, http.StatusUnauthorized, crmwire.SFCodeInvalidSessionID, "Session expired or invalid")
		return true
	}

	service.inFlight.Add(1)
	defer service.inFlight.Add(-1)
	ctx, cancel := context.WithTimeout(request.Context(), service.requestTimeout)
	defer cancel()

	authority, err := service.analytics.authorize(ctx, bearer)
	if err != nil {
		service.failures.Add(1)
		writeAnalyticsFailure(writer, err)
		return true
	}

	var response any
	dashboardQuery := func() (string, string, string, bool) {
		query := request.URL.Query()
		runningUser, runningUserOK := analyticsSingleQueryValue(query, "runningUser")
		startDate, startDateOK := analyticsSingleQueryValue(query, "startDate")
		endDate, endDateOK := analyticsSingleQueryValue(query, "endDate")
		return runningUser, startDate, endDate, runningUserOK && startDateOK && endDateOK
	}
	switch route.kind {
	case analyticsRouteDashboards:
		response, err = service.analytics.listDashboards(ctx, bearer, authority, analyticsListLimit(request.URL.Query().Get("limit")))
	case analyticsRouteDashboard:
		if request.Method == http.MethodPut {
			if !analyticsRequestBodyEmpty(writer, request, service.maxRequestBytes) {
				err = errAnalyticsInvalid
				break
			}
			runningUser, startDate, endDate, queryOK := dashboardQuery()
			if _, runningUserOK := analyticsRunningUser(runningUser); !queryOK || !runningUserOK || startDate != "" || endDate != "" {
				err = errAnalyticsInvalid
				break
			}
			_, err = service.analytics.dashboard(ctx, bearer, route.id, authority)
			if err == nil {
				response = map[string]any{"statusUrl": fmt.Sprintf("/services/data/%s/analytics/dashboards/%s/status?runningUser=viewer", route.version, route.id)}
			}
		} else {
			query := request.URL.Query()
			if _, hasStartDate := query["startDate"]; hasStartDate {
				err = errAnalyticsInvalid
				break
			}
			if _, hasEndDate := query["endDate"]; hasEndDate {
				err = errAnalyticsInvalid
				break
			}
			var dashboard analyticsDashboard
			dashboard, err = service.analytics.dashboard(ctx, bearer, route.id, authority)
			response = map[string]any{"dashboardMetadata": dashboard, "componentData": map[string]any{}}
		}
	case analyticsRouteDashboardRefresh:
		if !analyticsRequestBodyEmpty(writer, request, service.maxRequestBytes) {
			err = errAnalyticsInvalid
			break
		}
		runningUser, startDate, endDate, queryOK := dashboardQuery()
		if !queryOK {
			err = errAnalyticsInvalid
			break
		}
		response, err = service.analytics.runDashboard(ctx, bearer, route.id, authority, runningUser, startDate, endDate)
	case analyticsRouteDashboardStatus:
		runningUser, startDate, endDate, queryOK := dashboardQuery()
		if !queryOK {
			err = errAnalyticsInvalid
			break
		}
		var result analyticsDashboardRun
		result, err = service.analytics.runDashboard(ctx, bearer, route.id, authority, runningUser, startDate, endDate)
		if err == nil {
			response = map[string]any{"status": "Success", "dashboardMetadata": result.DashboardMetadata, "componentData": result.ComponentData}
		}
	case analyticsRouteReports:
		response, err = service.analytics.listReports(ctx, bearer, authority, analyticsListLimit(request.URL.Query().Get("limit")))
	case analyticsRouteReport:
		if !analyticsRequestBodyEmpty(writer, request, service.maxRequestBytes) {
			err = errAnalyticsInvalid
			break
		}
		response, err = service.analytics.runReport(ctx, bearer, route.id, authority, nil)
	case analyticsRouteReportDescribe:
		response, err = service.analytics.describeReport(ctx, bearer, route.id, authority)
	case analyticsRouteReportExecution:
		request.Body = http.MaxBytesReader(writer, request.Body, service.maxRequestBytes)
		var body struct {
			ReportID       string          `json:"reportId"`
			ReportMetadata json.RawMessage `json:"reportMetadata"`
			Limit          uint32          `json:"limit"`
		}
		decoder := json.NewDecoder(request.Body)
		decoder.DisallowUnknownFields()
		if decodeErr := decoder.Decode(&body); decodeErr != nil || requireJSONEOF(decoder) != nil || body.ReportID == "" || len(body.ReportMetadata) != 0 {
			err = errAnalyticsInvalid
			break
		}
		response, err = service.analytics.runReport(ctx, bearer, body.ReportID, authority, &body.Limit)
	case analyticsRouteReportDefinitionExecution:
		response, err = service.analytics.executeReportDefinition(ctx, bearer, authority, service.maxRequestBytes, writer, request)
	}
	if err != nil {
		service.failures.Add(1)
		writeAnalyticsFailure(writer, err)
		return true
	}
	service.successes.Add(1)
	writeJSON(writer, http.StatusOK, response)
	return true
}

func analyticsRequestBodyEmpty(writer http.ResponseWriter, request *http.Request, maximum int64) bool {
	request.Body = http.MaxBytesReader(writer, request.Body, maximum)
	body, err := io.ReadAll(request.Body)
	return err == nil && strings.TrimSpace(string(body)) == ""
}

func analyticsSingleQueryValue(query map[string][]string, name string) (string, bool) {
	values := query[name]
	if len(values) > 1 {
		return "", false
	}
	if len(values) == 0 {
		return "", true
	}
	return values[0], true
}

func analyticsMethodAllowed(kind analyticsRouteKind, method string) bool {
	switch kind {
	case analyticsRouteDashboard:
		return method == http.MethodGet || method == http.MethodPut
	case analyticsRouteDashboardRefresh, analyticsRouteReportExecution, analyticsRouteReportDefinitionExecution:
		return method == http.MethodPost
	case analyticsRouteReport:
		return method == http.MethodGet || method == http.MethodPost
	default:
		return method == http.MethodGet
	}
}

func analyticsAllowedMethods(kind analyticsRouteKind) string {
	switch kind {
	case analyticsRouteDashboard:
		return "GET, PUT"
	case analyticsRouteDashboardRefresh, analyticsRouteReportExecution, analyticsRouteReportDefinitionExecution:
		return "POST"
	case analyticsRouteReport:
		return "GET, POST"
	default:
		return "GET"
	}
}

var (
	errAnalyticsInvalid   = errors.New("invalid analytics request")
	errAnalyticsNotFound  = errors.New("analytics resource not found")
	errAnalyticsForbidden = errors.New("analytics access forbidden")
	errAnalyticsAuthority = errors.New("mixed analytics Runtime authority")
)

func writeAnalyticsFailure(writer http.ResponseWriter, err error) {
	switch {
	case errors.Is(err, errAnalyticsInvalid):
		writeCRMError(writer, http.StatusBadRequest, crmwire.SFCodeInvalidRequest, "Invalid analytics request")
	case errors.Is(err, errAnalyticsNotFound):
		writeCRMError(writer, http.StatusNotFound, crmwire.SFCodeNotFound, "Analytics resource not found")
	case errors.Is(err, errAnalyticsForbidden):
		writeCRMError(writer, http.StatusForbidden, crmwire.SFCodeForbidden, "Insufficient access")
	case errors.Is(err, errAnalyticsAuthority):
		writeCRMError(writer, http.StatusServiceUnavailable, crmwire.SFCodeUnknownException, "Service temporarily unavailable")
	default:
		writeRuntimeFailure(writer, err)
	}
}

func (client *RuntimeAnalyticsClient) authorize(ctx context.Context, bearer string) (commonsemantic.Receipts, error) {
	permissions, err := client.readPermissions(ctx, bearer, systemPermissionAuthorityRequest())
	if err != nil {
		return commonsemantic.Receipts{}, err
	}
	if err := permissionsemantic.ValidateResponse(permissions); err != nil {
		return commonsemantic.Receipts{}, err
	}
	for _, grant := range permissions.SystemPermissions {
		if grant.PermissionID == analyticsPermissionRunReports && grant.Granted {
			return permissions.Receipts, nil
		}
	}
	return commonsemantic.Receipts{}, errAnalyticsForbidden
}

func sameAnalyticsAuthority(expected, actual commonsemantic.Receipts) error {
	if expected.CatalogRevision != actual.CatalogRevision || expected.SecurityEpoch != actual.SecurityEpoch ||
		expected.SchemaGeneration != actual.SchemaGeneration || expected.EngineGeneration != actual.EngineGeneration {
		return errAnalyticsAuthority
	}
	return nil
}

func (client *RuntimeAnalyticsClient) sameAppMetadataAuthority(
	ctx context.Context,
	view catalogsemantic.AppMetadataViewV3,
	expected commonsemantic.Receipts,
) error {
	if err := sameAnalyticsAuthority(expected, view.Receipts); err == nil {
		return nil
	}
	reconciled, err := reconcileAppMetadataSecurityEpoch(
		ctx, client.reconcileAppMetadata, view.Receipts, expected,
	)
	if err != nil {
		return err
	}
	if reconciled {
		return nil
	}
	return errAnalyticsAuthority
}

func analyticsSelections(fields ...string) []querysemantic.Selection {
	result := make([]querysemantic.Selection, len(fields))
	for index, field := range fields {
		result[index] = querysemantic.Selection{Kind: querysemantic.SelectionField, Field: field}
	}
	return result
}

func analyticsStringPredicate(field, value string) querysemantic.Predicate {
	return querysemantic.Predicate{
		Kind: querysemantic.PredicateFieldComparison, Field: field, Operator: querysemantic.ComparisonEqual,
		Value: &querysemantic.Scalar{String: &value},
	}
}

type analyticsQueryPage struct {
	Records          []map[string]any
	TotalSize        uint64
	TotalSizeUnknown bool
	Done             bool
}

func (client *RuntimeAnalyticsClient) queryRecordPage(
	ctx context.Context,
	bearer string,
	authority commonsemantic.Receipts,
	request querysemantic.Request,
) (analyticsQueryPage, error) {
	revision := authority.CatalogRevision
	request.MinCatalogRevision = &revision
	if err := querysemantic.ValidateRequest(ctx, request); err != nil {
		return analyticsQueryPage{}, err
	}
	response, err := client.query(ctx, bearer, request)
	if err != nil {
		return analyticsQueryPage{}, err
	}
	if err := querysemantic.ValidateResponse(response); err != nil {
		return analyticsQueryPage{}, err
	}
	if err := sameAnalyticsAuthority(authority, response.Receipts); err != nil {
		return analyticsQueryPage{}, err
	}
	result := make([]map[string]any, 0, len(response.Records))
	for _, record := range response.Records {
		mapped, err := queryRecordFromSemantic(record)
		if err != nil {
			return analyticsQueryPage{}, err
		}
		result = append(result, mapped.Fields)
	}
	return analyticsQueryPage{Records: result, TotalSize: response.TotalSize, TotalSizeUnknown: response.TotalSizeUnknown, Done: response.Done}, nil
}

type analyticsDashboard struct {
	ID            string                        `json:"id"`
	Name          string                        `json:"name"`
	DeveloperName string                        `json:"developerName"`
	Description   string                        `json:"description,omitempty"`
	LayoutType    string                        `json:"layoutType,omitempty"`
	DashboardType string                        `json:"dashboardType,omitempty"`
	RunningUserID string                        `json:"runningUserId,omitempty"`
	Components    []analyticsDashboardComponent `json:"components"`
}

type analyticsDashboardComponent struct {
	ID          string         `json:"id"`
	DashboardID string         `json:"-"`
	ReportID    string         `json:"reportId"`
	Type        string         `json:"type"`
	Title       string         `json:"title"`
	Config      map[string]any `json:"config"`
}

type analyticsDashboardSummary struct {
	ID            string `json:"id"`
	Name          string `json:"name"`
	Label         string `json:"label"`
	DeveloperName string `json:"developerName"`
	FolderID      string `json:"folderId,omitempty"`
	Description   string `json:"description,omitempty"`
	LayoutType    string `json:"layoutType,omitempty"`
}

func (client *RuntimeAnalyticsClient) listDashboards(ctx context.Context, bearer string, authority commonsemantic.Receipts, limit uint32) (map[string]any, error) {
	page, err := client.queryRecordPage(ctx, bearer, authority, querysemantic.Request{
		ObjectID:   analyticsDashboardObject,
		Selections: analyticsSelections("Id", "Name", "DeveloperName", "FolderId", "Description", "LayoutType"),
		Limit:      limit,
		OrderBy:    []querysemantic.Sort{{Field: "Name", Direction: querysemantic.SortAscending}},
	})
	if err != nil {
		return nil, err
	}
	if page.TotalSizeUnknown {
		return nil, errAnalyticsAuthority
	}
	records := page.Records
	items := make([]analyticsDashboardSummary, 0, len(records))
	for _, record := range records {
		name := analyticsString(record["Name"])
		items = append(items, analyticsDashboardSummary{
			ID: analyticsString(record["Id"]), Name: name, Label: name,
			DeveloperName: analyticsString(record["DeveloperName"]), FolderID: analyticsString(record["FolderId"]),
			Description: analyticsString(record["Description"]), LayoutType: analyticsString(record["LayoutType"]),
		})
	}
	return map[string]any{"dashboards": items, "totalSize": page.TotalSize}, nil
}

func (client *RuntimeAnalyticsClient) dashboard(ctx context.Context, bearer, id string, authority commonsemantic.Receipts) (analyticsDashboard, error) {
	fields := analyticsSelections("Id", "Name", "DeveloperName", "Description", "LayoutType", "DashboardType", "RunningUserId")
	lookup := func(field string) (analyticsQueryPage, error) {
		page, err := client.queryRecordPage(ctx, bearer, authority, querysemantic.Request{
			ObjectID: analyticsDashboardObject, Selections: fields,
			Filter: analyticsStringPredicate(field, id), Limit: 1,
		})
		if err != nil {
			return analyticsQueryPage{}, err
		}
		if page.TotalSizeUnknown || !page.Done || page.TotalSize != uint64(len(page.Records)) {
			return analyticsQueryPage{}, errAnalyticsAuthority
		}
		return page, nil
	}
	page, err := lookup("DeveloperName")
	if err != nil {
		return analyticsDashboard{}, err
	}
	if len(page.Records) == 0 {
		page, err = lookup("Id")
		if err != nil {
			return analyticsDashboard{}, err
		}
	}
	if len(page.Records) != 1 {
		return analyticsDashboard{}, errAnalyticsNotFound
	}
	record := page.Records[0]
	resolvedID := analyticsString(record["Id"])
	componentPage, err := client.queryRecordPage(ctx, bearer, authority, querysemantic.Request{
		ObjectID:   analyticsComponentObject,
		Selections: analyticsSelections("Id", "DashboardId", "ReportId", "Type", "Title", "Config"),
		Filter:     analyticsStringPredicate("DashboardId", resolvedID), Limit: analyticsDashboardMaxParts,
		OrderBy: []querysemantic.Sort{{Field: "Id", Direction: querysemantic.SortAscending}},
	})
	if err != nil {
		return analyticsDashboard{}, err
	}
	if componentPage.TotalSizeUnknown || !componentPage.Done ||
		componentPage.TotalSize != uint64(len(componentPage.Records)) {
		return analyticsDashboard{}, errAnalyticsAuthority
	}
	components := componentPage.Records
	result := analyticsDashboard{
		ID: resolvedID, Name: analyticsString(record["Name"]), DeveloperName: analyticsString(record["DeveloperName"]),
		Description: analyticsString(record["Description"]), LayoutType: analyticsString(record["LayoutType"]),
		DashboardType: analyticsString(record["DashboardType"]), RunningUserID: analyticsString(record["RunningUserId"]),
		Components: make([]analyticsDashboardComponent, 0, len(components)),
	}
	for _, component := range components {
		properties := map[string]any{}
		if raw := analyticsString(component["Config"]); raw != "" {
			decoder := json.NewDecoder(strings.NewReader(raw))
			decoder.UseNumber()
			if err := decoder.Decode(&properties); err != nil || decoder.Decode(&struct{}{}) != io.EOF {
				return analyticsDashboard{}, errAnalyticsAuthority
			}
		}
		result.Components = append(result.Components, analyticsDashboardComponent{
			ID: analyticsString(component["Id"]), DashboardID: analyticsString(component["DashboardId"]),
			ReportID: analyticsString(component["ReportId"]),
			Type:     analyticsString(component["Type"]), Title: analyticsString(component["Title"]), Config: properties,
		})
	}
	return result, nil
}

type analyticsDashboardRun struct {
	DashboardMetadata analyticsDashboard        `json:"dashboardMetadata"`
	ComponentData     map[string]map[string]any `json:"componentData"`
}

func (client *RuntimeAnalyticsClient) runDashboard(ctx context.Context, bearer, id string, authority commonsemantic.Receipts, runningUser, startDate, endDate string) (analyticsDashboardRun, error) {
	if _, ok := analyticsRunningUser(runningUser); !ok || startDate != "" || endDate != "" {
		return analyticsDashboardRun{}, errAnalyticsInvalid
	}
	dashboard, err := client.dashboard(ctx, bearer, id, authority)
	if err != nil {
		return analyticsDashboardRun{}, err
	}
	seenComponents := make(map[string]struct{}, len(dashboard.Components))
	for _, component := range dashboard.Components {
		_, duplicate := seenComponents[component.ID]
		if component.ID == "" || duplicate || component.DashboardID != dashboard.ID ||
			(!analyticsDashboardDisplayOnly(component.Type) && component.ReportID == "") {
			return analyticsDashboardRun{}, errAnalyticsAuthority
		}
		seenComponents[component.ID] = struct{}{}
	}
	metadata, err := client.analyticsObjectSpecs(ctx, authority)
	if err != nil {
		return analyticsDashboardRun{}, err
	}
	canonicalFilters := []byte("{}")
	result := analyticsDashboardRun{DashboardMetadata: dashboard, ComponentData: make(map[string]map[string]any, len(dashboard.Components))}
	for _, component := range dashboard.Components {
		if analyticsDashboardDisplayOnly(component.Type) {
			continue
		}
		report, err := client.readSavedReport(ctx, bearer, component.ReportID, authority, metadata, canonicalFilters, 0)
		if err != nil {
			return analyticsDashboardRun{}, err
		}
		result.ComponentData[component.ID] = report
	}
	return result, nil
}

func analyticsDashboardDisplayOnly(componentType string) bool {
	return strings.EqualFold(componentType, "RichText") || strings.EqualFold(componentType, "Image")
}

type analyticsReportSummary struct {
	ID            string `json:"id"`
	Name          string `json:"name"`
	DeveloperName string `json:"developerName"`
	FolderID      string `json:"folderId,omitempty"`
	Description   string `json:"description,omitempty"`
	ReportType    string `json:"reportType,omitempty"`
	SourceObject  string `json:"sourceObject,omitempty"`
}

func (client *RuntimeAnalyticsClient) listReports(ctx context.Context, bearer string, authority commonsemantic.Receipts, limit uint32) (map[string]any, error) {
	page, err := client.queryRecordPage(ctx, bearer, authority, querysemantic.Request{
		ObjectID:   analyticsReportObject,
		Selections: analyticsSelections("Id", "Name", "DeveloperName", "FolderId", "Description", "ReportType", "SourceObject"),
		Limit:      limit,
		OrderBy:    []querysemantic.Sort{{Field: "Name", Direction: querysemantic.SortAscending}},
	})
	if err != nil {
		return nil, err
	}
	if page.TotalSizeUnknown {
		return nil, errAnalyticsAuthority
	}
	records := page.Records
	items := make([]analyticsReportSummary, 0, len(records))
	for _, record := range records {
		items = append(items, analyticsReportSummary{
			ID: analyticsString(record["Id"]), Name: analyticsString(record["Name"]), DeveloperName: analyticsString(record["DeveloperName"]),
			FolderID: analyticsString(record["FolderId"]), Description: analyticsString(record["Description"]),
			ReportType: analyticsString(record["ReportType"]), SourceObject: analyticsString(record["SourceObject"]),
		})
	}
	return map[string]any{"reports": items, "totalSize": page.TotalSize}, nil
}

func (client *RuntimeAnalyticsClient) runReport(ctx context.Context, bearer, id string, authority commonsemantic.Receipts, requestedLimit *uint32) (map[string]any, error) {
	limit := uint32(reportsemantic.MaxRows)
	if requestedLimit != nil && *requestedLimit != 0 {
		limit = *requestedLimit
	}
	metadata, err := client.analyticsObjectSpecs(ctx, authority)
	if err != nil {
		return nil, err
	}
	return client.readSavedReport(ctx, bearer, id, authority, metadata, []byte("{}"), limit)
}

func (client *RuntimeAnalyticsClient) readSavedReport(ctx context.Context, bearer, id string, authority commonsemantic.Receipts, metadata map[string]searchObjectSpec, canonicalFilters []byte, limit uint32) (map[string]any, error) {
	document, err := client.readSavedReportDocument(ctx, bearer, id, authority, canonicalFilters, limit)
	if err != nil {
		return nil, err
	}
	return projectCanonicalReport(document, metadata)
}

func (client *RuntimeAnalyticsClient) analyticsObjectSpecs(ctx context.Context, authority commonsemantic.Receipts) (map[string]searchObjectSpec, error) {
	revision := authority.CatalogRevision
	view, err := client.appMetadata(ctx, catalogsemantic.GetRequest{MinCatalogRevision: &revision})
	if err != nil {
		return nil, err
	}
	if err := catalogsemantic.ValidateAppMetadataViewV3(view); err != nil || view.AppID != AppID {
		return nil, errAnalyticsAuthority
	}
	if err := client.sameAppMetadataAuthority(ctx, view, authority); err != nil {
		return nil, err
	}
	metadata, err := searchObjectSpecsFromView(view)
	if err != nil {
		return nil, errAnalyticsAuthority
	}
	return metadata, nil
}

func (client *RuntimeAnalyticsClient) readSavedReportDocument(ctx context.Context, bearer, id string, authority commonsemantic.Receipts, canonicalFilters []byte, limit uint32) (canonicalReportDocument, error) {
	if limit == 0 {
		limit = reportsemantic.MaxRows
	}
	revision := authority.CatalogRevision
	request := reportsemantic.Request{ReportID: id, CanonicalFilters: canonicalFilters, Limit: limit, MinCatalogRevision: &revision}
	if err := reportsemantic.ValidateRequest(ctx, request); err != nil {
		return canonicalReportDocument{}, err
	}
	response, err := client.readReport(ctx, bearer, request)
	if err != nil {
		return canonicalReportDocument{}, err
	}
	if err := reportsemantic.ValidateResponse(response); err != nil {
		return canonicalReportDocument{}, err
	}
	if err := sameAnalyticsAuthority(authority, response.Receipts); err != nil {
		return canonicalReportDocument{}, err
	}
	return decodeCanonicalReport(response.CanonicalResult, id)
}

func (client *RuntimeAnalyticsClient) describeReport(ctx context.Context, bearer, id string, authority commonsemantic.Receipts) (map[string]any, error) {
	// ReportRead is the immutable definition owner. A one-row read provides its
	// exact selected definition/version/digest; no repository/global metadata
	// lookup is introduced merely for the describe projection.
	document, err := client.readSavedReportDocument(ctx, bearer, id, authority, []byte("{}"), 1)
	if err != nil {
		return nil, err
	}
	metadata, err := client.analyticsObjectSpecs(ctx, authority)
	if err != nil {
		return nil, err
	}
	projection, err := projectCanonicalReportDefinition(document, metadata)
	if err != nil {
		return nil, err
	}
	return map[string]any{"reportMetadata": projection}, nil
}

type canonicalReportDocument struct {
	Schema               string                     `json:"schema"`
	ReportID             string                     `json:"reportId"`
	Name                 string                     `json:"name"`
	DefinitionVersion    string                     `json:"definitionVersion"`
	DefinitionDigest     string                     `json:"definitionDigest"`
	Definition           canonicalReportDefinition  `json:"definition"`
	DisplayMode          string                     `json:"displayMode"`
	Columns              []string                   `json:"columns"`
	Grouping             []string                   `json:"grouping"`
	Aggregates           []canonicalReportAggregate `json:"aggregates"`
	Rows                 []map[string]any           `json:"rows"`
	TotalCount           int                        `json:"totalCount"`
	AggregateDedupColumn map[string]string          `json:"aggregateDedupColumn,omitempty"`
}

type canonicalReportDefinition struct {
	SourceObject string                     `json:"sourceObject"`
	SourceRef    string                     `json:"sourceRef"`
	DisplayMode  string                     `json:"displayMode"`
	Scope        string                     `json:"scope"`
	Columns      []string                   `json:"columns"`
	Filters      []canonicalReportFilter    `json:"filters"`
	Grouping     []string                   `json:"grouping"`
	Aggregates   []canonicalReportAggregate `json:"aggregates"`
	DateFilter   *canonicalReportDateFilter `json:"dateFilter,omitempty"`
}

type canonicalReportFilter struct {
	Column   string `json:"column"`
	Operator string `json:"operator"`
	Value    string `json:"value"`
}

type canonicalReportDateFilter struct {
	Column        string `json:"column"`
	DurationValue string `json:"durationValue"`
	StartDate     string `json:"startDate"`
	EndDate       string `json:"endDate"`
}

type canonicalReportAggregate struct {
	Field string `json:"field"`
	Type  string `json:"type"`
}

func decodeCanonicalReport(payload []byte, expectedID string) (canonicalReportDocument, error) {
	decoder := json.NewDecoder(strings.NewReader(string(payload)))
	decoder.UseNumber()
	var document canonicalReportDocument
	if err := decoder.Decode(&document); err != nil || decoder.Decode(&struct{}{}) != io.EOF ||
		document.Schema != "nexuscrm.report-result/v1" || document.ReportID != expectedID ||
		document.Name == "" || document.DefinitionVersion == "" || document.DefinitionDigest == "" || document.TotalCount < 0 ||
		(document.Definition.SourceObject == "" && document.Definition.SourceRef == "") ||
		!validCanonicalReportDisplayMode(document.DisplayMode) ||
		!validCanonicalReportDisplayMode(document.Definition.DisplayMode) ||
		!validCanonicalAggregates(document.Aggregates) ||
		!validCanonicalAggregates(document.Definition.Aggregates) ||
		!sameCanonicalAggregateShape(document.Aggregates, document.Definition.Aggregates) ||
		!validCanonicalTotalCount(document) ||
		!validCanonicalAggregateValues(document) ||
		!validCanonicalDedupColumns(document.Aggregates, document.Rows, document.AggregateDedupColumn) ||
		!validCanonicalPreAggregatedSummary(document) {
		return canonicalReportDocument{}, errAnalyticsAuthority
	}
	return document, nil
}

func validCanonicalReportDisplayMode(value string) bool {
	switch strings.ToUpper(strings.TrimSpace(value)) {
	case "", "TABULAR", "SUMMARY":
		return true
	default:
		// MATRIX and unknown modes need a different factMap projection. The frozen
		// read slice must reject them instead of presenting tabular semantics.
		return false
	}
}

func validCanonicalTotalCount(document canonicalReportDocument) bool {
	// Pre-aggregated rows represent groups, not detail records, so their count is
	// not comparable to TotalCount. RowCount summaries are checked separately by
	// validCanonicalPreAggregatedSummary.
	if canonicalRowsArePreAggregatedSummary(document) {
		return true
	}
	// ReportRead is paginated: a nonzero total may exceed the returned page, but
	// it cannot be smaller than the number of detail rows in that page.
	return document.TotalCount == 0 || document.TotalCount >= len(document.Rows)
}

func validCanonicalAggregateValues(document canonicalReportDocument) bool {
	// Marker rows carry an already-computed aggregate in "val" and are validated
	// by validCanonicalPreAggregatedSummary rather than by execution field name.
	if canonicalRowsArePreAggregatedSummary(document) {
		return true
	}
	for _, aggregate := range document.Aggregates {
		switch aggregate.Type {
		case "SUM", "AVG", "MIN", "MAX":
			for _, row := range document.Rows {
				value := rowValue(row, aggregate.Field)
				if value == nil {
					continue
				}
				if _, ok := analyticsNumber(value); !ok {
					return false
				}
			}
		}
	}
	return true
}

func canonicalRowsArePreAggregatedSummary(document canonicalReportDocument) bool {
	return strings.EqualFold(strings.TrimSpace(document.DisplayMode), "SUMMARY") &&
		len(document.Grouping) == 1 && len(document.Columns) == 0 &&
		analyticsAggregatedRows(document.Rows)
}

func sameCanonicalAggregateShape(execution, definition []canonicalReportAggregate) bool {
	if len(execution) != len(definition) {
		return false
	}
	for index := range execution {
		if execution[index].Type != definition[index].Type {
			return false
		}
	}
	return true
}

func validCanonicalAggregates(aggregates []canonicalReportAggregate) bool {
	for _, aggregate := range aggregates {
		switch aggregate.Type {
		case "RowCount":
			if aggregate.Field != "" {
				return false
			}
		case "COUNT":
			if aggregate.Field == "" {
				return false
			}
		case "SUM", "AVG", "MIN", "MAX":
			if aggregate.Field == "" {
				return false
			}
		default:
			return false
		}
	}
	return true
}

func validCanonicalPreAggregatedSummary(document canonicalReportDocument) bool {
	// The current Runtime producer uses the reserved name/val row shape only
	// for the no-detail, single-group analytics path. Once that shape is
	// present, do not let a contradictory display/grouping declaration fall
	// through to the ordinary summary projector.
	if len(document.Columns) != 0 ||
		!canonicalRowsContainAggregateMarkers(document.Rows) {
		return true
	}
	if !strings.EqualFold(strings.TrimSpace(document.DisplayMode), "SUMMARY") ||
		len(document.Grouping) != 1 || !analyticsAggregatedRows(document.Rows) ||
		len(document.Aggregates) > 1 {
		return false
	}
	if len(document.Aggregates) == 1 && strings.EqualFold(document.Aggregates[0].Type, "AVG") {
		return false
	}
	rowCountValues := len(document.Aggregates) == 0 || document.Aggregates[0].Type == "RowCount"
	integerValues := rowCountValues || len(document.Aggregates) == 1 && document.Aggregates[0].Type == "COUNT"
	totalCount := 0
	for _, row := range document.Rows {
		if analyticsFormat(row["name"]) == "" {
			return false
		}
		if !integerValues {
			if _, ok := analyticsNumber(row["val"]); !ok {
				return false
			}
			continue
		}
		value, ok := analyticsInteger(row["val"])
		if !ok || value < 0 || value > int(^uint(0)>>1)-totalCount {
			return false
		}
		if rowCountValues {
			totalCount += value
		}
	}
	if !rowCountValues {
		return true
	}
	return document.TotalCount == 0 || document.TotalCount == totalCount
}

func validCanonicalDedupColumns(
	aggregates []canonicalReportAggregate,
	rows []map[string]any,
	columns map[string]string,
) bool {
	fields := make(map[string]struct{}, len(aggregates))
	for _, aggregate := range aggregates {
		if aggregate.Field != "" {
			fields[aggregate.Field] = struct{}{}
		}
	}
	for field, column := range columns {
		if _, ok := fields[field]; !ok || column == "" {
			return false
		}
		for _, row := range rows {
			identity, ok := rowValue(row, column).(string)
			if !ok || identity == "" {
				return false
			}
		}
	}
	return true
}

func projectCanonicalReport(document canonicalReportDocument, objects map[string]searchObjectSpec) (map[string]any, error) {
	format := strings.ToUpper(strings.TrimSpace(document.DisplayMode))
	if format == "" {
		format = "TABULAR"
	}
	sourceObject, sourceRef := analyticsReportSource(document.Definition)
	columns := append([]string{}, document.Columns...)
	definitionColumns := append([]string{}, document.Definition.Columns...)
	if format != "SUMMARY" || len(document.Grouping) != 1 || !analyticsAggregatedRows(document.Rows) {
		columns, definitionColumns = analyticsEffectiveColumns(document)
	}
	document.Columns = columns
	document.Definition.Columns = definitionColumns
	aggregateKeys := analyticsAggregateKeys(document.Aggregates)
	extendedMetadata, err := analyticsExtendedMetadata(
		sourceObject,
		columns, definitionColumns,
		document.Grouping, document.Definition.Grouping,
		document.Aggregates, document.Definition.Aggregates,
		objects,
	)
	if err != nil {
		return nil, err
	}
	metadata := map[string]any{
		"id": document.ReportID, "name": document.Name, "reportFormat": format,
		"reportType": analyticsReportType(sourceObject, sourceRef), "sourceObject": sourceObject,
		"detailColumns": append([]string{}, document.Columns...), "aggregates": aggregateKeys,
		"definitionVersion": document.DefinitionVersion, "definitionDigest": document.DefinitionDigest,
		"groupingsDown":          analyticsGroupingMetadata(document.Grouping),
		"reportExtendedMetadata": extendedMetadata,
	}
	if document.Definition.SourceRef != "" {
		metadata["sourceRef"] = document.Definition.SourceRef
	}
	if document.Definition.Scope != "" {
		metadata["scope"] = document.Definition.Scope
	}
	if len(document.Definition.Filters) > 0 {
		filters := make([]map[string]any, len(document.Definition.Filters))
		for index, filter := range document.Definition.Filters {
			filters[index] = map[string]any{
				"column": filter.Column, "operator": filter.Operator, "value": filter.Value,
			}
		}
		metadata["reportFilters"] = filters
	}
	if filter := document.Definition.DateFilter; filter != nil {
		metadata["standardDateFilter"] = map[string]any{
			"column": filter.Column, "durationValue": filter.DurationValue,
			"startDate": filter.StartDate, "endDate": filter.EndDate,
		}
	}
	if format == "SUMMARY" && len(document.Grouping) > 0 {
		if len(document.Grouping) == 1 && analyticsAggregatedRows(document.Rows) {
			return analyticsAggregatedSummaryReport(metadata, document), nil
		}
		return analyticsSummaryReport(metadata, document), nil
	}
	return analyticsTabularReport(metadata, document), nil
}

func analyticsEffectiveColumns(document canonicalReportDocument) ([]string, []string) {
	columns := append([]string{}, document.Columns...)
	definitionColumns := append([]string{}, document.Definition.Columns...)
	if len(columns) != 0 || len(definitionColumns) != 0 || len(document.Rows) == 0 {
		return columns, definitionColumns
	}
	for key := range document.Rows[0] {
		if key != "attributes" && key != "_metadata" && !strings.HasPrefix(key, "__") {
			columns = append(columns, key)
		}
	}
	sort.Strings(columns)
	return columns, append([]string{}, columns...)
}

func projectCanonicalReportDefinition(document canonicalReportDocument, objects map[string]searchObjectSpec) (map[string]any, error) {
	definition := document.Definition
	format := strings.ToUpper(strings.TrimSpace(definition.DisplayMode))
	if format == "" {
		format = strings.ToUpper(strings.TrimSpace(document.DisplayMode))
	}
	if format == "" {
		format = "TABULAR"
	}
	sourceObject, sourceRef := analyticsReportSource(definition)
	extendedMetadata, err := analyticsExtendedMetadata(
		sourceObject,
		definition.Columns, definition.Columns,
		definition.Grouping, definition.Grouping,
		nil, nil,
		objects,
	)
	if err != nil {
		return nil, err
	}
	filters := make([]map[string]any, len(definition.Filters))
	for index, filter := range definition.Filters {
		filters[index] = map[string]any{
			"column": filter.Column, "operator": filter.Operator, "value": filter.Value,
		}
	}
	metadata := map[string]any{
		"id": document.ReportID, "name": document.Name,
		"reportFormat": format, "reportType": analyticsReportType(sourceObject, sourceRef),
		"sourceObject": sourceObject, "sourceRef": definition.SourceRef,
		"scope":                  definition.Scope,
		"detailColumns":          append([]string{}, definition.Columns...),
		"reportFilters":          filters,
		"groupingsDown":          analyticsGroupingMetadata(definition.Grouping),
		"definitionVersion":      document.DefinitionVersion,
		"definitionDigest":       document.DefinitionDigest,
		"reportExtendedMetadata": extendedMetadata,
	}
	if definition.DateFilter != nil {
		metadata["standardDateFilter"] = map[string]any{
			"column":        definition.DateFilter.Column,
			"durationValue": definition.DateFilter.DurationValue,
			"startDate":     definition.DateFilter.StartDate,
			"endDate":       definition.DateFilter.EndDate,
		}
	}
	return metadata, nil
}

func analyticsReportSource(definition canonicalReportDefinition) (string, string) {
	rawSourceObject := strings.TrimSpace(definition.SourceObject)
	sourceObject := analyticsNormalizeReportSourceObject(rawSourceObject)
	sourceRef := strings.TrimSpace(definition.SourceRef)
	if sourceRef == "" {
		if rawSourceObject != sourceObject {
			sourceRef = rawSourceObject
		} else {
			sourceRef = sourceObject + "List"
		}
	} else if strings.EqualFold(sourceRef, sourceObject) || analyticsReportFormatName(sourceRef) {
		sourceRef = sourceObject + "List"
	}
	return sourceObject, sourceRef
}

func analyticsNormalizeReportSourceObject(sourceObject string) string {
	if index := strings.Index(sourceObject, "With"); index > 0 {
		sourceObject = sourceObject[:index]
	}
	for _, suffix := range []string{"FieldAuditHistory", "AuditHistory", "Activity", "List", "Report"} {
		if strings.HasSuffix(sourceObject, suffix) {
			return strings.TrimSuffix(sourceObject, suffix)
		}
	}
	return sourceObject
}

func analyticsReportFormatName(value string) bool {
	switch strings.ToUpper(strings.TrimSpace(value)) {
	case "TABULAR", "SUMMARY", "MATRIX":
		return true
	default:
		return false
	}
}

func analyticsReportType(sourceObject, sourceRef string) map[string]any {
	return map[string]any{"type": sourceRef, "label": sourceObject}
}

func analyticsTabularReport(metadata map[string]any, document canonicalReportDocument) map[string]any {
	columns := append([]string{}, document.Columns...)
	rows := analyticsDetailRows(document.Rows, columns)
	totalCount := analyticsTotalCount(document)
	return map[string]any{
		"reportMetadata": metadata,
		"factMap": map[string]any{"T!T": map[string]any{
			"rows": rows, "aggregates": []map[string]any{{"label": strconv.Itoa(totalCount), "value": totalCount}},
		}},
		"groupingsDown": map[string]any{"groupings": []any{}},
		"hasDetailRows": len(rows) > 0,
		"allData":       len(document.Rows) >= totalCount,
	}
}

func analyticsSummaryReport(metadata map[string]any, document canonicalReportDocument) map[string]any {
	factMap := map[string]any{}
	grand := analyticsAggregateValues(document.Rows, document.Aggregates, document.AggregateDedupColumn)
	if len(grand) == 0 {
		totalCount := analyticsTotalCount(document)
		grand = []map[string]any{{"label": strconv.Itoa(totalCount), "value": totalCount}}
	} else {
		overrideAnalyticsRowCount(grand, document.Aggregates, analyticsTotalCount(document))
	}
	factMap["T!T"] = map[string]any{"aggregates": grand, "rows": []any{}}
	groupings := analyticsGroupingLevel(document.Rows, document.Grouping, document.Aggregates, document.Columns, document.AggregateDedupColumn, factMap, 0, "")
	return map[string]any{
		"reportMetadata": metadata, "factMap": factMap,
		"groupingsDown": map[string]any{"groupings": groupings},
		"hasDetailRows": len(document.Rows) > 0,
	}
}

func analyticsTotalCount(document canonicalReportDocument) int {
	if document.TotalCount != 0 {
		return document.TotalCount
	}
	return len(document.Rows)
}

func analyticsAggregatedSummaryReport(metadata map[string]any, document canonicalReportDocument) map[string]any {
	groupings := make([]map[string]any, 0, len(document.Rows))
	factMap := make(map[string]any, len(document.Rows)+1)
	rowCountValues := len(document.Aggregates) == 0 || document.Aggregates[0].Type == "RowCount"
	grandTotal := new(big.Rat)
	var aggregateType string
	if len(document.Aggregates) == 1 {
		aggregateType = document.Aggregates[0].Type
	}
	// The legacy grouped analytics engine returns only {name,val}; it does not
	// return a per-group row count alongside an explicit SUM/COUNT/MIN/MAX.
	// Do not advertise an implicit RowCount key that would shift the one proven
	// aggregate value into the wrong Salesforce metadata slot.
	if len(document.Aggregates) == 1 && !rowCountValues {
		keys := analyticsAggregateKeys(document.Aggregates)
		metadata["aggregates"] = append([]string{}, keys[len(keys)-1:]...)
		if extended, ok := metadata["reportExtendedMetadata"].(map[string]any); ok {
			if info, ok := extended["aggregateColumnInfo"].(map[string]any); ok {
				delete(info, "RowCount")
			}
		}
	}
	for index, row := range document.Rows {
		label := analyticsFormat(row["name"])
		value, _ := analyticsNumber(row["val"])
		key := strconv.Itoa(index)
		groupings = append(groupings, map[string]any{"label": label, "value": label, "key": key})
		wireValue := any(analyticsJSONNumber(value))
		if rowCountValues {
			integer, _ := analyticsInteger(row["val"])
			wireValue = integer
		}
		factMap[key+"!T"] = map[string]any{
			"aggregates": []map[string]any{{"label": analyticsFormat(wireValue), "value": wireValue}},
			"rows":       []any{},
		}
		if index == 0 || aggregateType == "MIN" || aggregateType == "MAX" {
			if index == 0 || aggregateType == "MIN" && value.Cmp(grandTotal) < 0 || aggregateType == "MAX" && value.Cmp(grandTotal) > 0 {
				grandTotal.Set(value)
			}
		} else {
			grandTotal.Add(grandTotal, value)
		}
	}
	aggregateGrandValue := any(analyticsJSONNumber(grandTotal))
	if rowCountValues {
		integer, _ := analyticsInteger(analyticsJSONNumber(grandTotal))
		aggregateGrandValue = integer
	}
	rowCount := document.TotalCount
	if rowCount == 0 {
		if rowCountValues {
			rowCount, _ = analyticsInteger(analyticsJSONNumber(grandTotal))
		} else {
			rowCount = len(document.Rows)
		}
	}
	grand := []map[string]any{{"label": strconv.Itoa(rowCount), "value": rowCount}}
	if len(document.Aggregates) == 1 && document.Aggregates[0].Type != "RowCount" {
		grand = []map[string]any{{"label": analyticsFormat(aggregateGrandValue), "value": aggregateGrandValue}}
	}
	factMap["T!T"] = map[string]any{"aggregates": grand, "rows": []any{}}
	return map[string]any{
		"reportMetadata": metadata, "factMap": factMap,
		"groupingsDown": map[string]any{"groupings": groupings},
		"hasDetailRows": false,
	}
}

func overrideAnalyticsRowCount(values []map[string]any, aggregates []canonicalReportAggregate, totalCount int) {
	if len(values) == 0 {
		return
	}
	rowCountIndex := 0
	found := false
	for index, aggregate := range aggregates {
		if aggregate.Field == "" && strings.EqualFold(aggregate.Type, "RowCount") {
			rowCountIndex = index
			found = true
			break
		}
	}
	if !found {
		rowCountIndex = 0
	}
	if rowCountIndex < len(values) {
		values[rowCountIndex] = map[string]any{"label": strconv.Itoa(totalCount), "value": totalCount}
	}
}

func analyticsAggregatedRows(rows []map[string]any) bool {
	if len(rows) == 0 {
		return false
	}
	for _, row := range rows {
		_, hasName := row["name"]
		_, hasValue := row["val"]
		if !hasName || !hasValue || len(row) != 2 {
			return false
		}
	}
	return true
}

func canonicalRowsContainAggregateMarkers(rows []map[string]any) bool {
	for _, row := range rows {
		_, hasName := row["name"]
		_, hasValue := row["val"]
		if hasName || hasValue {
			return true
		}
	}
	return false
}

func analyticsGroupingLevel(rows []map[string]any, fields []string, aggregates []canonicalReportAggregate, columns []string, dedupColumns map[string]string, factMap map[string]any, level int, prefix string) []map[string]any {
	if level >= len(fields) {
		return []map[string]any{}
	}
	type bucket struct {
		label string
		rows  []map[string]any
	}
	ordered := []string{}
	buckets := map[string]*bucket{}
	for _, row := range rows {
		label := analyticsFormat(rowValue(row, fields[level]))
		if label == "" {
			label = "(blank)"
		}
		if buckets[label] == nil {
			buckets[label] = &bucket{label: label}
			ordered = append(ordered, label)
		}
		buckets[label].rows = append(buckets[label].rows, row)
	}
	result := make([]map[string]any, 0, len(ordered))
	leaf := level == len(fields)-1
	for index, label := range ordered {
		key := strconv.Itoa(index)
		if prefix != "" {
			key = prefix + "_" + key
		}
		entry := map[string]any{"aggregates": analyticsAggregateValues(buckets[label].rows, aggregates, dedupColumns), "rows": []any{}}
		if leaf {
			entry["rows"] = analyticsDetailRows(buckets[label].rows, columns)
		}
		factMap[key+"!T"] = entry
		grouping := map[string]any{"key": key, "label": fmt.Sprintf("%s (%d)", label, len(buckets[label].rows)), "value": label}
		if !leaf {
			grouping["groupings"] = analyticsGroupingLevel(buckets[label].rows, fields, aggregates, columns, dedupColumns, factMap, level+1, key)
		}
		result = append(result, grouping)
	}
	return result
}

func analyticsDetailRows(rows []map[string]any, columns []string) []map[string]any {
	result := make([]map[string]any, 0, len(rows))
	for _, row := range rows {
		cells := make([]map[string]any, len(columns))
		for index, column := range columns {
			value := rowValue(row, column)
			cells[index] = map[string]any{"label": analyticsFormat(value), "value": value}
		}
		result = append(result, map[string]any{"dataCells": cells})
	}
	return result
}

func analyticsAggregateValues(rows []map[string]any, aggregates []canonicalReportAggregate, dedupColumns map[string]string) []map[string]any {
	hasRowCount := false
	for _, aggregate := range aggregates {
		if aggregate.Field == "" && strings.EqualFold(aggregate.Type, "RowCount") {
			hasRowCount = true
		}
	}
	result := []map[string]any{}
	if !hasRowCount {
		result = append(result, map[string]any{"label": strconv.Itoa(len(rows)), "value": len(rows)})
	}
	for _, aggregate := range aggregates {
		if aggregate.Field == "" && strings.EqualFold(aggregate.Type, "RowCount") {
			result = append(result, map[string]any{"label": strconv.Itoa(len(rows)), "value": len(rows)})
			continue
		}
		if strings.EqualFold(aggregate.Type, "COUNT") {
			count := 0
			seen := map[string]struct{}{}
			dedupColumn := dedupColumns[aggregate.Field]
			for _, row := range rows {
				if dedupColumn != "" {
					identity := analyticsFormat(rowValue(row, dedupColumn))
					if identity != "" {
						if _, duplicate := seen[identity]; duplicate {
							continue
						}
						seen[identity] = struct{}{}
					}
				}
				if aggregate.Field == "" || rowValue(row, aggregate.Field) != nil {
					count++
				}
			}
			result = append(result, map[string]any{"label": strconv.Itoa(count), "value": count})
			continue
		}
		values := make([]*big.Rat, 0, len(rows))
		seen := map[string]struct{}{}
		dedupColumn := dedupColumns[aggregate.Field]
		for _, row := range rows {
			if dedupColumn != "" {
				identity := analyticsFormat(rowValue(row, dedupColumn))
				if identity != "" {
					if _, duplicate := seen[identity]; duplicate {
						continue
					}
					seen[identity] = struct{}{}
				}
			}
			if value, ok := analyticsNumber(rowValue(row, aggregate.Field)); ok {
				values = append(values, value)
			}
		}
		value := new(big.Rat)
		if len(values) > 0 {
			value.Set(values[0])
			switch strings.ToUpper(aggregate.Type) {
			case "SUM", "AVG":
				value.SetInt64(0)
				for _, item := range values {
					value.Add(value, item)
				}
				if strings.EqualFold(aggregate.Type, "AVG") {
					value.Quo(value, new(big.Rat).SetInt64(int64(len(values))))
				}
			case "MIN":
				for _, item := range values[1:] {
					if item.Cmp(value) < 0 {
						value.Set(item)
					}
				}
			case "MAX":
				for _, item := range values[1:] {
					if item.Cmp(value) > 0 {
						value.Set(item)
					}
				}
			}
		}
		number := analyticsJSONNumber(value)
		result = append(result, map[string]any{"label": number.String(), "value": number})
	}
	return result
}

func analyticsAggregateKeys(aggregates []canonicalReportAggregate) []string {
	keys := []string{}
	hasRowCount := false
	for _, aggregate := range aggregates {
		key := aggregate.Type
		if aggregate.Field != "" {
			switch strings.ToUpper(aggregate.Type) {
			case "COUNT":
				key = "c!" + aggregate.Field
			case "SUM":
				key = "s!" + aggregate.Field
			case "AVG":
				key = "a!" + aggregate.Field
			case "MIN":
				key = "mn!" + aggregate.Field
			case "MAX":
				key = "mx!" + aggregate.Field
			}
		}
		if key == "RowCount" {
			hasRowCount = true
		}
		keys = append(keys, key)
	}
	if !hasRowCount {
		keys = append([]string{"RowCount"}, keys...)
	}
	return keys
}

func analyticsGroupingMetadata(fields []string) []map[string]any {
	result := make([]map[string]any, len(fields))
	for index, field := range fields {
		result[index] = map[string]any{"name": field, "sortOrder": "Asc", "dateGranularity": "NONE"}
	}
	return result
}

func analyticsExtendedMetadata(
	sourceObject string,
	columns, definitionColumns []string,
	groupings, definitionGroupings []string,
	aggregates, definitionAggregates []canonicalReportAggregate,
	objects map[string]searchObjectSpec,
) (map[string]any, error) {
	if len(columns) != len(definitionColumns) ||
		len(groupings) != len(definitionGroupings) ||
		len(aggregates) != len(definitionAggregates) {
		return nil, errAnalyticsAuthority
	}
	columnInfo := map[string]any{}
	for index, column := range columns {
		field, ok := analyticsFieldSpec(objects, sourceObject, definitionColumns[index])
		if !ok || !validAnalyticsFieldTypeAuthority(field) {
			return nil, errAnalyticsAuthority
		}
		columnInfo[column] = map[string]any{
			"label": field.Label, "dataType": analyticsFieldDataType(field),
		}
	}
	groupingInfo := map[string]any{}
	for index, grouping := range groupings {
		field, ok := analyticsFieldSpec(objects, sourceObject, definitionGroupings[index])
		if !ok || !validAnalyticsFieldTypeAuthority(field) {
			return nil, errAnalyticsAuthority
		}
		groupingInfo[grouping] = map[string]any{
			"label": field.Label, "dataType": analyticsFieldDataType(field),
		}
	}
	aggregateInfo := map[string]any{"RowCount": map[string]any{"label": "Record Count", "dataType": "int"}}
	keys := analyticsAggregateKeys(aggregates)
	offset := 0
	if len(keys) > len(aggregates) {
		offset = 1
	}
	for index, aggregate := range aggregates {
		if aggregate.Field == "" && strings.EqualFold(aggregate.Type, "RowCount") {
			continue
		}
		definitionAggregate := definitionAggregates[index]
		field, ok := analyticsFieldSpec(objects, sourceObject, definitionAggregate.Field)
		if !ok || !validAnalyticsFieldTypeAuthority(field) {
			return nil, errAnalyticsAuthority
		}
		dataType := analyticsFieldDataType(field)
		if strings.EqualFold(aggregate.Type, "COUNT") {
			dataType = "int"
		}
		aggregateInfo[keys[index+offset]] = map[string]any{
			"label": field.Label, "dataType": dataType,
		}
	}
	return map[string]any{"detailColumnInfo": columnInfo, "groupingColumnInfo": groupingInfo, "aggregateColumnInfo": aggregateInfo}, nil
}

func analyticsFieldSpec(objects map[string]searchObjectSpec, sourceObject, column string) (searchFieldSpec, bool) {
	column = strings.TrimSuffix(strings.TrimSpace(column), ".CONVERT")
	if column == "" {
		return searchFieldSpec{}, false
	}
	objectName := analyticsNormalizeReportSourceObject(sourceObject)
	fieldName := column
	if index := strings.LastIndex(column, "."); index >= 0 {
		prefix := column[:index]
		fieldName = column[index+1:]
		if _, exists := objects[strings.ToLower(prefix)]; exists {
			objectName = prefix
		}
	}
	object, ok := objects[strings.ToLower(objectName)]
	if !ok {
		return searchFieldSpec{}, false
	}
	for _, field := range object.Fields {
		if strings.EqualFold(field.APIName, fieldName) {
			if strings.TrimSpace(field.Label) == "" {
				return searchFieldSpec{}, false
			}
			return field, true
		}
	}
	return searchFieldSpec{}, false
}

func validAnalyticsFieldTypeAuthority(field searchFieldSpec) bool {
	fieldType := strings.ToLower(strings.TrimSpace(field.Type))
	if fieldType == "formula" || fieldType == "rollupsummary" {
		return strings.TrimSpace(field.ReturnType) != ""
	}
	return true
}

func analyticsFieldDataType(field searchFieldSpec) string {
	fieldType := strings.ToLower(strings.TrimSpace(field.Type))
	if (fieldType == "formula" || fieldType == "rollupsummary") &&
		strings.TrimSpace(field.ReturnType) != "" {
		fieldType = strings.ToLower(strings.TrimSpace(field.ReturnType))
	}
	switch fieldType {
	case "date", "datetime":
		return "date"
	case "currency":
		return "currency"
	case "percent":
		return "percent"
	case "boolean", "checkbox":
		return "boolean"
	case "double", "number":
		return "double"
	case "int", "integer":
		return "int"
	default:
		// Salesforce analytics collapses every other described scalar (text,
		// reference, picklist, address, location, encrypted, and future textual
		// aliases) to string. The field still has to exist in the immutable
		// AppMetadata view; this is only the L1 wire-type projection.
		return "string"
	}
}

func rowValue(row map[string]any, column string) any {
	if value, ok := row[column]; ok {
		return value
	}
	if index := strings.LastIndex(column, "."); index >= 0 {
		if value, ok := row[column[index+1:]]; ok {
			return value
		}
	}
	underscored := strings.ReplaceAll(column, ".", "_")
	if value, ok := row[underscored]; ok {
		return value
	}
	for key, value := range row {
		if strings.EqualFold(key, column) {
			return value
		}
	}
	return nil
}

func analyticsString(value any) string {
	result, _ := value.(string)
	return result
}

func analyticsFormat(value any) string {
	if value == nil {
		return ""
	}
	return fmt.Sprint(value)
}

func analyticsNumber(value any) (*big.Rat, bool) {
	var raw string
	switch typed := value.(type) {
	case json.Number:
		raw = typed.String()
	case float64:
		raw = strconv.FormatFloat(typed, 'g', -1, 64)
	case int:
		return new(big.Rat).SetInt64(int64(typed)), true
	case int64:
		return new(big.Rat).SetInt64(typed), true
	case uint:
		return new(big.Rat).SetInt(new(big.Int).SetUint64(uint64(typed))), true
	case uint64:
		return new(big.Rat).SetInt(new(big.Int).SetUint64(typed)), true
	case string:
		raw = strings.TrimSpace(typed)
	default:
		return nil, false
	}
	decoder := json.NewDecoder(strings.NewReader(raw))
	decoder.UseNumber()
	var decoded any
	if err := decoder.Decode(&decoded); err != nil || decoder.Decode(&struct{}{}) != io.EOF {
		return nil, false
	}
	number, ok := decoded.(json.Number)
	if !ok {
		return nil, false
	}
	result, ok := new(big.Rat).SetString(number.String())
	return result, ok
}

func analyticsInteger(value any) (int, bool) {
	number, ok := analyticsNumber(value)
	if !ok || !number.IsInt() || !number.Num().IsInt64() {
		return 0, false
	}
	integer := number.Num().Int64()
	if strconv.IntSize == 32 && (integer < -1<<31 || integer > 1<<31-1) {
		return 0, false
	}
	return int(integer), true
}

func analyticsJSONNumber(value *big.Rat) json.Number {
	denominator := new(big.Int).Set(value.Denom())
	two, five := big.NewInt(2), big.NewInt(5)
	twos, fives := 0, 0
	for {
		quotient, modulus := new(big.Int), new(big.Int)
		quotient.QuoRem(denominator, two, modulus)
		if modulus.Sign() != 0 {
			break
		}
		denominator = quotient
		twos++
	}
	for {
		quotient, modulus := new(big.Int), new(big.Int)
		quotient.QuoRem(denominator, five, modulus)
		if modulus.Sign() != 0 {
			break
		}
		denominator = quotient
		fives++
	}
	precision := 34
	if denominator.Cmp(big.NewInt(1)) == 0 {
		precision = max(twos, fives)
	}
	formatted := value.FloatString(precision)
	if strings.Contains(formatted, ".") {
		formatted = strings.TrimRight(strings.TrimRight(formatted, "0"), ".")
	}
	if formatted == "-0" || formatted == "" {
		formatted = "0"
	}
	return json.Number(formatted)
}

func analyticsListLimit(raw string) uint32 {
	if raw == "" {
		return analyticsDefaultListLimit
	}
	parsed, err := strconv.ParseUint(raw, 10, 32)
	if err != nil || parsed == 0 || parsed > analyticsMaxListLimit {
		return analyticsDefaultListLimit
	}
	return uint32(parsed)
}

func analyticsRunningUser(raw string) (string, bool) {
	if raw == "" {
		return "viewer", true
	}
	return raw, raw == "viewer"
}
