package models

import "time"

// Report structures
type ReportDefinition struct {
	ID                 string              `json:"id"`
	Name               string              `json:"name"`
	SourceObject       string              `json:"sourceObject"`
	ReportType         string              `json:"reportType"`
	ReportFormat       string              `json:"reportFormat"`
	// Scope is the "Show me" filter: "all" (no filter), "mine" (OwnerId = current user),
	// or "myTeam" (OwnerId in current user + role subordinates). Persisted in the
	// Report.Scope column. Case-insensitive on read; empty means "all".
	Scope              string              `json:"scope,omitempty"`
	Columns            []string            `json:"columns"`
	Filters            []ReportFilter      `json:"filters"`
	// BooleanFilter is the SF-style numbered boolean expression that
	// combines Filters (e.g. "1 OR 2 OR 3", "1 AND (2 OR 3)"). Empty string
	// means "AND all filters". Parsed at execution time and compiled into
	// a formula expression that drives QueryRequest.FilterExpr.
	BooleanFilter      string              `json:"booleanFilter,omitempty"`
	Grouping           []string            `json:"grouping"`
	Aggregates         []ReportAggregate   `json:"aggregates"`
	StandardDateFilter *StandardDateFilter `json:"standardDateFilter,omitempty"`
	// DegradeOnError controls whether the query retry logic may silently
	// drop SelectFields/Criteria on failure. When false (the default),
	// query errors are returned immediately. Dashboard components set
	// this to true so individual report failures don't break the whole
	// dashboard.
	DegradeOnError bool `json:"-"`
}

// StandardDateFilter represents a Salesforce report's date range filter.
type StandardDateFilter struct {
	Column        string `json:"column"`
	DurationValue string `json:"durationValue"`
	StartDate     string `json:"startDate"`
	EndDate       string `json:"endDate"`
}

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

type ReportAggregate struct {
	Field string `json:"field"`
	Type  string `json:"type"` // SUM, AVG, COUNT, etc.
}

type ReportResult struct {
	ReportMetadata ReportDefinition       `json:"reportMetadata"`
	FactMap        map[string]interface{} `json:"factMap"` // For summary/matrix (keys -> aggregates)
	Rows           []SObject              `json:"rows"`    // Tabular data or detail rows
	// TotalCount is the unpaginated row count from a separate COUNT(*) query.
	// Zero means "not computed" — the REST layer falls back to len(Rows).
	// Needed because Rows is capped by the execution limit (default 2000) and
	// the SF-compatible factMap.aggregates[RowCount] is supposed to reflect
	// the true total, not the display cap.
	TotalCount int `json:"totalCount,omitempty"`
	// AggregateDedupColumn tells the handler's aggregate computation which
	// row key to dedupe on when summing a given aggregate field. Salesforce
	// computes SUM/AVG/MIN/MAX over primary-entity fields by deduping the
	// JOIN fan-out against the primary entity's Id; without that dedup the
	// same opportunity gets summed once per converted lead. Key = canonical
	// aggregate field name (e.g. "AMOUNT"); value = SObject row key that
	// holds the dedup id (e.g. "__primary_id__"). Absent entries mean the
	// aggregate is summed across raw rows (joined-entity fields, counts).
	AggregateDedupColumn map[string]string `json:"aggregateDedupColumn,omitempty"`
	// Warnings carries structured degradation notices produced by the CRT
	// resolver/synthesizer (design §4.11). The REST layer copies these into
	// reportExtendedMetadata.warnings on the wire. Nil or empty means no
	// degradation occurred.
	Warnings []CRTWarning `json:"warnings,omitempty"`
}

// CRTWarningCode is the closed set of structured warning codes emitted when
// a Custom Report Type is degraded rather than fully resolved. Lives in the
// models package so ReportResult can reference it without importing the
// analytics feature package (which would be an import cycle).
type CRTWarningCode string

// CRTWarning is the structured degradation notice emitted by the CRT
// synthesizer/resolver. See docs/design/crt-report-support.md §4.11.
type CRTWarning struct {
	Code         CRTWarningCode `json:"code"`
	Message      string         `json:"message"`
	SourceObject string         `json:"sourceObject,omitempty"`
}

// Dashboard structures - Salesforce wire format
type DashboardDefinition struct {
	ID            string                `json:"id"`
	Name          string                `json:"name"`
	DeveloperName string                `json:"developerName"`
	Description   string                `json:"description"`
	LayoutType    string                `json:"layoutType"`
	DashboardType string                `json:"dashboardType,omitempty"`
	RunningUserId string                `json:"runningUserId,omitempty"`
	Components    []ComponentDefinition `json:"components"`
}

type ComponentDefinition struct {
	ID       string                 `json:"id"`
	ReportID string                 `json:"reportId"`
	Type     string                 `json:"type"`
	Title    string                 `json:"title"`
	Config   map[string]interface{} `json:"config"` // Layout info (x,y,w,h)
}

// DashboardResult - Salesforce wire format
type DashboardResult struct {
	DashboardMetadata DashboardDefinition      `json:"dashboardMetadata"`
	ComponentData     map[string]*ReportResult `json:"componentData"` // Keyed by Component ID
	GeneratedAt       time.Time                `json:"generatedAt"`
}
