"""Protocol contracts for the shared eval subsystem."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable


if TYPE_CHECKING:
    from .schemas import MetricPayload


@runtime_checkable
class ActionTrackerProtocol(Protocol):
    """Minimal tracker interface used by eval flows."""

    def update_status(self, step_code: str, status: str, description: str) -> Any:
        """Persist lifecycle status for a specific evaluation step."""
        ...

    def save_evaluation_results(self, payload: MetricPayload) -> Any:
        """Persist normalized evaluation payload records."""
        ...

    def log_error(self, file_path: str, module: str, message: str) -> Any:
        """Persist an evaluation error entry for observability."""
        ...


@runtime_checkable
class ModelLoaderProtocol(Protocol):
    """Runtime model loader callable contract."""

    def __call__(self, action_tracker: Any) -> Any:
        """Load and return a model artifact for the active runtime."""
        ...


@runtime_checkable
class InferenceRunnerProtocol(Protocol):
    """Inference runner callable contract.

    Runners usually return tuples like:
    - (predictions, outputs, targets) for classification
    - (outputs, targets) for detection/segmentation
    """

    def __call__(self, data_loader: Any, model: Any, *args: Any, **kwargs: Any) -> Any:
        """Run model inference over one split and return raw outputs."""
        ...


@runtime_checkable
class ResultFormatterProtocol(Protocol):
    """Result formatter callable contract."""

    def __call__(self, *args: Any, **kwargs: Any) -> MetricPayload:
        """Convert raw inference outputs into normalized payload records."""
        ...


@runtime_checkable
class SplitEvaluatorProtocol(Protocol):
    """Single split evaluator callable contract."""

    def __call__(self, split: str, loader: Any) -> MetricPayload:
        """Evaluate a specific split and return normalized metrics payload."""
        ...

