"""
threshold_band: map a numeric value into a score using ordered upper bounds.

params:
  value_key: str — key in inputs to read
  bands: list of { "max": float | null, "score": float } — ascending max; null = +inf

Missing value_key → normalized_score 0, missing_inputs lists value_key.
"""

from __future__ import annotations

from typing import Any, List, Mapping

from data_layer.training_profile.models import AlgorithmRunResult
from data_layer.utils import safe_float


ALGORITHM_ID = "threshold_band"


def threshold_band_score(
    *,
    inputs: Mapping[str, Any],
    params: Mapping[str, Any],
) -> AlgorithmRunResult:
    value_key = str(params.get("value_key", ""))
    if not value_key:
        return AlgorithmRunResult(
            raw_score=0.0,
            normalized_score=0.0,
            missing_inputs=["__param_value_key__"],
            detail={"error": "params.value_key required"},
        )

    if value_key not in inputs or inputs[value_key] is None:
        return AlgorithmRunResult(
            raw_score=0.0,
            normalized_score=0.0,
            missing_inputs=[value_key],
            detail={"value_key": value_key},
        )

    raw = safe_float(inputs[value_key])
    bands = params.get("bands") or []
    if not isinstance(bands, list) or not bands:
        return AlgorithmRunResult(
            raw_score=raw,
            normalized_score=0.0,
            missing_inputs=[],
            detail={"error": "params.bands must be a non-empty list", "raw": raw},
        )

    score = 0.0
    for band in bands:
        if not isinstance(band, dict):
            continue
        max_v = band.get("max")
        s = safe_float(band.get("score"))
        if max_v is None:
            score = s
            break
        if raw <= safe_float(max_v):
            score = s
            break
    else:
        score = safe_float(bands[-1].get("score")) if isinstance(bands[-1], dict) else 0.0

    norm = max(0.0, min(1.0, score))
    return AlgorithmRunResult(
        raw_score=raw,
        normalized_score=norm,
        missing_inputs=[],
        detail={"value_key": value_key, "bands_applied": True, "band_score": score},
    )
