package collector

import (
	"bee/audit/internal/schema"
	"fmt"
	"time"
)

func BuildHealthSummary(snap schema.HardwareSnapshot) *schema.HardwareHealthSummary {
	summary := &schema.HardwareHealthSummary{
		Status:      statusOK,
		CollectedAt: time.Now().UTC().Format(time.RFC3339),
	}

	for _, dimm := range snap.Memory {
		switch derefString(dimm.Status) {
		case statusWarning:
			summary.MemoryWarn++
			summary.Warnings = append(summary.Warnings, formatMemorySummary(dimm))
		case statusCritical:
			summary.MemoryFail++
			summary.Failures = append(summary.Failures, formatMemorySummary(dimm))
		case statusEmpty:
			summary.EmptyDIMMs++
		}
	}

	for _, disk := range snap.Storage {
		switch derefString(disk.Status) {
		case statusWarning:
			summary.StorageWarn++
			summary.Warnings = append(summary.Warnings, formatStorageSummary(disk))
		case statusCritical:
			summary.StorageFail++
			summary.Failures = append(summary.Failures, formatStorageSummary(disk))
		}
	}

	for _, dev := range snap.PCIeDevices {
		switch derefString(dev.Status) {
		case statusWarning:
			summary.PCIeWarn++
			summary.Warnings = append(summary.Warnings, formatPCIeSummary(dev))
		case statusCritical:
			summary.PCIeFail++
			summary.Failures = append(summary.Failures, formatPCIeSummary(dev))
		}
	}

	for _, psu := range snap.PowerSupplies {
		if psu.Present != nil && !*psu.Present {
			summary.MissingPSUs++
		}
		switch derefString(psu.Status) {
		case statusWarning:
			summary.PSUWarn++
			summary.Warnings = append(summary.Warnings, formatPSUSummary(psu))
		case statusCritical:
			summary.PSUFail++
			summary.Failures = append(summary.Failures, formatPSUSummary(psu))
		}
	}

	if len(summary.Failures) > 0 || summary.StorageFail > 0 || summary.PCIeFail > 0 || summary.PSUFail > 0 || summary.MemoryFail > 0 {
		summary.Status = statusCritical
	} else if len(summary.Warnings) > 0 || summary.StorageWarn > 0 || summary.PCIeWarn > 0 || summary.PSUWarn > 0 || summary.MemoryWarn > 0 {
		summary.Status = statusWarning
	}

	if len(summary.Warnings) == 0 {
		summary.Warnings = nil
	}
	if len(summary.Failures) == 0 {
		summary.Failures = nil
	}

	return summary
}

func derefString(value *string) string {
	if value == nil {
		return ""
	}
	return *value
}

func preferredName(model, serial, slot *string) string {
	switch {
	case model != nil && *model != "":
		return *model
	case serial != nil && *serial != "":
		return *serial
	case slot != nil && *slot != "":
		return *slot
	default:
		return "unknown"
	}
}

func formatStorageSummary(disk schema.HardwareStorage) string {
	return fmt.Sprintf("storage %s status=%s", preferredName(disk.Model, disk.SerialNumber, disk.Slot), derefString(disk.Status))
}

func formatPCIeSummary(dev schema.HardwarePCIeDevice) string {
	return fmt.Sprintf("pcie %s status=%s", preferredName(dev.Model, dev.SerialNumber, dev.BDF), derefString(dev.Status))
}

func formatPSUSummary(psu schema.HardwarePowerSupply) string {
	return fmt.Sprintf("psu %s status=%s", preferredName(psu.Model, psu.SerialNumber, psu.Slot), derefString(psu.Status))
}

func formatMemorySummary(dimm schema.HardwareMemory) string {
	return fmt.Sprintf("memory %s status=%s", preferredName(dimm.PartNumber, dimm.SerialNumber, dimm.Slot), derefString(dimm.Status))
}
