"""IIHS rating engine.

IIHS rates individual body regions as Good/Acceptable/Marginal/Poor.
The overall rating is determined by the worst sub-rating.
"""

from __future__ import annotations

from typing import Any

from impakt.criteria.base import CriterionResult
from impakt.protocol.base import BodyRegionScore, ProtocolResult, Rating


# Thresholds: (good_limit, acceptable_limit, marginal_limit)
# Values above marginal_limit = Poor
# higher_is_worse indicates that higher values are worse
IIHS_THRESHOLDS_2024: dict[str, tuple[float, float, float, bool]] = {
    "HIC15": (250.0, 500.0, 700.0, True),
    "Chest Deflection": (38.0, 50.0, 63.0, True),  # mm
    "Femur Load Left": (3.8, 6.2, 10.0, True),  # kN
    "Femur Load Right": (3.8, 6.2, 10.0, True),  # kN
    "Nij": (0.52, 0.78, 1.0, True),
    "Tibia Index": (0.5, 0.8, 1.3, True),
}

IIHS_THRESHOLDS: dict[str, dict[str, tuple[float, float, float, bool]]] = {
    "2024": IIHS_THRESHOLDS_2024,
}


def _rate_value(
    value: float,
    good_limit: float,
    acceptable_limit: float,
    marginal_limit: float,
    higher_is_worse: bool,
) -> Rating:
    """Rate a single value against IIHS thresholds."""
    if higher_is_worse:
        if value <= good_limit:
            return Rating.GOOD
        elif value <= acceptable_limit:
            return Rating.ACCEPTABLE
        elif value <= marginal_limit:
            return Rating.MARGINAL
        else:
            return Rating.POOR
    else:
        if value >= good_limit:
            return Rating.GOOD
        elif value >= acceptable_limit:
            return Rating.ACCEPTABLE
        elif value >= marginal_limit:
            return Rating.MARGINAL
        else:
            return Rating.POOR


RATING_ORDER = {
    Rating.GOOD: 0,
    Rating.ACCEPTABLE: 1,
    Rating.MARGINAL: 2,
    Rating.POOR: 3,
}


class IIHS:
    """IIHS evaluator."""

    def __init__(self, version: str = "2024") -> None:
        self._version = version
        if version not in IIHS_THRESHOLDS:
            raise ValueError(
                f"Unknown IIHS version: {version}. Available: {list(IIHS_THRESHOLDS.keys())}"
            )
        self._thresholds = IIHS_THRESHOLDS[version]

    @property
    def protocol_name(self) -> str:
        return "IIHS"

    @property
    def version(self) -> str:
        return self._version

    def evaluate(
        self,
        criteria: dict[str, CriterionResult],
    ) -> ProtocolResult:
        """Rate criteria against IIHS thresholds."""
        region_scores: list[BodyRegionScore] = []
        worst_rating = Rating.GOOD

        for criterion_name, (
            good,
            acceptable,
            marginal,
            higher_is_worse,
        ) in self._thresholds.items():
            result = criteria.get(criterion_name)
            if result is None:
                for key, res in criteria.items():
                    if (
                        criterion_name.lower() in key.lower()
                        or key.lower() in criterion_name.lower()
                    ):
                        result = res
                        break

            if result is None:
                continue

            rating = _rate_value(
                result.value,
                good,
                acceptable,
                marginal,
                higher_is_worse,
            )

            if RATING_ORDER[rating] > RATING_ORDER[worst_rating]:
                worst_rating = rating

            region_scores.append(
                BodyRegionScore(
                    region=result.body_region or criterion_name,
                    criterion=criterion_name,
                    value=result.value,
                    unit=result.unit,
                    rating=rating,
                )
            )

        return ProtocolResult(
            protocol=self.protocol_name,
            version=self._version,
            overall_rating=worst_rating.value.upper(),
            region_scores=region_scores,
            details={
                "worst_region": worst_rating.value,
            },
        )


def evaluate(
    criteria: dict[str, CriterionResult],
    version: str = "2024",
) -> ProtocolResult:
    """Convenience function for IIHS evaluation."""
    return IIHS(version=version).evaluate(criteria)
