package platform

import "time"

// BenchmarkHostConfig holds static CPU and memory configuration captured at
// benchmark start. Useful for correlating results across runs on different hardware.
type BenchmarkHostConfig struct {
	CPUModel    string  `json:"cpu_model,omitempty"`
	CPUSockets  int     `json:"cpu_sockets,omitempty"`
	CPUCores    int     `json:"cpu_cores,omitempty"`
	CPUThreads  int     `json:"cpu_threads,omitempty"`
	MemTotalGiB float64 `json:"mem_total_gib,omitempty"`
}

// BenchmarkCPULoad summarises host CPU utilisation sampled during the GPU
// steady-state phase. High or unstable CPU load during a GPU benchmark may
// indicate a competing workload or a CPU-bound driver bottleneck.
type BenchmarkCPULoad struct {
	AvgPct  float64 `json:"avg_pct"`
	MaxPct  float64 `json:"max_pct"`
	P95Pct  float64 `json:"p95_pct"`
	Samples int     `json:"samples"`
	// Status is "ok", "high", or "unstable".
	Status string `json:"status"`
	Note   string `json:"note,omitempty"`
}

// BenchmarkCoolingSummary captures fan telemetry averaged across the full
// benchmark run.
type BenchmarkCoolingSummary struct {
	Available             bool     `json:"available"`
	AvgFanRPM             float64  `json:"avg_fan_rpm,omitempty"`
	FanDutyCycleAvailable bool     `json:"fan_duty_cycle_available,omitempty"`
	AvgFanDutyCyclePct    float64  `json:"avg_fan_duty_cycle_pct,omitempty"`
	P95FanDutyCyclePct    float64  `json:"p95_fan_duty_cycle_pct,omitempty"`
	Notes                 []string `json:"notes,omitempty"`
}

const (
	NvidiaBenchmarkProfileStandard  = "standard"
	NvidiaBenchmarkProfileStability = "stability"
	NvidiaBenchmarkProfileOvernight = "overnight"
)

type NvidiaBenchmarkOptions struct {
	Profile           string
	SizeMB            int
	GPUIndices        []int
	ExcludeGPUIndices []int
	RunNCCL           bool
	ParallelGPUs      bool   // run all selected GPUs simultaneously instead of sequentially
	RampStep          int    // 1-based step index within a ramp-up run (0 = not a ramp-up)
	RampTotal         int    // total number of ramp-up steps in this run
	RampRunID         string // shared identifier across all steps of the same ramp-up run
}

type NvidiaBenchmarkResult struct {
	BenchmarkVersion   string                       `json:"benchmark_version"`
	GeneratedAt        time.Time                    `json:"generated_at"`
	Hostname           string                       `json:"hostname,omitempty"`
	ServerModel        string                       `json:"server_model,omitempty"`
	BenchmarkProfile   string                       `json:"benchmark_profile"`
	ParallelGPUs       bool                         `json:"parallel_gpus,omitempty"`
	RampStep           int                          `json:"ramp_step,omitempty"`
	RampTotal          int                          `json:"ramp_total,omitempty"`
	RampRunID          string                       `json:"ramp_run_id,omitempty"`
	ScalabilityScore   float64                      `json:"scalability_score,omitempty"`
	// PlatformPowerScore is the mean compute scalability across ramp steps 2..N.
	// 100% = each added GPU contributes exactly its single-card throughput.
	// < 100% = throughput loss due to thermal throttle, power limits, or contention.
	PlatformPowerScore   float64                    `json:"platform_power_score,omitempty"`
	PerformanceRampSteps []NvidiaPerformanceRampStep `json:"performance_ramp_steps,omitempty"`
	OverallStatus      string                       `json:"overall_status"`
	SelectedGPUIndices []int                        `json:"selected_gpu_indices"`
	Findings           []string                     `json:"findings,omitempty"`
	Warnings           []string                     `json:"warnings,omitempty"`
	Normalization      BenchmarkNormalization       `json:"normalization"`
	HostConfig         *BenchmarkHostConfig         `json:"host_config,omitempty"`
	CPULoad            *BenchmarkCPULoad            `json:"cpu_load,omitempty"`
	Cooling            *BenchmarkCoolingSummary     `json:"cooling,omitempty"`
	GPUs               []BenchmarkGPUResult         `json:"gpus"`
	Interconnect       *BenchmarkInterconnectResult `json:"interconnect,omitempty"`
	ServerPower        *BenchmarkServerPower        `json:"server_power,omitempty"`
}

type BenchmarkNormalization struct {
	Status string                      `json:"status"`
	Notes  []string                    `json:"notes,omitempty"`
	GPUs   []BenchmarkNormalizationGPU `json:"gpus,omitempty"`
}

type BenchmarkNormalizationGPU struct {
	Index                 int      `json:"index"`
	PersistenceMode       string   `json:"persistence_mode,omitempty"`
	GPUClockLockMHz       float64  `json:"gpu_clock_lock_mhz,omitempty"`
	GPUClockLockStatus    string   `json:"gpu_clock_lock_status,omitempty"`
	MemoryClockLockMHz    float64  `json:"memory_clock_lock_mhz,omitempty"`
	MemoryClockLockStatus string   `json:"memory_clock_lock_status,omitempty"`
	Notes                 []string `json:"notes,omitempty"`
}

type BenchmarkGPUResult struct {
	Index               int     `json:"index"`
	UUID                string  `json:"uuid,omitempty"`
	Name                string  `json:"name,omitempty"`
	BusID               string  `json:"bus_id,omitempty"`
	VBIOS               string  `json:"vbios,omitempty"`
	ComputeCapability   string  `json:"compute_capability,omitempty"`
	Backend             string  `json:"backend,omitempty"`
	Status              string  `json:"status"`
	PowerLimitW         float64 `json:"power_limit_w,omitempty"`
	PowerLimitDerated   bool    `json:"power_limit_derated,omitempty"`
	MultiprocessorCount int     `json:"multiprocessor_count,omitempty"`
	DefaultPowerLimitW  float64 `json:"default_power_limit_w,omitempty"`
	// CalibratedPeakPowerW is the p95 power measured during a short
	// dcgmi targeted_power calibration run before the main benchmark.
	// Used as the reference denominator for PowerSustainScore instead of
	// the hardware default limit, which bee-gpu-burn cannot reach.
	CalibratedPeakPowerW   float64                         `json:"calibrated_peak_power_w,omitempty"`
	CalibratedPeakTempC    float64                         `json:"calibrated_peak_temp_c,omitempty"`
	PowerCalibrationTries  int                             `json:"power_calibration_tries,omitempty"`
	MaxGraphicsClockMHz    float64                         `json:"max_graphics_clock_mhz,omitempty"`
	BaseGraphicsClockMHz   float64                         `json:"base_graphics_clock_mhz,omitempty"`
	MaxMemoryClockMHz      float64                         `json:"max_memory_clock_mhz,omitempty"`
	LockedGraphicsClockMHz float64                         `json:"locked_graphics_clock_mhz,omitempty"`
	LockedMemoryClockMHz   float64                         `json:"locked_memory_clock_mhz,omitempty"`
	Baseline               BenchmarkTelemetrySummary       `json:"baseline"`
	Steady                 BenchmarkTelemetrySummary       `json:"steady"`
	PrecisionSteady        []BenchmarkPrecisionSteadyPhase `json:"precision_steady,omitempty"`
	PrecisionFailures      []string                        `json:"precision_failures,omitempty"`
	Cooldown               BenchmarkTelemetrySummary       `json:"cooldown"`
	Throttle               BenchmarkThrottleCounters       `json:"throttle_counters"`
	// ECC error delta accumulated over the full benchmark (all phases combined).
	ECC                BenchmarkECCCounters       `json:"ecc,omitempty"`
	PrecisionResults   []BenchmarkPrecisionResult `json:"precision_results,omitempty"`
	Scores             BenchmarkScorecard         `json:"scores"`
	DegradationReasons []string                   `json:"degradation_reasons,omitempty"`
	Notes              []string                   `json:"notes,omitempty"`
	// CoolingWarning is non-empty when a thermal throttle event occurred with
	// a clock drop ≥20% while server fans were not at 100% duty cycle.
	CoolingWarning string `json:"cooling_warning,omitempty"`
}

type BenchmarkTelemetrySummary struct {
	DurationSec         float64 `json:"duration_sec"`
	Samples             int     `json:"samples"`
	AvgTempC            float64 `json:"avg_temp_c"`
	P95TempC            float64 `json:"p95_temp_c"`
	AvgPowerW           float64 `json:"avg_power_w"`
	P95PowerW           float64 `json:"p95_power_w"`
	AvgGraphicsClockMHz float64 `json:"avg_graphics_clock_mhz"`
	P95GraphicsClockMHz float64 `json:"p95_graphics_clock_mhz"`
	AvgMemoryClockMHz   float64 `json:"avg_memory_clock_mhz"`
	P95MemoryClockMHz   float64 `json:"p95_memory_clock_mhz"`
	AvgUsagePct         float64 `json:"avg_usage_pct"`
	AvgMemUsagePct      float64 `json:"avg_mem_usage_pct"`
	ClockCVPct          float64 `json:"clock_cv_pct"`
	PowerCVPct          float64 `json:"power_cv_pct"`
	TempCVPct           float64 `json:"temp_cv_pct"`
	ClockDriftPct       float64 `json:"clock_drift_pct"`
}

type BenchmarkThrottleCounters struct {
	SWPowerCapUS           uint64 `json:"sw_power_cap_us"`
	SWThermalSlowdownUS    uint64 `json:"sw_thermal_slowdown_us"`
	SyncBoostUS            uint64 `json:"sync_boost_us"`
	HWThermalSlowdownUS    uint64 `json:"hw_thermal_slowdown_us"`
	HWPowerBrakeSlowdownUS uint64 `json:"hw_power_brake_slowdown_us"`
}

// BenchmarkECCCounters holds ECC error counts sampled at a point in time.
// Corrected = single-bit errors fixed by ECC (DRAM degradation).
// Uncorrected = double-bit errors that could not be corrected (serious fault).
// Both are volatile (since last driver reset), not persistent.
type BenchmarkECCCounters struct {
	Corrected   uint64 `json:"corrected"`
	Uncorrected uint64 `json:"uncorrected"`
}

func (e BenchmarkECCCounters) Total() uint64 { return e.Corrected + e.Uncorrected }
func (e BenchmarkECCCounters) IsZero() bool  { return e.Corrected == 0 && e.Uncorrected == 0 }

type BenchmarkPrecisionResult struct {
	Name          string  `json:"name"`
	Category      string  `json:"category"`
	Supported     bool    `json:"supported"`
	Lanes         int     `json:"lanes,omitempty"`
	M             uint64  `json:"m,omitempty"`
	N             uint64  `json:"n,omitempty"`
	K             uint64  `json:"k,omitempty"`
	Iterations    uint64  `json:"iterations,omitempty"`
	TeraOpsPerSec float64 `json:"teraops_per_sec,omitempty"`
	// Weight is the fp32-equivalence factor for this precision category.
	// fp32 = 1.0 (baseline), fp64 = 2.0, fp16 = 0.5, int8/fp8 = 0.25, fp4 = 0.125.
	// WeightedTOPS = TeraOpsPerSec * Weight gives fp32-equivalent throughput.
	Weight                float64 `json:"weight,omitempty"`
	WeightedTeraOpsPerSec float64 `json:"weighted_teraops_per_sec,omitempty"`
	Notes                 string  `json:"notes,omitempty"`
}

type BenchmarkScorecard struct {
	ComputeScore float64 `json:"compute_score"`
	// SyntheticScore is the sum of fp32-equivalent TOPS from per-precision
	// steady phases (each precision ran alone, full GPU dedicated).
	SyntheticScore float64 `json:"synthetic_score,omitempty"`
	// MixedScore is the sum of fp32-equivalent TOPS from the combined phase
	// (all precisions competing simultaneously — closer to real workloads).
	MixedScore float64 `json:"mixed_score,omitempty"`
	// MixedEfficiency = MixedScore / SyntheticScore. Measures how well the GPU
	// sustains throughput under concurrent mixed-precision load.
	MixedEfficiency     float64 `json:"mixed_efficiency,omitempty"`
	PowerSustainScore   float64 `json:"power_sustain_score"`
	ThermalSustainScore float64 `json:"thermal_sustain_score"`
	StabilityScore      float64 `json:"stability_score"`
	InterconnectScore   float64 `json:"interconnect_score"`
	CompositeScore      float64 `json:"composite_score"`
	// TOPSPerSMPerGHz is compute efficiency independent of clock speed and SM count.
	TOPSPerSMPerGHz float64 `json:"tops_per_sm_per_ghz,omitempty"`
}

// BenchmarkServerPower captures server-side power via IPMI alongside GPU-reported
// power. The reporting_ratio (delta / gpu_reported_sum) near 1.0 means GPU power
// telemetry is accurate; a ratio well below 1.0 (e.g. 0.5) means the GPU is
// over-reporting its power consumption.
type BenchmarkServerPower struct {
	Available       bool     `json:"available"`
	IdleW           float64  `json:"idle_w,omitempty"`
	LoadedW         float64  `json:"loaded_w,omitempty"`
	DeltaW          float64  `json:"delta_w,omitempty"`
	GPUReportedSumW float64  `json:"gpu_reported_sum_w,omitempty"`
	ReportingRatio  float64  `json:"reporting_ratio,omitempty"`
	Notes           []string `json:"notes,omitempty"`
}

// BenchmarkPrecisionSteadyPhase holds per-precision-category telemetry collected
// during a dedicated single-precision steady window.  Because only one kernel
// type runs at a time the PowerCVPct here is a genuine stability signal.
type BenchmarkPrecisionSteadyPhase struct {
	Precision             string                    `json:"precision"` // e.g. "fp8", "fp16", "fp32"
	Status                string                    `json:"status,omitempty"`
	Steady                BenchmarkTelemetrySummary `json:"steady"`
	TeraOpsPerSec         float64                   `json:"teraops_per_sec,omitempty"`
	WeightedTeraOpsPerSec float64                   `json:"weighted_teraops_per_sec,omitempty"`
	// ECC errors accumulated during this precision phase only.
	// Non-zero corrected = stress-induced DRAM errors for this kernel type.
	// Any uncorrected = serious fault triggered by this precision workload.
	ECC   BenchmarkECCCounters `json:"ecc,omitempty"`
	Notes string               `json:"notes,omitempty"`
}

type BenchmarkInterconnectResult struct {
	Status             string   `json:"status"`
	Attempted          bool     `json:"attempted"`
	Supported          bool     `json:"supported"`
	SelectedGPUIndices []int    `json:"selected_gpu_indices,omitempty"`
	AvgAlgBWGBps       float64  `json:"avg_algbw_gbps,omitempty"`
	MaxAlgBWGBps       float64  `json:"max_algbw_gbps,omitempty"`
	AvgBusBWGBps       float64  `json:"avg_busbw_gbps,omitempty"`
	MaxBusBWGBps       float64  `json:"max_busbw_gbps,omitempty"`
	Notes              []string `json:"notes,omitempty"`
}

type NvidiaPowerBenchResult struct {
	BenchmarkVersion     string                 `json:"benchmark_version"`
	GeneratedAt          time.Time              `json:"generated_at"`
	Hostname             string                 `json:"hostname,omitempty"`
	ServerModel          string                 `json:"server_model,omitempty"`
	BenchmarkProfile     string                 `json:"benchmark_profile"`
	SelectedGPUIndices   []int                  `json:"selected_gpu_indices"`
	RecommendedSlotOrder []int                  `json:"recommended_slot_order,omitempty"`
	RampSteps            []NvidiaPowerBenchStep `json:"ramp_steps,omitempty"`
	OverallStatus        string                 `json:"overall_status"`
	// PlatformMaxTDPW is the sum of per-GPU stable power limits found during the
	// cumulative thermal ramp. Represents the actual sustained power budget of
	// this server under full GPU load. Use for rack power planning.
	PlatformMaxTDPW float64  `json:"platform_max_tdp_w"`
	Findings        []string `json:"findings,omitempty"`
	GPUs            []NvidiaPowerBenchGPU `json:"gpus"`
}

type NvidiaPowerBenchGPU struct {
	Index               int      `json:"index"`
	Name                string   `json:"name,omitempty"`
	BusID               string   `json:"bus_id,omitempty"`
	DefaultPowerLimitW  float64  `json:"default_power_limit_w,omitempty"`
	// AppliedPowerLimitW is the stable limit found during single-card calibration.
	AppliedPowerLimitW  float64  `json:"applied_power_limit_w,omitempty"`
	// StablePowerLimitW is the final fixed limit for this GPU after the
	// cumulative thermal ramp. This is the limit at which the GPU operated
	// stably with all other GPUs running simultaneously at their own limits.
	// May be lower than AppliedPowerLimitW if multi-GPU thermal load required
	// additional derating.
	StablePowerLimitW   float64  `json:"stable_power_limit_w,omitempty"`
	MaxObservedPowerW   float64  `json:"max_observed_power_w,omitempty"`
	MaxObservedTempC    float64  `json:"max_observed_temp_c,omitempty"`
	CalibrationAttempts int      `json:"calibration_attempts,omitempty"`
	Derated             bool     `json:"derated,omitempty"`
	Status              string   `json:"status"`
	Notes               []string `json:"notes,omitempty"`
	// CoolingWarning mirrors BenchmarkGPUResult.CoolingWarning for the power workflow.
	CoolingWarning string `json:"cooling_warning,omitempty"`
}

type NvidiaPowerBenchStep struct {
	StepIndex           int      `json:"step_index"`
	GPUIndices          []int    `json:"gpu_indices"`
	// NewGPUIndex is the GPU whose stable limit was searched in this step.
	NewGPUIndex         int      `json:"new_gpu_index"`
	// NewGPUStableLimitW is the stable power limit found for the new GPU.
	NewGPUStableLimitW  float64  `json:"new_gpu_stable_limit_w,omitempty"`
	TotalObservedPowerW float64  `json:"total_observed_power_w,omitempty"`
	AvgObservedPowerW   float64  `json:"avg_observed_power_w,omitempty"`
	Derated             bool     `json:"derated,omitempty"`
	Status              string   `json:"status"`
	Notes               []string `json:"notes,omitempty"`
}

// NvidiaPerformanceRampStep holds per-step performance data for the
// scalability ramp-up phase of the performance benchmark.
type NvidiaPerformanceRampStep struct {
	StepIndex          int      `json:"step_index"`
	GPUIndices         []int    `json:"gpu_indices"`
	// TotalSyntheticTOPS is the sum of per-GPU SyntheticScore (fp32-equivalent
	// TOPS from dedicated single-precision phases) across all GPUs in this step.
	TotalSyntheticTOPS float64  `json:"total_synthetic_tops"`
	TotalMixedTOPS     float64  `json:"total_mixed_tops,omitempty"`
	// ScalabilityPct = TotalSyntheticTOPS / (k × best_single_gpu_tops) × 100.
	// 100% = perfect linear scaling. < 100% = thermal/power/interconnect loss.
	ScalabilityPct     float64  `json:"scalability_pct"`
	Status             string   `json:"status"`
	Notes              []string `json:"notes,omitempty"`
}
