from __future__ import annotations

import json
import logging
from pathlib import Path
from typing import Mapping

from verifiers.types import GenerateOutputs

from medarc_verifiers.cli.utils.json_io import write_json

logger = logging.getLogger(__name__)


def log_results_summary(
    *,
    results: GenerateOutputs,
    env_slug: str,
    judge_name: str,
    stage: str,
    reward_limit: int = 25,
) -> None:
    """Emit a concise summary of rewards and key metrics for a run."""
    _ = reward_limit  # Legacy arg kept for API compatibility.
    metadata = _safe_get(results, "metadata", {}) or {}
    avg_reward = _safe_get(metadata, "avg_reward", None)
    avg_metrics = _safe_get(metadata, "avg_metrics", {}) or {}
    rollouts = _safe_get(metadata, "rollouts_per_example", None)
    examples = _safe_get(metadata, "num_examples", None)

    if avg_reward is None:
        logger.info(
            "[%s] %s / %s: examples=%s, rollouts_per_example=%s",
            stage,
            env_slug,
            judge_name,
            examples,
            rollouts,
        )
    else:
        logger.info(
            "[%s] %s / %s: avg_reward=%.4f, examples=%s, rollouts_per_example=%s",
            stage,
            env_slug,
            judge_name,
            float(avg_reward),
            examples,
            rollouts,
        )

    pass_rate = _safe_get(avg_metrics, "pass_rate", None)
    if pass_rate is not None:
        try:
            logger.info("  pass_rate avg: %.4f", float(pass_rate))
        except (TypeError, ValueError):
            logger.debug("Skipping pass_rate logging due to non-numeric value: %r", pass_rate)


def update_metadata_file(path: Path, avg_reward: float | None, metrics_avg: Mapping[str, float]) -> None:
    """Patch persisted metadata with up-to-date averages if the file exists."""
    if not path.exists():
        return
    try:
        with path.open("r", encoding="utf-8") as handle:
            payload = json.load(handle)
    except (OSError, ValueError):
        return

    changed = False
    if avg_reward is not None and payload.get("avg_reward") != avg_reward:
        payload["avg_reward"] = avg_reward
        changed = True
    if metrics_avg:
        current_metrics = payload.get("avg_metrics")
        if current_metrics != metrics_avg:
            payload["avg_metrics"] = metrics_avg
            changed = True
    if changed:
        write_json(path, payload)


def _safe_get(obj: object, key: str, default: object = None) -> object:
    if isinstance(obj, dict):
        return obj.get(key, default)
    return getattr(obj, key, default)
