// Percentile grading bands, ported EXACTLY from backend/data/grading.py —
// the cross-repo display contract both this domain's CLAUDE.md and the
// backend's call out. The backend is the source of truth for the tier names
// and thresholds; an off-by-one on any boundary paints a tier a different
// colour than the label the API returned. A test in bands_test.go re-parses
// the backend's grading.py (when the monorepo checkout is present) and
// asserts these tables have not drifted.
package format

// Band is one percentile tier: Threshold is the tier's LOWER bound; a tier
// spans [lower, next-lower) — lower-inclusive, upper-exclusive — except the
// TOP tier, which is strict (pct > threshold): see BandFor.
type Band struct {
	Threshold float64
	Label     string
	Class     string
}

// TempBands maps a percentile to (grade label, css class) for temperature.
// Higher percentile = warmer. 9 symmetric tiers around the middle 40-60%
// "Normal", escalating to "Near Record" at both edges. Boundaries sit on
// multiples of 5 (plus the 1/99 record edges). Source of truth:
// backend/data/grading.py TEMP_BANDS.
var TempBands = []Band{
	{99, "Near Record", "rec-hot"}, // >99   extreme high (danger)
	{90, "Very High", "very-hot"},  // 90-99
	{75, "High", "hot"},            // 75-90
	{60, "Above Normal", "warm"},   // 60-75
	{40, "Normal", "normal"},       // 40-60 (the middle)
	{25, "Below Normal", "cool"},   // 25-40
	{10, "Low", "cold"},            // 10-25
	{1, "Very Low", "very-cold"},   // 1-10
	{0, "Near Record", "rec-cold"}, // <1    extreme low (danger)
}

// RainBands grades precipitation among days with ANY rain (> 0) in the
// seasonal window — a "rain percentile". Rain is one-directional (heavier =
// more extreme), so these 8 tiers are sequential light->heavy, using the SAME
// cut points as temperature. Dry days (no rain at all) are handled separately
// (the "dry" class, colored by dry streak in the UI). Same [lower, upper)
// convention as TempBands. The eight tiers fill the wet-2..wet-9 colour ramp
// with no gap. Source of truth: backend/data/grading.py RAIN_BANDS.
var RainBands = []Band{
	{99, "Extreme", "wet-9"},    // >99   heaviest rain for the season (darkest)
	{95, "Severe", "wet-8"},     // 95-99  (top half of the old Very Heavy)
	{90, "Very Heavy", "wet-7"}, // 90-95  (lower half)
	{60, "Heavy", "wet-6"},      // 60-90
	{40, "Typical", "wet-5"},    // 40-60
	{25, "Brisk", "wet-4"},      // 25-40
	{10, "Light", "wet-3"},      // 10-25
	{0, "Trace", "wet-2"},       // <10    the lightest measurable rain
}

// BandFor places a percentile on a band table — the port of grading.py's
// _band. The top tier is strict (pct > its threshold): "Near Record" high
// means strictly beyond the 99th percentile — the top <1% — mirroring the
// strictly-below-1st bottom tier (its lower neighbor already catches
// pct >= 1). Everything in between stays lower-inclusive, upper-exclusive.
func BandFor(pct float64, bands []Band) (label, class string) {
	top := bands[0]
	if pct > top.Threshold {
		return top.Label, top.Class
	}
	for _, b := range bands[1:] {
		if pct >= b.Threshold {
			return b.Label, b.Class
		}
	}
	last := bands[len(bands)-1]
	return last.Label, last.Class
}
