package main

// Drive is the normalized, vendor-agnostic health record for one physical
// drive. Nullable numeric fields use *int / *float64 so that "unknown" (the
// counter could not be read) is distinguishable from a real zero — this
// distinction drives the NO_DATA recommendation and keeps NO_DATA rows blank
// instead of misleadingly showing 0.
type Drive struct {
	CollectedAt string
	Hostname    string

	// Where/how smartctl reached the drive.
	DevicePath string
	Dtype      string
	Transport  string // Transport is the SCSI transport ("iSCSI", "SAS", ...); used to drop iSCSI LUNs.

	// Physical location reported by the RAID controller (if any).
	DeviceID  string // DeviceID is the megaraid,N index used by smartctl.
	Enclosure string
	Slot      string

	// Identity.
	Serial   string
	Model    string
	Firmware string
	Capacity string
	Rotation string // Rotation is "SSD", "NVMe", or "7200 rpm".

	SmartHealth string // PASSED | FAILED | PASSED_BY_ATTR | OK | UNKNOWN

	// Drive-attributable defect counters (nil = not readable).
	Reallocated       *int
	ReallocatedEvents *int
	Pending           *int
	Uncorrectable     *int
	ReportedUncorrect *int
	RuntimeBadBlocks  *int
	EndToEnd          *int
	UdmaCrc           *int

	// RAID controller signals (MegaCLI / storcli / perccli).
	MediaErrCtrl          int
	OtherErrCtrl          int
	PredictiveFailureCtrl int
	SmartAlertCtrl        bool
	FwState               string

	// Wear (vendor-normalized; remaining = % life left, consumed = 100 - that).
	WearPctRemaining *int
	WearPctWorst     *int
	WearPctConsumed  *int
	WearSrc          string
	UnusedReservePct *int
	HostWrittenTB    *float64

	// NVMe-specific health (from the NVMe SMART/Health log).
	NvmeCriticalWarning  *int
	NvmeAvailSpare       *int
	NvmeAvailSpareThresh *int
	NvmeMediaErrors      *int

	// Age.
	PowerOnHours    *int
	PowerOnYears    *float64
	PowerCycleCount *int
	TempC           *int

	// Derived.
	HaveSmart      bool
	DefectTotal    *int
	RiskScore      int
	Recommendation string
	RiskReasons    string

	// Diagnostics.
	SmartctlMessages string
}

// ---- Small pointer helpers ----

func pInt(n int) *int       { return &n }
func pF(f float64) *float64 { return &f }
func iv(p *int) int {
	if p == nil {
		return 0
	}
	return *p
}
