"""Statistical helpers for honest time-series backtest reporting."""

from __future__ import annotations

import math
import random
import statistics as stdlib_statistics
from collections.abc import Iterable


def _quantile(sorted_values: list[float], probability: float) -> float:
    position = (len(sorted_values) - 1) * probability
    lower = math.floor(position)
    upper = math.ceil(position)
    if lower == upper:
        return sorted_values[lower]
    fraction = position - lower
    return sorted_values[lower] * (1 - fraction) + sorted_values[upper] * fraction


def moving_block_bootstrap_ci(
    values: Iterable[float],
    *,
    block_size: int = 30,
    n_resamples: int = 1_000,
    confidence: float = 0.95,
    seed: int = 42,
) -> dict[str, float | int]:
    """Estimate a mean and CI while preserving local serial dependence."""
    series = [float(value) for value in values]
    if not series:
        raise ValueError("values must not be empty")
    if block_size < 1 or block_size > len(series):
        raise ValueError("block_size must be between 1 and the number of values")
    if n_resamples < 2:
        raise ValueError("n_resamples must be at least 2")
    if not 0 < confidence < 1:
        raise ValueError("confidence must be between 0 and 1")

    rng = random.Random(seed)
    sample_means: list[float] = []
    final_start = len(series) - block_size
    for _ in range(n_resamples):
        sample: list[float] = []
        while len(sample) < len(series):
            start = rng.randint(0, final_start)
            sample.extend(series[start:start + block_size])
        sample = sample[:len(series)]
        sample_means.append(sum(sample) / len(sample))

    sample_means.sort()
    tail = (1 - confidence) / 2
    return {
        "estimate": sum(series) / len(series),
        "ci_low": _quantile(sample_means, tail),
        "ci_high": _quantile(sample_means, 1 - tail),
        "n": len(series),
    }


def summarize_returns(
    values: Iterable[float],
    *,
    block_size: int = 30,
    n_resamples: int = 1_000,
    confidence: float = 0.95,
    seed: int = 42,
) -> dict[str, float | int]:
    """Summarize realized returns with an autocorrelation-aware mean CI."""
    series = [float(value) for value in values]
    interval = moving_block_bootstrap_ci(
        series,
        block_size=min(block_size, len(series)),
        n_resamples=n_resamples,
        confidence=confidence,
        seed=seed,
    )
    return {
        "n": len(series),
        "mean": round(float(interval["estimate"]), 2),
        "median": round(stdlib_statistics.median(series), 2),
        "win_rate": round(sum(value > 0 for value in series) / len(series) * 100, 1),
        "mean_ci_low": round(float(interval["ci_low"]), 2),
        "mean_ci_high": round(float(interval["ci_high"]), 2),
    }
