"""C4 pose-estimator config block (AZ-355).

Registered into the global config registry via
``register_component_block("c4_pose", C4PoseConfig)`` on import of
``gps_denied_onboard.components.c4_pose``. The runtime root reads
``config.components["c4_pose"]`` and dispatches to the
``opencv_gtsam`` strategy (the only one defined; the Protocol exists
for ADR-009).
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Final

from gps_denied_onboard.config.schema import ConfigError

__all__ = ["KNOWN_POSE_STRATEGIES", "C4PoseConfig"]


KNOWN_POSE_STRATEGIES: Final[frozenset[str]] = frozenset({"opencv_gtsam"})


@dataclass(frozen=True)
class C4PoseConfig:
    """C4 pose-estimator config block.

    Fields per the C4 contract §"Config-load-time validation":

    * ``strategy`` — selects the concrete estimator. Currently only
      ``"opencv_gtsam"`` is defined.
    * ``ransac_iterations`` — OpenCV ``solvePnPRansac`` iteration
      budget. Default 200 per the contract.
    * ``ransac_reprojection_threshold_px`` — RANSAC inlier-distance
      threshold. Default 4.0 pixels per the contract.
    * ``thermal_throttle_threshold_celsius`` — informational only;
      the actual ``ThermalState.thermal_throttle_active`` decision is owned by C7
      (AZ-302). Default 75.0 °C.
    """

    strategy: str = "opencv_gtsam"
    ransac_iterations: int = 200
    ransac_reprojection_threshold_px: float = 4.0
    thermal_throttle_threshold_celsius: float = 75.0

    def __post_init__(self) -> None:
        if self.strategy not in KNOWN_POSE_STRATEGIES:
            raise ConfigError(
                f"C4PoseConfig.strategy={self.strategy!r} not in {sorted(KNOWN_POSE_STRATEGIES)}"
            )
        if self.ransac_iterations <= 0:
            raise ConfigError(
                f"C4PoseConfig.ransac_iterations must be > 0; got {self.ransac_iterations}"
            )
        if self.ransac_reprojection_threshold_px <= 0.0:
            raise ConfigError(
                "C4PoseConfig.ransac_reprojection_threshold_px must be > 0; "
                f"got {self.ransac_reprojection_threshold_px}"
            )
        if self.thermal_throttle_threshold_celsius <= 0.0:
            raise ConfigError(
                "C4PoseConfig.thermal_throttle_threshold_celsius must be > 0; "
                f"got {self.thermal_throttle_threshold_celsius}"
            )
