#!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
from pathlib import Path
from typing import Any, Dict, List

import numpy as np

from forecast_diagnostics import diebold_mariano_squared_error, rolling_mean_forecast


def simulate_sprints(
    *,
    T: int = 100,
    seed: int = 123,
) -> List[Dict[str, Any]]:
    """
    Synthetic simulation used to demonstrate the forecast-accuracy pipeline.

    This is NOT meant to claim any particular performance; it's a runnable example
    that produces a time series of:
      - realised outcome (actual)
      - model forecast (sc_forecast)

    The generator is intentionally self-contained and does not depend on the
    `sprint_forecast` package internals.
    """
    rng = np.random.default_rng(seed)

    series: List[Dict[str, Any]] = []
    for t in range(T):
        # Latent "true" level follows a slow random walk with occasional shocks.
        level = 100.0 + 0.35 * t + rng.normal(0.0, 3.0)
        if rng.random() < 0.10:
            level *= rng.uniform(0.85, 0.95)

        # "Actual" outcome is noisy around the latent level.
        realised = float(level + rng.normal(0.0, 8.0))

        # "SC forecast" is a partially informed predictor.
        sc_forecast = float(level + rng.normal(0.0, 4.0))
        series.append({
            "sprint": t + 1,
            "actual": realised,
            "sc_forecast": sc_forecast,
        })

    return series


def main() -> None:
    ap = argparse.ArgumentParser(description="Generate synthetic sprint series and run DM test.")
    ap.add_argument("--T", type=int, default=100)
    ap.add_argument("--seed", type=int, default=123)
    ap.add_argument("--window", type=int, default=5)
    ap.add_argument("--out", default="synthetic_history.json")
    args = ap.parse_args()

    series = simulate_sprints(T=args.T, seed=args.seed)
    Path(args.out).write_text(json.dumps(series, indent=2), encoding="utf-8")

    actual = np.asarray([x["actual"] for x in series], dtype=float)
    sc = np.asarray([x["sc_forecast"] for x in series], dtype=float)

    idx, rm = rolling_mean_forecast(actual, window=args.window)
    dm = diebold_mariano_squared_error(actual[idx], forecast_sc=sc[idx], forecast_rm=rm)

    print(f"Wrote {args.out}")
    print("DM test:", dm.to_json())


if __name__ == "__main__":
    main()
