// Package tokenanalysis owns AgentTeam's local, opt-in Token diagnosis.
package tokenanalysis

import "time"

const (
	AnalysisSchemaVersion   = "agentteam-token-analysis/v2"
	ComparisonSchemaVersion = "agentteam-token-comparison/v2"

	StateAvailable   = "available"
	StateNoData      = "no_data"
	StateUnsupported = "unsupported"
	StateLimited     = "limited"
	StateDisabled    = "disabled"
)

// Request selects one bounded daemon-owned analysis.
type Request struct {
	Window     string             `json:"window"`
	AgentRef   string             `json:"agentRef,omitempty"`
	RunRef     string             `json:"runRef,omitempty"`
	Experiment ExperimentMetadata `json:"experiment"`
}

// Report is the local analysis wire contract. Display names and exact model
// values are removed by Portable before an artifact is written to disk.
type Report struct {
	SchemaVersion string            `json:"schemaVersion"`
	GeneratedAt   time.Time         `json:"generatedAt"`
	SnapshotAt    time.Time         `json:"snapshotAt"`
	Window        string            `json:"window"`
	Scope         AnalysisScope     `json:"scope"`
	Collection    CollectionStatus  `json:"collection"`
	Summary       UsageSummary      `json:"summary"`
	Agents        []AgentSummary    `json:"agents"`
	Runs          []RunSummary      `json:"runs"`
	Ledger        []BlockSummary    `json:"ledger"`
	Opportunities []Opportunity     `json:"opportunities"`
	DataQuality   DataQuality       `json:"dataQuality"`
	Comparability ComparabilityInfo `json:"comparability"`
	Fingerprint   string            `json:"fingerprint"`
}

type CollectionStatus struct {
	Enabled          bool `json:"enabled"`
	CallerCanControl bool `json:"callerCanControl"`
	AutoEnabled      bool `json:"autoEnabled,omitempty"`
	Stopped          bool `json:"stopped,omitempty"`
}

type AnalysisScope struct {
	Kind         string     `json:"kind"`
	RunState     string     `json:"runState"`
	RunStartedAt *time.Time `json:"runStartedAt,omitempty"`
}

// ExperimentMetadata declares the controlled dimensions supplied by the
// operator. Free-form case, Workspace, and tool values are hashed before they
// enter a report.
type ExperimentMetadata struct {
	Case            string `json:"case,omitempty"`
	ChangedVariable string `json:"changedVariable,omitempty"`
	Workspace       string `json:"workspace,omitempty"`
	Tools           string `json:"tools,omitempty"`
	CacheState      string `json:"cacheState,omitempty"`
	Outcome         string `json:"outcome,omitempty"`
}

type MetricValue struct {
	State string  `json:"state"`
	Value *uint64 `json:"value,omitempty"`
}

type UsageSummary struct {
	RuntimeInput                  uint64           `json:"runtimeInput"`
	RuntimeCacheRead              uint64           `json:"runtimeCacheRead"`
	RuntimeOutput                 uint64           `json:"runtimeOutput"`
	UsageEvents                   uint64           `json:"usageEvents"`
	RootModelInvocations          MetricValue      `json:"rootModelInvocations"`
	RootAverageInputPerInvocation MetricValue      `json:"rootAverageInputPerInvocation"`
	RootRuntimeInput              MetricValue      `json:"rootRuntimeInput"`
	UnattributedInput             MetricValue      `json:"unattributedInput"`
	CompiledMaterialized          MetricValue      `json:"compiledMaterialized"`
	ControllableMaterialized      MetricValue      `json:"controllableMaterialized"`
	ControllableExposure          MetricValue      `json:"controllableExposure"`
	RequiredPayload               MetricValue      `json:"requiredPayload"`
	ContextPartition              ContextPartition `json:"contextPartition"`
}

type ContextPartition struct {
	AgentTeamOwned         MetricValue `json:"agentteamOwned"`
	WorkspaceConfiguration MetricValue `json:"workspaceConfiguration"`
	UserTaskPayload        MetricValue `json:"userTaskPayload"`
	Unknown                MetricValue `json:"unknown"`
}

type AgentSummary struct {
	AgentRef    string `json:"agentRef"`
	DisplayName string `json:"displayName,omitempty"`
	Runtime     string `json:"runtime,omitempty"`
	Model       string `json:"model,omitempty"`
	Input       uint64 `json:"input"`
	CacheRead   uint64 `json:"cacheRead"`
	Output      uint64 `json:"output"`
}

type RunSummary struct {
	RunRef                      string      `json:"runRef"`
	AgentRef                    string      `json:"agentRef"`
	Kind                        string      `json:"kind"`
	Runtime                     string      `json:"runtime,omitempty"`
	Model                       string      `json:"model,omitempty"`
	Input                       uint64      `json:"input"`
	CacheRead                   uint64      `json:"cacheRead"`
	Output                      uint64      `json:"output"`
	UsageObservations           uint64      `json:"usageObservations"`
	StartedAt                   *time.Time  `json:"startedAt,omitempty"`
	ActiveAtSnapshot            bool        `json:"activeAtSnapshot"`
	ModelInvocations            MetricValue `json:"modelInvocations"`
	AverageInputPerInvocation   MetricValue `json:"averageInputPerInvocation"`
	CompiledMaterialized        MetricValue `json:"compiledMaterialized"`
	ControllableMaterialized    MetricValue `json:"controllableMaterialized"`
	ControllableExposure        MetricValue `json:"controllableExposure"`
	RequiredPayloadMaterialized MetricValue `json:"requiredPayloadMaterialized"`
}

// BlockSummary is a report-scope aggregate. Compiler estimates are neither
// provider counters nor billing truth.
type BlockSummary struct {
	BlockID              string   `json:"blockId"`
	DisplayName          string   `json:"displayName"`
	Origin               string   `json:"origin"`
	Control              string   `json:"control"`
	Lifetime             string   `json:"lifetime"`
	MeanWhenInjected     float64  `json:"meanWhenInjected"`
	InjectionCount       uint64   `json:"injectionCount"`
	InjectionCoverage    float64  `json:"injectionCoverage"`
	MaterializedEstimate uint64   `json:"materializedEstimate"`
	ExposureCount        uint64   `json:"exposureCount,omitempty"`
	ExposureEstimate     *uint64  `json:"exposureEstimate,omitempty"`
	ControllableExposure *uint64  `json:"controllableExposure,omitempty"`
	AddressableEstimate  *uint64  `json:"addressableEstimate,omitempty"`
	SuggestedAction      string   `json:"suggestedAction"`
	RequiredValidation   []string `json:"requiredValidation"`
}

type Opportunity struct {
	BlockID            string   `json:"blockId"`
	DisplayName        string   `json:"displayName"`
	Origin             string   `json:"origin"`
	Control            string   `json:"control"`
	Estimate           uint64   `json:"estimate"`
	Estimator          string   `json:"estimator"`
	SuggestedAction    string   `json:"suggestedAction"`
	RequiredValidation []string `json:"requiredValidation"`
}

type DataQuality struct {
	State       string   `json:"state"`
	Diagnostics []string `json:"diagnostics"`
	Scanned     int      `json:"scanned"`
	Limit       int      `json:"limit"`
	Truncated   bool     `json:"truncated"`
}

// ComparabilityInfo is deliberately minimal in v1. Empty fingerprints make a
// natural-traffic report descriptive instead of pretending to be an A/B run.
type ComparabilityInfo struct {
	CaseFingerprint        string `json:"caseFingerprint,omitempty"`
	RuntimeFingerprint     string `json:"runtimeFingerprint,omitempty"`
	BuildFingerprint       string `json:"buildFingerprint,omitempty"`
	WorkspaceFingerprint   string `json:"workspaceFingerprint,omitempty"`
	ToolFingerprint        string `json:"toolFingerprint,omitempty"`
	TaskPayloadFingerprint string `json:"taskPayloadFingerprint,omitempty"`
	ChangedVariable        string `json:"changedVariable,omitempty"`
	CacheState             string `json:"cacheState"`
	Outcome                string `json:"outcome"`
	ScopeFingerprint       string `json:"scopeFingerprint"`
}
