"""Classify sensor values into three bands around (target, margin)

Auto mode derives target=mean, margin=1
"""

from __future__ import annotations

import math
from dataclasses import dataclass

BAND_IN = "in_range"
BAND_HIGH = "high"
BAND_LOW = "low"


@dataclass(frozen=True)
class ThresholdConfig:
    set_point: float = 149.0   # process target: used as band TARGET when auto=False
    margin: float = 1.0        # used as band MARGIN when auto=False
    auto: bool = True         # auto=True: target=frame mean, margin=frame 1σ

def resolve_bounds(values: list[float], cfg: ThresholdConfig) -> tuple[float, float]:
    if not cfg.auto:
        return cfg.set_point, cfg.margin
    clean = [v for v in values if not math.isnan(v)]
    if not clean:
        return cfg.set_point, cfg.margin
    mean = sum(clean) / len(clean)
    variance = sum((v - mean) ** 2 for v in clean) / len(clean)
    return mean, math.sqrt(variance)

def classify(value: float, target: float, margin: float) -> str:
    if math.isnan(value):
        return BAND_IN
    if value > target + margin:
        return BAND_HIGH
    if value < target - margin:
        return BAND_LOW
    return BAND_IN

def classify_all(values: list[float], cfg: ThresholdConfig) -> list[str]:
    target, margin = resolve_bounds(values, cfg)
    return [classify(v, target, margin)for v in values ]
