"""Multi-run aggregation for benchmark metrics."""

from __future__ import annotations

import logging
import math
from collections.abc import Sequence

from sage_evaluator.models import ModelRunResult, ModelRunStats

logger = logging.getLogger(__name__)


class MetricsCollector:
    """Aggregates metrics across multiple runs of the same model."""

    @staticmethod
    def aggregate(model: str, results: list[ModelRunResult]) -> ModelRunStats:
        """Compute mean and standard deviation across multiple runs.

        Args:
            model: Model identifier.
            results: List of individual run results.

        Returns:
            Aggregated ModelRunStats.
        """
        if not results:
            return ModelRunStats(model=model)

        n = len(results)
        successful = [r for r in results if r.success]
        success_rate = len(successful) / n if n > 0 else 0.0
        logger.info(
            "Aggregating %d run(s) for model %s (%.0f%% success rate)",
            n,
            model,
            success_rate * 100,
        )

        prompt_tokens = [r.prompt_tokens for r in results]
        completion_tokens = [r.completion_tokens for r in results]
        total_tokens = [r.total_tokens for r in results]
        latencies = [r.latency_ms for r in results]
        tool_call_counts = [len(r.tool_calls) for r in results]

        return ModelRunStats(
            model=model,
            runs=n,
            mean_prompt_tokens=_mean(prompt_tokens),
            mean_completion_tokens=_mean(completion_tokens),
            mean_total_tokens=_mean(total_tokens),
            stdev_total_tokens=_stdev(total_tokens),
            mean_latency_ms=_mean(latencies),
            stdev_latency_ms=_stdev(latencies),
            success_rate=success_rate,
            mean_tool_calls=_mean(tool_call_counts),
        )


def _mean(values: Sequence[int | float]) -> float:
    """Compute mean of a list of numbers."""
    if not values:
        return 0.0
    return sum(values) / len(values)


def _stdev(values: Sequence[int | float]) -> float:
    """Compute population standard deviation."""
    if len(values) < 2:
        return 0.0
    avg = _mean(values)
    variance = sum((x - avg) ** 2 for x in values) / len(values)
    return math.sqrt(variance)
