package collector

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

func enrichPSUsWithTelemetry(psus []schema.HardwarePowerSupply, doc sensorsDoc) []schema.HardwarePowerSupply {
	if len(psus) == 0 || len(doc) == 0 {
		return psus
	}

	tempBySlot := psuTempsFromSensors(doc)
	healthBySlot := psuHealthFromSensors(doc)
	for i := range psus {
		slot := derefPSUSlot(psus[i].Slot)
		if slot == "" {
			continue
		}
		if psus[i].TemperatureC == nil {
			if value, ok := tempBySlot[slot]; ok {
				psus[i].TemperatureC = &value
			}
		}
		if psus[i].LifeRemainingPct == nil {
			if value, ok := healthBySlot[slot]; ok {
				psus[i].LifeRemainingPct = &value
				used := 100 - value
				psus[i].LifeUsedPct = &used
			}
		}
	}
	return psus
}

func psuHealthFromSensors(doc sensorsDoc) map[string]float64 {
	out := map[string]float64{}
	for chip, features := range doc {
		for featureName, raw := range features {
			feature, ok := raw.(map[string]any)
			if !ok {
				continue
			}
			if !isLikelyPSUHealth(chip, featureName) {
				continue
			}
			value, ok := firstFeaturePercent(feature)
			if !ok {
				continue
			}
			if slot, ok := detectPSUSlot(chip, featureName); ok {
				if _, exists := out[slot]; !exists {
					out[slot] = value
				}
			}
		}
	}
	return out
}

func firstFeaturePercent(feature map[string]any) (float64, bool) {
	keys := sortedFeatureKeys(feature)
	for _, key := range keys {
		lower := strings.ToLower(key)
		if strings.HasSuffix(lower, "_alarm") {
			continue
		}
		if strings.Contains(lower, "health") || strings.Contains(lower, "life") || strings.Contains(lower, "remain") {
			if value, ok := floatFromAny(feature[key]); ok {
				return value, true
			}
		}
	}
	return 0, false
}

func isLikelyPSUHealth(chip, feature string) bool {
	value := strings.ToLower(chip + " " + feature)
	return (strings.Contains(value, "psu") || strings.Contains(value, "power supply")) &&
		(strings.Contains(value, "health") || strings.Contains(value, "life") || strings.Contains(value, "remain"))
}

func psuTempsFromSensors(doc sensorsDoc) map[string]float64 {
	out := map[string]float64{}
	for chip, features := range doc {
		for featureName, raw := range features {
			feature, ok := raw.(map[string]any)
			if !ok || classifySensorFeature(feature) != "temp" {
				continue
			}
			if !isLikelyPSUTemp(chip, featureName) {
				continue
			}
			temp, ok := firstFeatureFloat(feature, "_input")
			if !ok {
				continue
			}
			if slot, ok := detectPSUSlot(chip, featureName); ok {
				if _, exists := out[slot]; !exists {
					out[slot] = temp
				}
			}
		}
	}
	return out
}

func isLikelyPSUTemp(chip, feature string) bool {
	value := strings.ToLower(chip + " " + feature)
	return strings.Contains(value, "psu") || strings.Contains(value, "power supply")
}

func detectPSUSlot(parts ...string) (string, bool) {
	for _, part := range parts {
		if value, ok := parsePSUSlot(part); ok && value > 0 {
			return strconv.Itoa(value - 1), true
		}
	}
	return "", false
}
