package collector

import (
	"bee/audit/internal/schema"
	"strings"
)

func NormalizeSnapshot(snap *schema.HardwareSnapshot, collectedAt string) {
	finalizeSnapshot(snap, collectedAt)
}

func finalizeSnapshot(snap *schema.HardwareSnapshot, collectedAt string) {
	snap.Memory = filterMemory(snap.Memory)
	snap.Storage = filterStorage(snap.Storage)
	snap.PCIeDevices = filterPCIe(snap.PCIeDevices)
	snap.PowerSupplies = filterPSUs(snap.PowerSupplies)

	setComponentStatusMetadata(snap, collectedAt)
}

func filterMemory(dimms []schema.HardwareMemory) []schema.HardwareMemory {
	out := make([]schema.HardwareMemory, 0, len(dimms))
	for _, dimm := range dimms {
		if dimm.Present != nil && !*dimm.Present {
			continue
		}
		if dimm.Status != nil && *dimm.Status == statusEmpty {
			continue
		}
		if dimm.SerialNumber == nil || *dimm.SerialNumber == "" {
			continue
		}
		out = append(out, dimm)
	}
	return out
}

func filterStorage(disks []schema.HardwareStorage) []schema.HardwareStorage {
	out := make([]schema.HardwareStorage, 0, len(disks))
	for _, disk := range disks {
		if disk.SerialNumber == nil || *disk.SerialNumber == "" {
			continue
		}
		if disk.Model != nil && isVirtualHDiskModel(*disk.Model) {
			continue
		}
		out = append(out, disk)
	}
	return out
}

func filterPCIe(devs []schema.HardwarePCIeDevice) []schema.HardwarePCIeDevice {
	out := make([]schema.HardwarePCIeDevice, 0, len(devs))
	for _, dev := range devs {
		if dev.DeviceClass != nil && strings.Contains(strings.ToLower(strings.TrimSpace(*dev.DeviceClass)), "co-processor") {
			continue
		}
		out = append(out, dev)
	}
	return out
}

func filterPSUs(psus []schema.HardwarePowerSupply) []schema.HardwarePowerSupply {
	out := make([]schema.HardwarePowerSupply, 0, len(psus))
	for _, psu := range psus {
		hasIdentity := false
		switch {
		case psu.SerialNumber != nil && *psu.SerialNumber != "":
			hasIdentity = true
		case psu.Slot != nil && *psu.Slot != "":
			hasIdentity = true
		case psu.Model != nil && *psu.Model != "":
			hasIdentity = true
		case psu.Vendor != nil && *psu.Vendor != "":
			hasIdentity = true
		}
		if !hasIdentity {
			continue
		}
		out = append(out, psu)
	}
	return out
}

func setComponentStatusMetadata(snap *schema.HardwareSnapshot, collectedAt string) {
	for i := range snap.CPUs {
		setStatusCheckedAt(&snap.CPUs[i].HardwareComponentStatus, collectedAt)
	}
	for i := range snap.Memory {
		setStatusCheckedAt(&snap.Memory[i].HardwareComponentStatus, collectedAt)
	}
	for i := range snap.Storage {
		setStatusCheckedAt(&snap.Storage[i].HardwareComponentStatus, collectedAt)
	}
	for i := range snap.PCIeDevices {
		setStatusCheckedAt(&snap.PCIeDevices[i].HardwareComponentStatus, collectedAt)
	}
	for i := range snap.PowerSupplies {
		setStatusCheckedAt(&snap.PowerSupplies[i].HardwareComponentStatus, collectedAt)
	}
}

func setStatusCheckedAt(status *schema.HardwareComponentStatus, collectedAt string) {
	if status == nil || status.Status == nil || *status.Status == "" {
		return
	}
	if status.StatusCheckedAt == nil {
		status.StatusCheckedAt = &collectedAt
	}
}
